Skip to content

Commit 5dafba9

Browse files
76peterxkcoding
authored andcommitted
jpa增加部门上下级自关联,用户部门多对多关联 (xkcoding#59)
* 添加部门之间多对一关联,部门和用户多对多关联。
1 parent ddb3c50 commit 5dafba9

File tree

6 files changed

+227
-5
lines changed

6 files changed

+227
-5
lines changed

spring-boot-demo-orm-jpa/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,12 @@
5959
<artifactId>lombok</artifactId>
6060
<optional>true</optional>
6161
</dependency>
62+
<dependency>
63+
<groupId>com.alibaba</groupId>
64+
<artifactId>fastjson</artifactId>
65+
<version>1.2.58</version>
66+
<scope>test</scope>
67+
</dependency>
6268
</dependencies>
6369

6470
<build>
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package com.xkcoding.orm.jpa.entity;
2+
3+
import com.xkcoding.orm.jpa.entity.base.AbstractAuditModel;
4+
import lombok.*;
5+
6+
import javax.persistence.*;
7+
import java.util.Collection;
8+
9+
/**
10+
* <p>
11+
* 部门实体类
12+
* </p>
13+
*
14+
* @package: com.xkcoding.orm.jpa.entity
15+
* @description: 部门实体类
16+
* @author: 76peter
17+
* @date: Created in 2019/10/1 18:07
18+
* @copyright: Copyright (c) 2019
19+
* @version: V1.0
20+
* @modified: 76peter
21+
*/
22+
@EqualsAndHashCode(callSuper = true)
23+
@Data
24+
@NoArgsConstructor
25+
@AllArgsConstructor
26+
@Builder
27+
@Entity
28+
@Table(name = "orm_department")
29+
@ToString(callSuper = true)
30+
public class Department extends AbstractAuditModel {
31+
32+
/**
33+
* 部门名
34+
*/
35+
@Column(name = "name", columnDefinition = "varchar(255) not null")
36+
private String name;
37+
38+
/**
39+
* 上级部门id
40+
*/
41+
@ManyToOne(cascade = {CascadeType.REFRESH},optional = true)
42+
@JoinColumn(name = "superior",referencedColumnName = "id")
43+
private Department superior;
44+
/**
45+
* 所属层级
46+
*/
47+
@Column(name = "levels", columnDefinition = "int not null default 0")
48+
private Integer levels;
49+
/**
50+
* 排序
51+
*/
52+
@Column(name = "orderno", columnDefinition = "int not null default 0")
53+
private Integer orderno;
54+
/**
55+
* 子部门集合
56+
*/
57+
@OneToMany(cascade={CascadeType.REFRESH, CascadeType.REMOVE}, fetch = FetchType.EAGER,mappedBy="superior")
58+
private Collection<Department> children;
59+
60+
/**
61+
* 部门下用户集合
62+
*/
63+
@ManyToMany(mappedBy = "departmentList")
64+
private Collection<User> userList;
65+
66+
}

spring-boot-demo-orm-jpa/src/main/java/com/xkcoding/orm/jpa/entity/User.java

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@
33
import com.xkcoding.orm.jpa.entity.base.AbstractAuditModel;
44
import lombok.*;
55

6-
import javax.persistence.Column;
7-
import javax.persistence.Entity;
8-
import javax.persistence.Table;
6+
import javax.persistence.*;
7+
import java.util.Collection;
98
import java.util.Date;
109

1110
/**
@@ -19,12 +18,12 @@
1918
* @date: Created in 2018/11/7 14:06
2019
* @copyright: Copyright (c)
2120
* @version: V1.0
22-
* @modified: yangkai.shen
21+
* @modified: 76peter
2322
*/
2423
@EqualsAndHashCode(callSuper = true)
25-
@Data
2624
@NoArgsConstructor
2725
@AllArgsConstructor
26+
@Data
2827
@Builder
2928
@Entity
3029
@Table(name = "orm_user")
@@ -66,4 +65,22 @@ public class User extends AbstractAuditModel {
6665
*/
6766
@Column(name = "last_login_time")
6867
private Date lastLoginTime;
68+
69+
70+
/**
71+
* 关联部门表
72+
*/
73+
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
74+
@JoinTable(name = "orm_usersetdept",joinColumns = @JoinColumn(name = "userid",referencedColumnName="id"),
75+
inverseJoinColumns = @JoinColumn(name = "deptid",referencedColumnName="id"))
76+
//1、关系维护端,负责多对多关系的绑定和解除
77+
//2、@JoinTable注解的name属性指定关联表的名字,joinColumns指定外键的名字,关联到关系维护端(User)
78+
//3、inverseJoinColumns指定外键的名字,要关联的关系被维护端(Department)
79+
//4、其实可以不使用@JoinTable注解,默认生成的关联表名称为主表表名+下划线+从表表名,
80+
//即表名为user_department
81+
//关联到主表的外键名:主表名+下划线+主表中的主键列名,即user_id,这里使用referencedColumnName指定
82+
//关联到从表的外键名:主表中用于关联的属性名+下划线+从表的主键列名,department_id
83+
//主表就是关系维护端对应的表,从表就是关系被维护端对应的表
84+
private Collection<Department> departmentList;
85+
6986
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.xkcoding.orm.jpa.repository;
2+
3+
import com.xkcoding.orm.jpa.entity.Department;
4+
import org.springframework.data.jpa.repository.JpaRepository;
5+
import org.springframework.stereotype.Repository;
6+
7+
import java.util.Collection;
8+
9+
10+
/**
11+
* <p>
12+
* User Dao
13+
* </p>
14+
*
15+
* @package: com.xkcoding.orm.jpa.repository
16+
* @description: Department Dao
17+
* @author: 76peter
18+
* @date: Created in 2019/10/1 18:07
19+
* @copyright: Copyright (c) 2019
20+
* @version: V1.0
21+
* @modified: 76peter
22+
*/
23+
@Repository
24+
public interface DepartmentDao extends JpaRepository<Department, Long> {
25+
public Collection<Department> findDepartmentsByLevels(Integer level);
26+
}

spring-boot-demo-orm-jpa/src/main/resources/db/schema.sql

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,24 @@ CREATE TABLE `orm_user` (
1111
`last_login_time` DATETIME DEFAULT NULL COMMENT '上次登录时间',
1212
`last_update_time` DATETIME NOT NULL DEFAULT NOW() COMMENT '上次更新时间'
1313
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Spring Boot Demo Orm 系列示例表';
14+
15+
16+
DROP TABLE IF EXISTS `orm_department`;
17+
CREATE TABLE `orm_department` (
18+
`id` INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '主键',
19+
`name` VARCHAR(32) NOT NULL COMMENT '部门名称',
20+
`superior` INT(11) COMMENT '上级id',
21+
`levels` INT(11) NOT NULL COMMENT '层级',
22+
`orderno` INT(11) NOT NULL DEFAULT 0 COMMENT '排序',
23+
`create_time` DATETIME NOT NULL DEFAULT NOW() COMMENT '创建时间',
24+
`last_update_time` DATETIME NOT NULL DEFAULT NOW() COMMENT '上次更新时间'
25+
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Spring Boot Demo Orm 系列示例表';
26+
27+
--DROP TABLE IF EXISTS `orm_usersetdept`;
28+
CREATE TABLE `orm_usersetdept` (
29+
`id` INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '主键',
30+
`userid` INT(11) NOT NULL COMMENT '用户id',
31+
`deptid` INT(11) NOT NULL COMMENT '部门id',
32+
`create_time` DATETIME NOT NULL DEFAULT NOW() COMMENT '创建时间',
33+
`last_update_time` DATETIME NOT NULL DEFAULT NOW() COMMENT '上次更新时间'
34+
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Spring Boot Demo Orm 系列示例表';
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package com.xkcoding.orm.jpa.repository;
2+
3+
import com.xkcoding.orm.jpa.SpringBootDemoOrmJpaApplicationTests;
4+
import com.xkcoding.orm.jpa.entity.Department;
5+
import com.xkcoding.orm.jpa.entity.User;
6+
import lombok.extern.slf4j.Slf4j;
7+
import net.minidev.json.JSONArray;
8+
import org.junit.Test;
9+
import org.springframework.beans.factory.annotation.Autowired;
10+
11+
import javax.transaction.Transactional;
12+
import java.util.Collection;
13+
import java.util.List;
14+
15+
/**
16+
* <p>
17+
* jpa 测试类
18+
* </p>
19+
*
20+
* @package: com.xkcoding.orm.jpa.repository
21+
* @description: jpa 测试类
22+
* @author: 76peter
23+
* @date: Created in 2018/11/7 14:09
24+
* @copyright: Copyright (c) 2018
25+
* @version: V1.0
26+
* @modified: 76peter
27+
*/
28+
@Slf4j
29+
public class DepartmentDaoTest extends SpringBootDemoOrmJpaApplicationTests {
30+
@Autowired
31+
private DepartmentDao departmentDao;
32+
@Autowired
33+
private UserDao userDao;
34+
35+
/**
36+
* 测试保存 ,根节点
37+
*/
38+
@Test
39+
@Transactional
40+
public void testSave() {
41+
Collection<Department> departmentList = departmentDao.findDepartmentsByLevels(0);
42+
if(departmentList.size()==0){
43+
Department testSave1 = Department.builder().name("testSave1").orderno(0).levels(0).superior(null).build();
44+
Department testSave1_1 = Department.builder().name("testSave1_1").orderno(0).levels(1).superior(testSave1).build();
45+
Department testSave1_2 = Department.builder().name("testSave1_2").orderno(0).levels(1).superior(testSave1).build();
46+
Department testSave1_1_1 = Department.builder().name("testSave1_1_1").orderno(0).levels(2).superior(testSave1_1).build();
47+
departmentList.add(testSave1);
48+
departmentList.add(testSave1_1);
49+
departmentList.add(testSave1_2);
50+
departmentList.add(testSave1_1_1);
51+
departmentDao.saveAll(departmentList);
52+
53+
Collection<Department> deptall = departmentDao.findAll();
54+
log.debug("【部门】= {}", JSONArray.toJSONString((List)deptall));
55+
}
56+
57+
58+
userDao.findById(1L).ifPresent(user -> {
59+
user.setName("添加部门");
60+
Department dept = departmentDao.findById(2L).get();
61+
user.setDepartmentList(departmentList);
62+
userDao.save(user);
63+
});
64+
User users = userDao.findById(1L).get();
65+
log.debug("用户部门={}", JSONArray.toJSONString((List)userDao.findById(1L).get().getDepartmentList()));
66+
67+
68+
departmentDao.findById(2L).ifPresent(dept -> {
69+
Collection<User> userlist = dept.getUserList();
70+
//关联关系由user维护中间表,department userlist不会发生变化,可以增加查询方法来处理 重写getUserList方法
71+
log.debug("部门下用户={}", JSONArray.toJSONString((List)userlist));
72+
});
73+
74+
75+
userDao.findById(1L).ifPresent(user -> {
76+
user.setName("清空部门");
77+
user.setDepartmentList(null);
78+
userDao.save(user);
79+
});
80+
log.debug("用户部门={}", userDao.findById(1L).get().getDepartmentList());
81+
82+
83+
}
84+
85+
86+
}

0 commit comments

Comments
 (0)