目录

  • `JPA` 中的一对一
  • `JPA` 中的一对多
  • 测试
    • 一对一的添加测试
    • 一对多的添加测试
    • 查询测试

JPA 中的一对一

比如说一个学校有一个地址,一个地址对应的只有一个学校,Address

@Data
@Entity
@Table(name = "t_address")
public class Address {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Integer aid;private String province;private String city;private String area;private String phone;@OneToOne(cascade = CascadeType.ALL)private School school;
}

School

@Data
@Entity
@Table(name = "t_school")
public class School {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Integer sid;private String name;@OneToOne(cascade = CascadeType.ALL)private Address address;
}

如上的一对一的关系中,可以只在 School 类中维护,也可以只在 Address 类中维护,也可以两者都维护,具体哪种,那就看需求了。在 SchoolAddress 类中都通过 @OneToOne 注解来维护了一对一的关系,cascade 用来配置级联操作,有如下取值

  • ALL:所有操作
  • PERSIST:级联添加
  • MERGE:级联更新
  • REMOVE:级联删除
  • REFRESH:级联刷新

这样,最终创建出来的 t_school 表和 t_address 表中,会分别多出来一个字段 address_aidschool_sid,这两个字段都是外键,正是通过外键,将两张表中不同的记录关联起来



有的人可能不习惯这种自动添加的字段,那也可以自定义该字段,反正该字段总是要有的,自定义的方式如下

@Data
@Entity
@Table(name = "t_address")
public class Address {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Integer aid;private String province;private String city;private String area;private String phone;@OneToOne(cascade = CascadeType.ALL)@JoinColumn(name = "sid",referencedColumnName = "sid")private School school;@Column(insertable = false,updatable = false)private Integer sid;
}
@Data
@Entity
@Table(name = "t_school")
public class School {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Integer sid;private String name;@OneToOne(cascade = CascadeType.ALL)@JoinColumn(name = "aid",referencedColumnName = "aid")private Address address;@Column(insertable = false,updatable = false)private Integer aid;
}

Address 中自定义一个 sid,并设置该字段不可添加和修改,然后通过 @JoinColumn 注解去指定关联关系,@JoinColumn 注解中的 name 表示的是当前类中的属性名,referencedColumnName 表示的则是 School 类中对应的属性名

School 类中做相似的操作

JPA 中的一对多

一个班级中有多个学生,而一个学生只属于一个班级,我们可以这样来定义实体类

@Data
@Table(name = "t_student")
@Entity
public class Student {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Integer sid;private String name;@ManyToOne(cascade = CascadeType.ALL)private Clazz clazz;
}
@Data
@Table(name = "t_clazz")
@Entity
public class Clazz {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Integer cid;private String name;@OneToMany(cascade = CascadeType.ALL,fetch = FetchType.EAGER)private List<Student> students;
}
  • StudentClazz 的关系是多对一,用 @ManyToOne 注解,ClazzStudent
    的关系是一对多,用 @OneToMany 注解
  • StudentClazz 的关系是多对一,将来的 t_student 表中会多出来一个属性 clazz_cid,通过这个外键将 StudentClazz 关联起来。如果我们不想要自动生成的 clazz_cid,那么也可以自定义,方式如下
@Data
@Table(name = "t_student")
@Entity
public class Student {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Integer sid;private String name;@ManyToOne(cascade = CascadeType.ALL)@JoinColumn(name = "cid")private Clazz clazz;@Column(insertable = false,updatable = false)private Integer cid;
}
  • 定义一个 cid 属性,并设置为不可编辑和不可添加,然后通过 @JoinColumn 注解配置 cid 属性为外键
  • ClazzStudent 的关系是一对多,这个是通过一个自动生成的第三张表来实现的,如下

测试

一对一的添加测试

public interface SchoolRepository extends JpaRepository<School,Integer> {}@SpringBootTest
public class JpaOneToOneApplicationTests {@AutowiredSchoolRepository schoolRepository;@Testvoid contextLoads() {School school = new School();school.setSid(1);school.setName("哈佛大学");Address address = new Address();address.setAid(1);address.setProvince("黑龙江");address.setCity("哈尔滨");address.setArea("某地");address.setPhone("123456");school.setAddress(address);schoolRepository.save(school);}
}

