JPA 中使用 @OneToMany 、@ManyToOne 等关系映射注解

news2025/2/27 2:48:43

JPA 做 ORM(Object Relational Mapping,对象关系映射)时,为了开发效率,通常会在实体类上用 hibernate 的关系关联注解。 包括:@OneToOne@OneToMany@ManyToOne@ManyToMany@JoinTable、以及 @JoinColumn 以及 OrderBy

JPA 中 @JoinColumn 与 关联注解之间用法

@JoinColumn 定义多个字段之间的关联关系,配合@OneToOne@ManyToOne 以及 @OneToMany一起使用

@Repeatable(JoinColumns.class)
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface JoinColumn {
	// 关联字段(子)
    String name() default "";
	// 关键实体字段(父)),非必填
    String referencedColumnName() default "";

    boolean unique() default false;

    boolean nullable() default true;
    // 是否更新 插入操作
    boolean insertable() default true;

    boolean updatable() default true;

    String columnDefinition() default "";

    String table() default "";

    ForeignKey foreignKey() default @ForeignKey(ConstraintMode.PROVIDER_DEFAULT);
}

@OneToMany 注解为例,源代码如下

@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface OneToMany {
    // 关联对象实体类
    Class targetEntity() default void.class;
	
    // 级联类型,
    // ALL, 级联所有操作
    // PERSIST,级联持久化
    // MERGE, 级联更新合并
    // REMOVE,级联删除
    // REFRESH,  刷新后更新
    //DETACH;  级联脱管操作
    CascadeType[] cascade() default {};
	
    //  获取方式
    // LAZY 懒加载,需要时加载;
    // EARLY 提前加载
    FetchType fetch() default FetchType.LAZY;
	// 被映射实体类名,当关联实体类上注有 ManyToOne 时,该参数必填;
    String mappedBy() default "";
    boolean orphanRemoval() default false;
}

@OneToMany 使用时可以结合 @JoinColumn 一起使用,既可以单向,也可以双向关联;单向指的是只配置一方,双向指两方都配置,实例如下:

假设小组(GroupClass)与学生(Student)关系,一个组可以容纳多个学生,一对多 ;多个学生组件成一个组(多对一);

外键关联,一般子实体类这边维护,因此由Student 来关联 :

@Entity
@Table(name = "student")
public class Student {
    
    // 主键自动生成策略
    @Id

    private Integer id;
    
    private String name;
    
    @Column(name = "student_no",unique = true)
    private String studentNo;
    
    @Column(name = "group_class_id")
    private Integer groupClassId;
	
 	// 关联关系多对一,级联关系,可更新,持久化, 获取方式懒加载;
    @ManyToOne(targetEntity = GroupClass.class,
            cascade = {CascadeType.MERGE,CascadeType.PERSIST,CascadeType.REFRESH},
            fetch = FetchType.LAZY)
      // 以 group_id 为外键进行关联,referencedColumnName 默认为被关联实体类主键,可以忽略;
    @JoinColumn(name="group_class_id",referencedColumnName = "id")
    private GroupClass groupClass;
}

而双向关联的 GroupClass 实体类(父类),定义如下:

@Data
@Entity
@Table(name = "group_class")
public class GroupClass {
    @Id
    private Integer id;

    private String name;

    @Column(name="group_no",unique = true)
    private String groupNo;

	// 由于外键关联由 Student 维护,这里不需要在做处理,只需要引用 
    // @OneToMany中的 mappedBy 参数即可;
    @OneToMany(mappedBy = "groupClass")
    private List<Student> students = new ArrayList<>();
}

其它关联注解用法类同:

  • @ManyToMany :多对多;
  • @OneToOne :一对一;

@OrderBy 字段排序

@OrderBy 顾名思义目的是为根据某个字段进行排序,注解一般与 @OneToMany@ManyToMany 同时使用,

@OneToMany(mappedBy = "groupClass")
// 根据名字对 学生对象逆向排序 
@OrderBy("name DESC")
private List<Student> students = new ArrayList<>();

