一.单向一对多
- 性能非常差,不建议使用
- 如果要使用,建议使用双向的多对一,一对多
代码配置
- 必需使用接口声明
- 可以使用List(有序允许重复)或者Set
- 一定要指定外键(否则会出现中间表)
@OneToMany
@JoinColumn(name = "dir_id ")
private List<Product> products = new ArrayList<>();
二.双向多对一,一对多
- 双向配置的表结构和单向是完全一样的
- 尽量使用多方来维护关系(性能好)
- 外键在哪边,哪边就是多方(也方便维护)
Prdocut(多方)
@Entity
@Table(name = "product")
public class Product {
...
/**
* 多个产品对应一个产品类型
* 默认的名称就dir_id
*/
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="dir_id")
private ProductDir dir;
...
}
PrdocutDir(一方)
@Entity
@Table(name = "productdir")
public class ProductDir {
...
/**
* 确定外键关连的名称叫:dir_id
* 保证维护关系的列是同一列
* mappedBy = "dir" :映射的关系交给Product类中的dir的属性去维护
* 放弃了关系维护
*/
@OneToMany(mappedBy = "dir")
private List<Product> products = new ArrayList<>();
...
}
三.级联
- 级联很危险,不要随便使用
- 组合关系(单据)必需使用级联
- 要使用就是使用最强级联: cascade = CascadeType.ALL,orphanRemoval = true
代码配置
@Entity
@Table(name = "productdir")
public class ProductDir {
...
/**
* 确定外键关连的名称叫:dir_id
* 保证维护关系的列是同一列
* mappedBy = "dir" :映射的关系交给Product类中的dir的属性去维护
* 放弃了关系维护
* cascade:级联
* CascadeType.PERSIST:级联保存(一人得道,鸡狗升天)
* CascadeType.MERGE:级联修改(荣辱与共)
* CascadeType.REMOVE:级联删除 (生死与共)
* CascadeType.ALL:级联增删改
* orphanRemoval:孤儿删除
*/
@OneToMany(mappedBy = "dir",cascade = CascadeType.ALL,orphanRemoval = true)
private List<Product> products = new ArrayList<>();
...
}
四.多对多
- 一定要自己去控制中间表的表名与列名
- 正常操作都没有问题(尽量不要使用级联)
- 双向保证表名列名是一致的
/**
* @JoinTable:对中间表进行设置
* name = "t_user_role":中间表的名称
* joinColumns = @JoinColumn(name = "user_id"):修改当前表对应的列名
* inverseJoinColumns = @JoinColumn(name = "role_id"):对面那张表的列名
*/
@ManyToMany
@JoinTable(name = "t_user_role"
,joinColumns = @JoinColumn(name = "user_id")
,inverseJoinColumns = @JoinColumn(name = "role_id"))
private List<Role> roles = new ArrayList<>();
五.一对一(了解)
- 共享主键(扩展性不强,不建议使用)
- 唯一外键(扩展性强,建议使用)
- 外键在哪边,哪边就是从表
QQ:主表
@Entity
public class QQ {
@Id
@GeneratedValue
private Long id;
private String number;
// 一对一,一个qq号码对应一个qq空间
@OneToOne(mappedBy="qq")
private QQZone zone;
}
QQZone:从表
@Entity
public class QQZone {
@Id
@GeneratedValue
private Long id;
private String name;
// 一对一,一个qq空间输入一个qq号码
// 默认值optional = true表示qq_id可以为空;反之。。。
@OneToOne(optional = false)
// unique=true确保了一对一关系
@JoinColumn(name = "qq_id", unique = true)
private QQ qq;
}
六.注意:
- 单向多对一,一对多,双向多对一,一对多,表结构完成一样
- 单向一对多性能差(不用)
- 声明的时候都用接口
- 集合先new出来(以免以后代码麻烦)
- JPA,集合默认懒加载
- 想要性能好,先一后多
- 先配置单向(业务需要再配置双向) 8.不要toString(),互相调用容易内存溢出