在这个测试过程中,关联关系是由 t_school 一方来维护的,因此将来填充的外键是 t_school 中的 aid。添加结果如下图

这是一个简单的添加案例。更新也是调用 save() 方法,更新的时候会先判断这个 id 是否存在,存在的话就更新,不存在就添加

一对多的添加测试

public interface ClazzRepository extends JpaRepository<Clazz,Integer> {}@SpringBootTest
public class JpaOneToManyApplicationTests {@AutowiredClazzRepository clazzRepository;@Testvoid test02() {Clazz c = new Clazz();c.setCid(1);c.setName("三年级二班");List<Student> students = new ArrayList<>();Student s1 = new Student();s1.setSid(1);s1.setName("javaboy");students.add(s1);Student s2 = new Student();s2.setSid(2);s2.setName("张三");students.add(s2);c.setStudents(students);clazzRepository.save(c);}
}

注意,添加的是班级,所以班级和学生之间关系就由第三张表来维护,而不是由学生来维护

查询测试

再来一个简单的查询,假设我们现在想根据省份来搜索学校

public interface SchoolRepository extends JpaRepository<School,Integer> {List<School> findSchoolByAddressProvince(String province);
}@SpringBootTest
public class JpaApplicationTests {@AutowiredSchoolRepository schoolRepository;@Testvoid test01() {List<School> list = schoolRepository.findSchoolByAddressProvince("黑龙江");System.out.println("list = " + list);}
}

捋一下 Spring Data JPA 如何解析上面自定义的查询方法

  • 首先截取掉 findSchoolByAddressProvince 的前缀,剩下 AddressProvince
  • 检查 School 是否有 addressProvince 属性,有就按照该属性查询,对于我们的案例,并没有 addressProvince 属性,所以继续下一步
  • 从右侧驼峰开始拆分,拆掉第一个驼峰后面的内容,我们这里拆分之后只剩下 Address 了,判断 School 是否存在 Address 属性,不存在就继续重复该步骤,继续切掉右侧第一个驼峰
  • 在上文案例中,School 中有 address 属性,所以接下来就去检查 address 中是否有 province 属性,因为我们这里只剩下一个 province 了,如果剩下的字符串类似于 provinceAaaBbb 这种,那么继续按照第三步去解析

上面这个写法有一个小小的风险,假设 School 中刚好就有一个属性叫做 addressProvince,那么此时的分析就会出错。所以,对于上面的查询,我们也可以定义成如下方式

public interface SchoolRepository extends JpaRepository<School,Integer> {List<School> findSchoolByAddress_Province(String province);
}

此时就不会产生歧义了,系统就知道 provinceaddress 的属性了。再来一个班级的查询,如下

public interface ClazzRepository extends JpaRepository<Clazz,Integer> {}@SpringBootTest
public class JpaApplicationTests {@AutowiredClazzRepository clazzRepository;@Testvoid test03() {List<Clazz> list = clazzRepository.findAll();System.out.println("list = " + list);}
}

如果在查询的过程中,需要对学生进行排序,可以添加如下属性

@Data
@Table(name = "t_clazz")
@Entity
public class Clazz {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Integer cid;private String name;@OneToMany(cascade = CascadeType.ALL,fetch = FetchType.EAGER)@OrderBy("sid desc")private List<Student> students;
}

通过 @OrderBy(“sid desc”) 可以设置查询的 student 排序

转载:https://blog.csdn.net/u012702547/article/details/123004809