使用实例如下,首先插入1条 GroupClass 和 两条Student 记录,并将两个 Student 关联至 GroupClass

  // 持久化 GroupClass
  GroupClass group = new GroupClass();
  group.setGroupNo("Ano");
  group.setName("名字");
  group.setId(2L);
  //持久化 Student;
  Student student = new Student();
  student.setStudentNo("12");
  student.setId(1);
  student.setName("name1");
  student.setGroupClass(group);
  Student student2 = new Student();
  student2.setStudentNo("122");
  student2.setId(2);
  student2.setGroupClass(group);
  student2.setName("name12");
  // save 保存
  List<Student> students = new ArrayList<>();
  students.add(student);
  students.add(student2);
  group.setStudents(students);
  groupClassRepository.save(group);

根据Id 查询 GroupClass 对象,在输出打印对象的toString 方法钱,需要重新写一下 对象的 toString 函数,防止循环嵌套导致的堆栈溢出问题

   //Student.class 
    @Override
    public String toString() {
        return "Student [id=" + id + ", name=" +name + ", studentNo=" +studentNo + ", groupClassId=" + groupClassId
                + "]";
    }

在上面例子中, GroupClass 对象中 toString 函数引用到 Student,而 StudenttoString 同时引用到 GroupClass,使用时会触发嵌套循环,造成栈溢出问题;

image-20221115090622405

输出 groupClass.toString后,就会发现 groupClass 关联的 students 属性是按照 @OrderBy 注解输出,如下:

 Optional<GroupClass> groupClassOptional = groupClassRepository.findById(2L);
 if(groupClassOptional.isPresent()) {
     GroupClass groupClass = groupClassOptional.get();
     log.info("groupClass str is {}",groupClass.toString());
 }

日志输出如下:

groupClass str is GroupClass(id=2, name=名字, groupNo=Ano, students=[Student [id=2, name=cname, studentNo=122, groupClassId=2], Student [id=1, name=bname1, studentNo=12, groupClassId=2]])

重写实体类 toString 方法,可以解决了父子实体类打印输出时,因相互依赖循环嵌套中堆栈溢出问题;但当实体类通过 SpringBoot 中 @ResponseBody以 Json 格式输出给前端时,会出现序列化堆栈溢出问题

Could not write JSON: Infinite recursion (StackOverflowError); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError)

该错误解决方法:在父类或子类对应的关联字段上,加上 JsonIgnore 注解,即在 Json序列化 时忽略该属性

// Json 序列化时忽略该属性
@JsonIgnore
@ManyToOne(targetEntity = GroupClass.class,
           cascade = CascadeType.ALL,
           fetch = FetchType.LAZY)
@JoinColumn(name="group_class_id",referencedColumnName = "id", insertable = false, updatable = false)
private GroupClass groupClass;

另一方面,我们在项目配置中打开JPA日志输出调试设置

srping:
  jpa:
    show-sql: true

    hibernate:
      ddl-auto: none

    properties:
      # 将 hibernate 执行语句以 sql 形式打印
      hibernate.format_sql: true
      hibernate.id.new_generator_mappings: false

因此可以从控制台日志输出来查看内部执行的sql逻辑

  select
        groupclass0_.id as id1_5_0_,
        groupclass0_.group_no as group_no2_5_0_,
        groupclass0_.name as name3_5_0_,
        students1_.group_class_id as group_cl2_6_1_,
        students1_.id as id1_6_1_,
        students1_.id as id1_6_2_,
        students1_.group_class_id as group_cl2_6_2_,
        students1_.name as name3_6_2_,
        students1_.student_no as student_4_6_2_ 
    from
        group_class groupclass0_ 
    left outer join
        student students1_ 
            on groupclass0_.id=students1_.group_class_id 
    where
        groupclass0_.id=? 
    order by
        students1_.name desc

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/39338.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

汽车Automotive > SOME/IP应用学习

