Skip to content

Commit 2b61979

Browse files
committed
✨ jpa增加部门上下级自关联,用户部门多对多关联,[PR#59](xkcoding#59)
1 parent 5dafba9 commit 2b61979

File tree

7 files changed

+287
-108
lines changed

7 files changed

+287
-108
lines changed

spring-boot-demo-orm-jpa/README.md

Lines changed: 192 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
# spring-boot-demo-orm-jpa
2-
> 此 demo 主要演示了 Spring Boot 如何使用 JPA 操作数据库。
2+
> 此 demo 主要演示了 Spring Boot 如何使用 JPA 操作数据库,包含简单使用以及级联使用。
3+
4+
## 主要代码
5+
6+
### pom.xml
37

4-
## pom.xml
58
```xml
69
<?xml version="1.0" encoding="UTF-8"?>
710
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
@@ -78,7 +81,7 @@
7881

7982
</project>
8083
```
81-
## JpaConfig.java
84+
### JpaConfig.java
8285
```java
8386
/**
8487
* <p>
@@ -123,7 +126,7 @@ public class JpaConfig {
123126
}
124127
}
125128
```
126-
## User.java
129+
### User.java
127130
```java
128131
/**
129132
* <p>
@@ -136,12 +139,12 @@ public class JpaConfig {
136139
* @date: Created in 2018/11/7 14:06
137140
* @copyright: Copyright (c)
138141
* @version: V1.0
139-
* @modified: yangkai.shen
142+
* @modified: 76peter
140143
*/
141144
@EqualsAndHashCode(callSuper = true)
142-
@Data
143145
@NoArgsConstructor
144146
@AllArgsConstructor
147+
@Data
145148
@Builder
146149
@Entity
147150
@Table(name = "orm_user")
@@ -183,9 +186,86 @@ public class User extends AbstractAuditModel {
183186
*/
184187
@Column(name = "last_login_time")
185188
private Date lastLoginTime;
189+
190+
/**
191+
* 关联部门表
192+
* 1、关系维护端,负责多对多关系的绑定和解除
193+
* 2、@JoinTable注解的name属性指定关联表的名字,joinColumns指定外键的名字,关联到关系维护端(User)
194+
* 3、inverseJoinColumns指定外键的名字,要关联的关系被维护端(Department)
195+
* 4、其实可以不使用@JoinTable注解,默认生成的关联表名称为主表表名+下划线+从表表名,
196+
* 即表名为user_department
197+
* 关联到主表的外键名:主表名+下划线+主表中的主键列名,即user_id,这里使用referencedColumnName指定
198+
* 关联到从表的外键名:主表中用于关联的属性名+下划线+从表的主键列名,department_id
199+
* 主表就是关系维护端对应的表,从表就是关系被维护端对应的表
200+
*/
201+
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
202+
@JoinTable(name = "orm_user_dept", joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "dept_id", referencedColumnName = "id"))
203+
private Collection<Department> departmentList;
204+
186205
}
187206
```
188-
## AbstractAuditModel.java
207+
### Department.java
208+
```java
209+
/**
210+
* <p>
211+
* 部门实体类
212+
* </p>
213+
*
214+
* @package: com.xkcoding.orm.jpa.entity
215+
* @description: 部门实体类
216+
* @author: 76peter
217+
* @date: Created in 2019/10/1 18:07
218+
* @copyright: Copyright (c) 2019
219+
* @version: V1.0
220+
* @modified: 76peter
221+
*/
222+
@EqualsAndHashCode(callSuper = true)
223+
@Data
224+
@NoArgsConstructor
225+
@AllArgsConstructor
226+
@Builder
227+
@Entity
228+
@Table(name = "orm_department")
229+
@ToString(callSuper = true)
230+
public class Department extends AbstractAuditModel {
231+
232+
/**
233+
* 部门名
234+
*/
235+
@Column(name = "name", columnDefinition = "varchar(255) not null")
236+
private String name;
237+
238+
/**
239+
* 上级部门id
240+
*/
241+
@ManyToOne(cascade = {CascadeType.REFRESH}, optional = true)
242+
@JoinColumn(name = "superior", referencedColumnName = "id")
243+
private Department superior;
244+
/**
245+
* 所属层级
246+
*/
247+
@Column(name = "levels", columnDefinition = "int not null default 0")
248+
private Integer levels;
249+
/**
250+
* 排序
251+
*/
252+
@Column(name = "order_no", columnDefinition = "int not null default 0")
253+
private Integer orderNo;
254+
/**
255+
* 子部门集合
256+
*/
257+
@OneToMany(cascade = {CascadeType.REFRESH, CascadeType.REMOVE}, fetch = FetchType.EAGER, mappedBy = "superior")
258+
private Collection<Department> children;
259+
260+
/**
261+
* 部门下用户集合
262+
*/
263+
@ManyToMany(mappedBy = "departmentList")
264+
private Collection<User> userList;
265+
266+
}
267+
```
268+
### AbstractAuditModel.java
189269
```java
190270
/**
191271
* <p>
@@ -228,7 +308,7 @@ public abstract class AbstractAuditModel implements Serializable {
228308
private Date lastUpdateTime;
229309
}
230310
```
231-
## UserDao.java
311+
### UserDao.java
232312
```java
233313
/**
234314
* <p>
@@ -248,7 +328,33 @@ public interface UserDao extends JpaRepository<User, Long> {
248328

249329
}
250330
```
251-
## application.yml
331+
### DepartmentDao.java
332+
```java
333+
/**
334+
* <p>
335+
* User Dao
336+
* </p>
337+
*
338+
* @package: com.xkcoding.orm.jpa.repository
339+
* @description: Department Dao
340+
* @author: 76peter
341+
* @date: Created in 2019/10/1 18:07
342+
* @copyright: Copyright (c) 2019
343+
* @version: V1.0
344+
* @modified: 76peter
345+
*/
346+
@Repository
347+
public interface DepartmentDao extends JpaRepository<Department, Long> {
348+
/**
349+
* 根据层级查询部门
350+
*
351+
* @param level 层级
352+
* @return 部门列表
353+
*/
354+
List<Department> findDepartmentsByLevels(Integer level);
355+
}
356+
```
357+
### application.yml
252358
```yaml
253359
server:
254360
port: 8080
@@ -290,7 +396,7 @@ logging:
290396
org.hibernate.SQL: debug
291397
org.hibernate.type: trace
292398
```
293-
## UserDaoTest.java
399+
### UserDaoTest.java
294400
```java
295401
/**
296402
* <p>
@@ -403,7 +509,82 @@ public class UserDaoTest extends SpringBootDemoOrmJpaApplicationTests {
403509

404510
}
405511
```
512+
### DepartmentDaoTest.java
513+
```java
514+
/**
515+
* <p>
516+
* jpa 测试类
517+
* </p>
518+
*
519+
* @package: com.xkcoding.orm.jpa.repository
520+
* @description: jpa 测试类
521+
* @author: 76peter
522+
* @date: Created in 2018/11/7 14:09
523+
* @copyright: Copyright (c) 2018
524+
* @version: V1.0
525+
* @modified: 76peter
526+
*/
527+
@Slf4j
528+
public class DepartmentDaoTest extends SpringBootDemoOrmJpaApplicationTests {
529+
@Autowired
530+
private DepartmentDao departmentDao;
531+
@Autowired
532+
private UserDao userDao;
533+
534+
/**
535+
* 测试保存 ,根节点
536+
*/
537+
@Test
538+
@Transactional
539+
public void testSave() {
540+
Collection<Department> departmentList = departmentDao.findDepartmentsByLevels(0);
541+
542+
if (departmentList.size() == 0) {
543+
Department testSave1 = Department.builder().name("testSave1").orderNo(0).levels(0).superior(null).build();
544+
Department testSave1_1 = Department.builder().name("testSave1_1").orderNo(0).levels(1).superior(testSave1).build();
545+
Department testSave1_2 = Department.builder().name("testSave1_2").orderNo(0).levels(1).superior(testSave1).build();
546+
Department testSave1_1_1 = Department.builder().name("testSave1_1_1").orderNo(0).levels(2).superior(testSave1_1).build();
547+
departmentList.add(testSave1);
548+
departmentList.add(testSave1_1);
549+
departmentList.add(testSave1_2);
550+
departmentList.add(testSave1_1_1);
551+
departmentDao.saveAll(departmentList);
552+
553+
Collection<Department> deptall = departmentDao.findAll();
554+
log.debug("【部门】= {}", JSONArray.toJSONString((List) deptall));
555+
}
556+
557+
558+
userDao.findById(1L).ifPresent(user -> {
559+
user.setName("添加部门");
560+
Department dept = departmentDao.findById(2L).get();
561+
user.setDepartmentList(departmentList);
562+
userDao.save(user);
563+
});
564+
565+
log.debug("用户部门={}", JSONUtil.toJsonStr(userDao.findById(1L).get().getDepartmentList()));
566+
567+
568+
departmentDao.findById(2L).ifPresent(dept -> {
569+
Collection<User> userlist = dept.getUserList();
570+
//关联关系由user维护中间表,department userlist不会发生变化,可以增加查询方法来处理 重写getUserList方法
571+
log.debug("部门下用户={}", JSONUtil.toJsonStr(userlist));
572+
});
573+
574+
575+
userDao.findById(1L).ifPresent(user -> {
576+
user.setName("清空部门");
577+
user.setDepartmentList(null);
578+
userDao.save(user);
579+
});
580+
log.debug("用户部门={}", userDao.findById(1L).get().getDepartmentList());
581+
582+
}
583+
}
584+
```
585+
586+
### 其余代码及 SQL 参见本 demo
406587

407588
## 参考
408589

409-
Spring Data JPA 官方文档:https://docs.spring.io/spring-data/jpa/docs/current/reference/html/
590+
- Spring Data JPA 官方文档:https://docs.spring.io/spring-data/jpa/docs/current/reference/html/

0 commit comments

Comments
 (0)