Spring Data JPA持久层中的一对一和一对多相关推荐

  1. 关于spring data jpa 仓储层自动实现

    Spring Data JPA: Spring提供的一个用于简化JPA开发的框架 Spring Data JPA不需要过多的关心Dao层的实现,只需关注我们继承的接口,按照一定的规则去编写我们的接口即 ...

  2. Spring Data JPA的持久层

    1.概述 本文将重点介绍Spring 3.1,JPA和Spring Data的持久层的配置和实现. 有关使用基于Java的配置和项目的基本Maven pom设置Spring上下文的分步介绍,请参阅本文 ...

  3. Spring Data JPA 原理与实战第十一天 Session相关、CompletableFuture、LazyInitializationException

    22 Session 的 open-in-view 对事务的影响是什么? 你好,欢迎来到第 22 讲,今天我们来学习 Session 的相关内容. 当我们使用 Spring Boot 加 JPA 的时 ...

  4. Spring Boot中使用Spring Data JPA示例

    JPA是Java Persistence API的简称,是sun公司早期推出的Java持久层规范,目前实现JPA规范的主流框架有Hibernate.OpenJPA等.Hibernate框架是当前较为流 ...

  5. hql 查询关联对象_在spring data jpa中如何做报表统计查询?

    问题描述 之前有个简单的报表统计需求,如果用sql的话是比较简单的,但是基于spring data jpa还没有遇到好的解决方案,折腾半天用spring data提供的几种方式都不能解决,spring ...

  6. Spring Data Jpa中的save和saveAndFlush方法

    Spring Data Jpa中save和saveAndFlush的区别,首先直接看图: save是CurdRepository接口下的方法 saveAndFlush是JpaRepository接口下 ...

  7. 对Spring Data JPA中的page对象下的content属性里的实体类对象转换为dto对象

    对Spring Data JPA中的page对象下的content属性里的实体类对象转换为dto对象. 刚开始试遍历content,进行转换,添加到新的list中,再set进去page.后来发现pag ...

  8. mysql jpa缓存,如何在Spring Data JPA CRUDRepository中添加缓存功能

    I want to add "Cacheable" annotation in findOne method, and evict the cache when delete or ...

  9. Spring Boot 、Spring Data JPA、Hibernate集成

    ###什么是JPA JPA是用于管理Java EE 和Java SE环境中的持久化,以及对象/关系映射的JAVA API 最新规范为"JSR 338:Java Persistence 2.1 ...

  10. springdatajpa命名规则_简单了解下spring data jpa

    公司准备搭建一个通用框架,以后项目就用统一一套框架了 以前只是听过jpa,但是没有实际用过 今天就来学习下一些简单的知识 什么是JPA 全称Java Persistence API,可以通过注解或者X ...

最新文章

  1. python selenium 文件上传_Python+Selenium学习--上传文件
  2. 自学python可以做什么兼职-一行生财:毕业100天,通过副业赚(挣)到我的第一个10w...
  3. nginx 学习笔记(6) nginx配置文件中的度量单位
  4. BLE 配对流程(转自襄坤在线)
  5. java char字符转编码_一、java基础-数据类型_数据类型转化_字符编码_转义字符
  6. 『中级篇』Docker Cloud自动构建 Docker image(55)
  7. Python在使用pip安装某个库时报错 Could not find a version that satisfies the requirement numpy
  8. MIT6.830 lab4 SimpleDB Transactions 实验报告
  9. BiLSTM+CRF命名实体识别:达观杯败走记(下篇)
  10. MATLAB 语言基础知识 矩阵和数组 从矩阵中删除行或列
  11. win10计算机的数字小键盘,Win10开机默认开启数字小键盘的方法
  12. datagrid的deleteRow使用
  13. python 读词向量文件
  14. Android WiFi only配置
  15. 刻意练习 Elasticsearch 10000 个小时,鬼知道经历了什么?!
  16. 点集拓扑学思维导图(附pdf源文档)
  17. 【C语言编程】简单密码
  18. 编程之路永无止境,想要与众不同你得这样做
  19. ESP01S CH340 一键下载电路设计
  20. W5500作为服务器突然断线

热门文章

  1. 算法:24.两两交换链表中的节点
  2. 易筋SpringBoot 2.1 | 第廿篇:SpringBoot的复杂JPA以及源码解析
  3. 计算机软件跨考教育学优点,2021教育学考研优势院校分析之:华南师范大学
  4. python字节码解析_简单入门python字节码混淆
  5. 四数之和 leetcode
  6. Fizz Buzz @leetcode Math
  7. JSTL简介以及简单示例
  8. linux的abrt目录满了,linux:abrt-cli list
  9. 2篇word文档比较重复率_【软件】PDF转word黑科技 快来get!
  10. module 'bit' not found:No LuaRocks module found for bit