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"
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
253359server :
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