SpringBoot结合SpringData Jpa–注解部分(二)
承接上篇博客:https://blog.youkuaiyun.com/qq_33608923/article/details/102729114
上篇主要讲了@OneToMany,这篇把ManyToMany和OneToOne也试一试。
首先是@OneToOne,就用User和UserInfo来表示一对一的关系,分别创建者两个实体类:
import javax.persistence.*;
import java.io.Serializable;
import java.util.List;
/**
*User
*author BenJerry
*version 1.0
*/
@Table(name = "t_user")
@Entity
public class User implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
private String email;
private Long rid;
@OneToMany
@JoinColumn(name = "id", referencedColumnName = "rid")
private List<Role> roles;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Long getRid() {
return rid;
}
public void setRid(Long rid) {
this.rid = rid;
}
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
}
------------------------------------------------------------------------------------------
import javax.persistence.*;
/**
*UserInfo
*author BenJerry
*version 1.0
*/
@Entity
@Table(name = "t_user_info")
public class UserInfo {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String gender;
private Long uid;
@OneToOne
@JoinColumn(name = "id", referencedColumnName = "uid")
private User user;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public Long getUid() {
return uid;
}
public void setUid(Long uid) {
this.uid = uid;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
------------------------------------------------------------------------------
<!-- 老套路,创建UserInfoRepository继承JpaRepository -->
import com.github.jpa.demo.entity.UserInfo;
import org.springframework.data.jpa.repository.JpaRepository;
/**
* UserInfoRepository
* author BenJerry
* version 1.0
*/
public interface UserInfoRepository extends JpaRepository<UserInfo, Long> {
}
--------------------------------------------------------------------------------
@GetMapping(path = "/all1")
@ResponseBody
public List<UserInfo> all1() {
return userInfoRepository.findAll();
}
运行效果是这样的:
[{
"id": 1,
"gender": "男",
"uid": 1,
"user": {
"id": 1,
"name": "1",
"email": "1",
"rid": 1,
"roles": [{
"id": 1,
"role": "role1",
"pid": 1
}]
}
}]
实际执行sql:
Hibernate: select userinfo0_.id as id1_5_, userinfo0_.gender as gender2_5_, userinfo0_.uid as uid3_5_ from t_user_info userinfo0_
Hibernate: select user0_.id as id1_4_0_, user0_.email as email2_4_0_, user0_.name as name3_4_0_, user0_.rid as rid4_4_0_ from t_user user0_ where user0_.id=?
Hibernate: select roles0_.id as id1_2_0_, roles0_.id as id1_2_1_, roles0_.pid as pid2_2_1_, roles0_.role as role3_2_1_ from t_role roles0_ where roles0_.id=?
可以看到一共执行了三条,上次一对多关系的语句也会执行。
一对一,一对多和多对多按道理都是可以双向查询的,比如说上面的例子是查询用户详情信息,用户本身的账户信息也会出来,那查询用户账户信息,用户的详情信息应该也可以出来。
在UserInfo中写好@OnetToOne和@JoinColumn注解之后,在User中声明一个UserInfo的属性和一个简单的注解就可以:
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import javax.persistence.*;
import java.io.Serializable;
import java.util.List;
/**
*User
*author BenJerry
*version 1.0
*/
@Table(name = "t_user")
@Entity
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class,property = "@id")
public class User implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
private String email;
private Long rid;
@OneToMany
@JoinColumn(name = "id", referencedColumnName = "rid")
private List<Role> roles;
@OneToOne(mappedBy = "user")
private UserInfo userInfo;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Long getRid() {
return rid;
}
public void setRid(Long rid) {
this.rid = rid;
}
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
public UserInfo getUserInfo() {
return userInfo;
}
public void setUserInfo(UserInfo userInfo) {
this.userInfo = userInfo;
}
}
-------------------------------------------------------------------------------------
@GetMapping(path = "/page1")
@ResponseBody
public Page<User> page1() {
return userRepository.selectUserByPage("1", PageRequest.of(0, 10));
}
注意:
1、mapperBy指定的是UserInfo类中,用User类声明的私有变量的名称,而不是直接写有外键关系的字段
2、@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class,property = “@id”)注解必不可少,可以防止json解析循环问题。
运行效果:
{
"content": [{
"@id": 1,
"id": 1,
"name": "1",
"email": "1",
"rid": 1,
"roles": [{
"id": 1,
"role": "role1",
"pid": 1
}],
"userInfo": {
"id": 1,
"gender": "男",
"uid": 1,
"user": 1
}
}],
"pageable": {
"sort": {
"sorted": false,
"unsorted": true,
"empty": true
},
"offset": 0,
"pageSize": 10,
"pageNumber": 0,
"unpaged": false,
"paged": true
},
"totalElements": 1,
"totalPages": 1,
"last": true,
"number": 0,
"size": 10,
"sort": {
"sorted": false,
"unsorted": true,
"empty": true
},
"numberOfElements": 1,
"first": true,
"empty": false
}
我们在再建一个Permission类用多对多的注解:
import javax.persistence.*;
import java.util.List;
/**
*Permission
*author BenJerry
*version 1.0
*/
@Table(name = "t_permission")
@Entity
public class Permission {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String permission;
@ManyToMany
@JoinTable(name = "t_role_permission", joinColumns = @JoinColumn(name = "pid", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "rid", referencedColumnName = "id"))
private List<Role> roles;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getPermission() {
return permission;
}
public void setPermission(String permission) {
this.permission = permission;
}
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
}
多对多关系用关系表维护外键关系,所以在类中使用@JoinTable,运行如下代码:
@GetMapping(path = "/all3")
@ResponseBody
public List<Permission> all3() {
return permissionRepository.findAll();
}
实际运行的sql:
Hibernate: select permission0_.id as id1_1_, permission0_.permission as permissi2_1_ from t_permission permission0_
Hibernate: select roles0_.pid as pid1_3_0_, roles0_.rid as rid2_3_0_, role1_.id as id1_2_1_, role1_.pid as pid2_2_1_, role1_.role as role3_2_1_ from t_role_permission roles0_ inner join t_role role1_ on roles0_.rid=role1_.id where roles0_.pid=?
Hibernate: select roles0_.pid as pid1_3_0_, roles0_.rid as rid2_3_0_, role1_.id as id1_2_1_, role1_.pid as pid2_2_1_, role1_.role as role3_2_1_ from t_role_permission roles0_ inner join t_role role1_ on roles0_.rid=role1_.id where roles0_.pid=?
运行结果:
[{
"id": 1,
"permission": "permission1",
"roles": [{
"id": 1,
"role": "role1",
"pid": 1
}]
}, {
"id": 2,
"permission": "permission2",
"roles": [{
"id": 2,
"role": "role2",
"pid": 1
}]
}]
可以看到如果一个角色有很多权限,这么搞坑定不行的,spring data jpa也有解决方案,下篇再说吧。