JAVA学习笔记:JPA映射关系
1. 单向多对一
映射配置:
// 多对一,懒加载
@ManyToOne(fetch = FetchType.LAZY)
// 多方的外键id
@JoinColumn(name = “xxx_id”)
注意:一方不要实例化
保存时,先保存一方,再保存多方
2. 单向一对多
映射配置:
// 一对多,默认懒加载,最好是写出来
@OneToMany(fetch = FetchType.LAZY)
// 多方的外键id
@JoinColumn(name = “xxx_id”)
集合最好是实例化出来,否则很容易空指针异常
保存时,先保存一方,再保存多方
3. 集合映射
List:有序,可重复,一般用在组合关系
Set:无序,不可重复,一般用在多对多,也有一对多
在声明集合的时候,一定要使用接口
Set products = new HashSet<>();
List products = new ArrayList<>();
因为Hibernate在创建了集合对象后是使用了它的的集合类PersistentSet/PersistentBag来接收数据的,而不是HashSet/ArrayList。如果我们使用接口声明(Set/List),那么它的集合类PersistentSet/PersistentBag也是实现了这个接口。所以它可以把这个类赋给Set/List。 但是我们使用HashSet/ArrayList,它们关系是平级的,不能进行转换,所以就会出现错误了。
4. 双向多对一、一对多
双向,其实就相当于配置两个单向
- 在java代码中让多方来维护关系(性能高),类似于单向多对一
- 在java 代码中让一方来维护关系(性能低-如下面的代码),类似于单向一对多。
4.1 映射配置
映射配置(一方):
@Entity
public class ProductDir {
@Id
@GeneratedValue
private Long id;
private String name;
// 一对多,一方的关系参照多方Prodcut属性dir来管理
@OneToMany( mappedBy = "dir")
// 建议实例化
private Set<Product2> products = new HashSet<Product2>();
}
映射配置(多方):
@Entity
public class Product {
@Id
@GeneratedValue
private Long id;
private String name;
// 多对一,懒加载
@ManyToOne(fetch = FetchType.LAZY) // 实现延迟加载
// 配置外键列名
@JoinColumn(name = "dir_id")
private ProductDir dir;
}
4.2 级联保存、删除、孤儿删除
只调用一次persist方法,通过保存一方,把与之相关联的多方一并保存
映射配置(一方):
在@OneToMany中配置属性cascade = CascadeType.PERSIST
级联删除配置cascade = CascadeType.REMOVE
cascade = CascadeType.ALL既支持级联保存,又支持级联删除,不过比较危险,容易误操作造成数据被删除。
孤儿删除:
在一方的@OneToMany中配置属性orphanRemoval = true,可以删除与该一方失去关系的多方,而不删除一方本身。
5. 单向多对多
多对多会额外建一张中间表来保存多对多的关系
保存数据随意先保存哪个多方都行
映射配置:
// 多对多,懒加载
@ManyToMany(fetch = FetchType.LAZY)
// 配置中间表的属性,表名,在中间表的列名,另一个多方在中间表中的列名
@JoinTable(name = "t_teacher_student", joinColumns = @JoinColumn(name = "teacher_id"), inverseJoinColumns = @JoinColumn(name = "student_id"))
private List<Student> students = new ArrayList<>();
6. 双向多对多
- 映射配置和单向多对多一样,在两个多方都配置就行,但是配置的中间表表名,和对应的列名必须一致。
- 可以配置级联保存,保存一个多方同时保存另一个多方
- 删除,直接常规删除就行,如
entityManager.remove(student);
student.getTeachers().remove(teacher);等 - 请勿配置级联删除或者CascadeType.ALL(危险操作),
比如配置了学生这边级联删除,删除一个学生,会先删除中间表与该学生相关的关系,再该学生和该学生相关的老师;
如果学生和老师都配置了级联删除,删除一个学生,会删除该学生的老师,然后删除该学生的老师的其他学生,然后删除其他学生的老师,一直循环到不能删除了为止,几乎相当于清空数据库(删库跑路)。
7. 一对一
7.1 唯一外键一对一
主一:
@Entity
@Table(name = "t_qq")
public class QQ {
@Id
@GeneratedValue
private Long id;
private String number;
// 一对一
@OneToOne(mappedBy="qq")
private QQZone zone;
}
从一:
@Entity
@Table(name = "t_qqzone")
public class QQZone {
@Id
@GeneratedValue
private Long id;
private String name;
// 一对一,外键不能为空
@OneToOne(optional = false)
// unique=true确保了一对一关系
@JoinColumn(name = "qq_id", unique = true)
private QQ qq;
}
7.2 共享主键一对一(不建议使用)
@Entity
public class QQZone {
@Id
@GeneratedValue(generator = "pkGenerator")
@GenericGenerator(name = "pkGenerator", strategy = "foreign", parameters [email protected](name = "property", value = "qq"))
private Long id;
private String name;
// 一对一,一个qq空间输入一个qq号码
@OneToOne(optional = false)
// 如果不加这个注解,添加QQZone信息时,就会自动在QQZone表中增加了一个外键qq_id
@PrimaryKeyJoinColumn
private QQ qq;
}
推荐阅读
-
Java学习笔记 DbUtils数据库查询和log4j日志输出 使用
-
java学习笔记(基础篇)—关键字static和final
-
Intellij IDEA 2019 + Java Spring MVC + Hibernate学习笔记(1)
-
python学习笔记:第17天 面向对象03 类与类之间的关系
-
.NetCore学习笔记:四、AutoMapper对象映射
-
【JAVA 学习笔记2】if使用例子
-
Java学习笔记十五:Java中的成员变量和局部变量
-
Java语言Consistent Hash算法学习笔记(代码示例)
-
2.2多线程(java学习笔记)线程状态及线程操作的相关方法
-
java学习笔记10