目录 SOME/IP介绍 SOME/IP主要功能 SOME/IP协议 SOME/IP服务类型 SOME/IP-举例 SOME/IP各模块协议 SOME/IP-基础元件 SOME/IP-SoAD SOME/IP-SD协议 SOME/IP-SD举例 SOME/IP-TP协议 SOME/IP-TP举例 SOME/IP介绍 SOME/IP ( Scalable service-Oriented Middleware ove…

面向大规模队列,百万并发的多优先级消费系统设计

大规模队列的核心诉求&#xff0c;不仅需要「快」&#xff0c;还需要兼顾「公平」。01 引言 HTTP是一种常用的通信协议&#xff0c;除了常见网站访问、上传下载&#xff0c;HTTP协议还经常被用在消息推送场景上。 设想你搭建了一个电商平台&#xff0c;有很多大型商家入驻了该…

Kotlin协程Flow浅析

Kotlin协程中的Flow主要用于处理复杂的异步数据&#xff0c;以一种”流“的方式&#xff0c;从上到下依次处理&#xff0c;和RxJava的处理方式类型&#xff0c;但是比后者更加强大。 Flow基本概念 Flow中基本上有三个概念&#xff0c;即 发送方&#xff0c;处理中间层&#x…

HTML+CSS大作业 (水果之家10个网页)

&#x1f380; 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

数字验证学习笔记——SystemVerilog芯片验证11 ——类的继承

一、类和继承 类的第二核心要素&#xff0c;即类的“继承”&#xff0c;继承也符合我们认识实际的观点&#xff0c;在自然界和科学界我们对世界的认识无外乎归纳法和演绎法。 归纳论证是一种由个别到一般的论证方法。它通过许多个别的事例或分论点&#xff0c;然后归纳出它们所…

17、Mybatis获取参数值的情况3(若mapper接口方法的参数为多个时,可以手动将这些参数放入map中存储)

Mybatis获取参数值的情况3&#xff08;若mapper接口方法的参数为多个时&#xff0c;可以手动将这些参数放入map中存储&#xff09; 第一步&#xff1a; 第二步&#xff1a; 第三步&#xff1a;

Linux系统tcp连接设置

目录net.ipv4.tcp_syn_retriesnet.ipv4.ip_local_port_rangenet.ipv4.tcp_net.core.somaxconnnet.ipv4.tcp_max_syn_backlognet.core.netdev_max_backlognet.ipv4.tcp_synack_retriesnet.ipv4.tcp_abort_on_overflownet.ipv4.tcp_syncookiesnet.ipv4.tcp_fastopennet.ipv4.tcp_…

兆易创新GD32 (四)FreeRTOS 移植 与 CMSIS OS2

可以完全参考STM32系列的方法 FreeRTOS 逛网下载 FreeRTOS源码 https://www.freertos.org/a00104.html GitHub地址 https://github.com/FreeRTOS/FreeRTOS-Kernel 下载后的FreeRTOS-Kernel复制到LIB文件夹下 在KEIL中添加文件&#xff0c;首先是公共部分 添加MDK移植文件CM4F…

含抽水蓄能电站系统的调峰经济调度研究matlab程序(粒子群算法)

含抽水蓄能电站系统的调峰经济调度研究matlab程序&#xff08;粒子群算法&#xff09; 参考文献&#xff1a;抽水蓄能电站的最佳调度方案研究 调峰电源的优化调度是促进电力系统安全稳定运行&#xff0c;实现可靠供电的要措施。因为目前我国的调峰电源严重不足&#xff0c;尤其…

【畅购商城】订单模块之收货人列表

目录 构建订单服务&#xff1a;8100 收货人列表 接口 后端实现&#xff1a;JavaBean 后端实现 前端实现 构建订单服务&#xff1a;8100 步骤一&#xff1a;构建项目&#xff0c;changgou4-service-orders 步骤二&#xff1a;修改pom.xml文件&#xff0c;添加依赖 <de…

Spring核心与设计思想

文章目录Spring 是什么&#xff1f;什么是容器&#xff1f;什么是IoC&#xff1f;传统程序开发控制反转式程序开发对比总结规律理解 Spring IoCDI 概念Spring 是什么&#xff1f; 我们通常所说的 Spring 指的是 Spring Framework&#xff08;Spring 框架&#xff09;&#xff…

ignite集群

ignite集群 基础知识 集群中的结点 Ignite 是一个分布式系统&#xff0c;集群是标配功能。 集群中的 节点&#xff0c;有两类&#xff1a; 服务器结点。具备完全功能的结点。 客户端结点&#xff1a;这个我没有完全理解&#xff0c;但从编程的角度&#xff0c;我初步认为这个…

Jenkins-CentOS安装jenkins

CentOS安装jenkins jenkins适配的jdk版本是17和11 第一步&#xff1a;安装jdk11 &#xff08;1&#xff09;在oracle下载jdk11 jdk-11.0.16.1_linux-x64_bin.tar,放到非root用户的家目录下 &#xff08;2&#xff09;解压&#xff0c;tar -zxvf jdk-11.0.16.1_linux-x64_bin…

校园论坛设计(Java)——介绍篇

校园论坛设计&#xff08;Java&#xff09; 文章目录校园论坛设计&#xff08;Java&#xff09;0、写在前面1、项目介绍2、项目背景3、项目功能介绍3.1 总体设计图3.2 帖子模块3.3 学习模块3.4 个人信息模块3.5 数据报表模块3.6 校园周边模块3.7 用户管理模块3.8 登录注册模块4…

基于桶的排序之基数排序以及排序方法总结

基于桶的排序之基数排序以及排序方法总结 作者&#xff1a;Grey 原文地址&#xff1a; 博客园&#xff1a;基于桶的排序之基数排序以及排序方法总结 CSDN&#xff1a;基于桶的排序之基数排序以及排序方法总结 说明 基于桶的排序有两种&#xff0c;分别是计数排序和基数排…

智源社区AI周刊No.107:英伟达推出Magic3D;Stable Diffusion2.0发布

汇聚每周AI热点&#xff0c;不错过重要资讯&#xff01;欢迎扫码&#xff0c;关注并订阅智源社区AI周刊。英伟达推出Magic3D&#xff0c;性能超过谷歌DreamFusion近一段时间&#xff0c;让AI生成3D点云成为业界研究的重点。谷歌曾在9月提出DreamFusion&#xff0c;引起广泛关注…

【LEACH协议】最佳簇半径的无线传感器网络分簇路由算法【含Matlab源码 2087期】

⛄一、 数据融合的LEACH协议简介 1 基于自适应数据融合的LEACH协议 1.1 基本定义和概念 无线传感器网络中的一个簇可以用一个无向加权全连通图G(V,E)来表示,V是簇中所有传感器节点的集合,E使簇中两个节点之间可以直接通信。假设顶点v∈V代表簇中的一个传感器节点,边euv(u,v)∈…

合作共赢,就在2022亚马逊云科技re:Invent全球大会

一年一度的科技狂欢盛会&#xff0c;2022年亚马逊云科技re:Invent全球大会即将于北京时间2022年11月29日盛大开启&#xff01;届时全球各领域关注“云计算圈”发展的人都将齐聚一堂&#xff0c;共同聆听5大重磅嘉宾的主题演讲&#xff0c;700前沿技术话题…… 携全球合作伙伴…

APP逆向案例之(三)sign 参数破解

说明&#xff1a;某新闻APP sign 参数 抓包发现包含内容&#xff1a; url: https://124.*.*.*/api/categorynews/lists 参数&#xff1a; 其中 sign 参数是需要变化的否则访问失败&#xff0c;其余都是固定的 page: 3, size: 10, category: -2, from: -1, lng: 116.363…

快收藏!最全GO语言实现设计模式【下】

点个关注&#x1f446;跟腾讯工程师学技术导语| 继上篇【快收藏&#xff01;最全GO语言实现设计模式】&#xff0c;本文继续列出GO语言实现的经典设计模式示例&#xff0c;每个示例都精心设计&#xff0c;力求符合模式结构&#xff0c;可作为日常编码参考&#xff0c;同时一些常…