0%

jpa实体关联

文章字数:691,阅读全文大约需要2分钟

实体间关联有@OneToOne@OneToMany or @ManyToOneManyToMany三种关系。其中,联机操作时只能One端操作Many端,代码层面则是cascade = CascadeType.ALL只能写在One端。One端删除,修改可以影响到Many端。反之则不允许。

一、@OneToOne关系映射

一个人有一个地址,就是一对一关系。其中people表的地址id对应地址表的id

1.1 通过外键关联一对一关系

people(id,name,addressId
address(id,phone,city,address)

People.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Entity
@Getter
@Setter
public class People{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false)
private Long id;

@Column(name = "name", nullable = true, length = 20)
private String name;

//People是关系的维护端,当删除 people,会级联删除 address。默认不联级。
@OneToOne(cascade=CascadeType.ALL)
//加入表中的字段(name)addressId,参考对应Address的id(referencedColumnName )
@JoinColumn(name = "addressId", referencedColumnName = "id")
private Address address;
}

Address.java

1
2
3
4
5
6
7
8
9
10
11
12
13
@Entity
public class Address {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false)
private Long id;
@Column(name = "phone", nullable = true, length = 11)
private String phone;
@Column(name = "city", nullable = true, length = 6)
private String city;
@Column(name = "address", nullable = true, length = 100)
private String address;
}

1.2 通过关联表保持
People(id,name)
Address(id,address)
PeopleAddr(PeopleId,addrId)关联表

People.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Entity
public class People {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false)
private Long id;

@Column(name = "name", nullable = true, length = 20)
private String name;

@OneToOne(cascade=CascadeType.ALL)//People是关系的维护端
@JoinTable(name = "PeopleAddr",//关系表名
joinColumns = @JoinColumn(name="PeopleId"),//对应当前主键的
inverseJoinColumns = @JoinColumn(name = "addressId"))//对应关联表的id的字段
private Address address;//关联表-地址实体
}

二、@OneToMany 和 @ManyToOne

一个班级有很多同学(一对多),班级被删除班上的同学的数据也没了(联级删除,默认没有)。删除同学的数据不会影响到班级(many不能影响one)

myClass.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Entity
public class Author {
@Id // 主键
@GeneratedValue(strategy = GenerationType.IDENTITY) // 自增长策略
private Long id; //id

@NotEmpty(message = "姓名不能为空")
@Column(nullable = false, length = 20)
private String name;

//指定Article的author字段关联id,mappedBy还代表放弃维护关系。即当自身修改删除时不会触发关联对象的相应操作。对应的,由对方维护。即文章修改了,作者对象下的文章列表也会相应修改。
//fetch=FetchType.LAZY 懒加载,不会马上加载。对于马上要用的可以设置马上加载
//mappendBy和JoinColumn相比一个放弃维护,另一个是建立联系(一端放弃,另一端建立)
@OneToMany(mappedBy = "author",cascade=CascadeType.ALL,fetch=FetchType.LAZY)
private List<Article> articleList;//文章列表
}

Article.java

1
2
3
4
5
6
@Entity
public class Article {
@ManyToOne(cascade={CascadeType.MERGE,CascadeType.REFRESH},optional=false)//可选属性optional=false,表示author不能为空。删除文章,不影响用户
@JoinColumn(name="author_id")//设置在article表中的关联字段(外键)
private Author author;//所属作者
}

三、@ManyToMany

  • 由其中一端维护关系
  • 被维护的一端无法直接删除,需要解除关系后才能删除。或者直接删除维护的一端,关系自动解除。
  • User.getAuthority().remove(authority)解除关系
  • User.setAuthorities(authorities)绑定关系
  • 多对多一般不设置联级操作

用户和权限组的例子就是多对多
User.java

1
2
3
4
@ManyToMany
@JoinTable(name = "user_authority",joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "authority_id"))
private List<Authority> authorityList;
  • 不使用@JoinTable注解,默认生成的关联表名称为主表表名+下划线+从表表名user_authority
  • 关联到主表的外键名:主表名+下划线+主表中的主键列名user_id
  • 关联到从表的外键名:主表中用于关联的属性名+下划线+从表的主键列名authority_id
  • 主表就是关系维护端对应的表,从表就是关系被维护端对应的表

Authority.java

1
2
@ManyToMany(mappedBy = "authorityList")
private List<User> userList;