这篇文章主要介绍“Spring JPA联表查询之OnetoOne源码分析”,在日常操作中,相信很多人在Spring JPA联表查询之OnetoOne源码分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Spring JPA联表查询之OnetoOne源码分析”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
源码
@OnetoOne 注解实现一对一关系映射。比如用户跟车辆的关系(这里假设一个人只能有一辆车),一个用户只能对应一辆车,而一辆车同样只能对应一个用户。
老规矩,在实例之前,我们先看看源码:
public @interface OnetoOne { Class targetEntity() default void.class; CascadeType[] cascade() default {}; FetchType fetch() default EAGER; String mappedBy() default ""; boolean orphanRemoval() default false; }
注解属性
cascade:(可选)当前类对象操作后级联对象的操作。默认为不级联任何操作。
fetch:(可选)关联是否延迟加载或者立刻加载。立刻加载是立刻获取关联的实体;延迟加载是表示关系类在被访问时才加载。默认值EAGER,也就是立刻加载。
mappedBy:(可选)拥有关联关系的域,如果关系是单向的就不需要;如果是双向关系表,那么拥有关系的这一方有建立、解除和更新与另一方关系的能力,而另一方没有,只能被动管理,这个属性被定义在关系的被拥有方
单向联表
我这里所说的单向联表就是只有一方添加注解;通俗讲就是我可以通过 user 获取到其 car 的信息,而不同通过 car 获取到其 user 的信息。
user 实体类
@Entity @Data public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; private String name; private int age; @OnetoOne @JoinColumn(name = "car_id") private Car car; }
car 实体类
@Data @Entity public class Car { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; private String name; }
执行请求 /user/findById?id=1
,控制台打印如下:
Hibernate: select user0_.id as id1_1_0_, user0_.age as age2_1_0_, user0_.car_id as car_id4_1_0_, user0_.name as name3_1_0_, car1_.id as id1_0_1_, car1_.name as name2_0_1_ from user user0_ left outer join car car1_ on user0_.car_id=car1_.id where user0_.id=?
查询结果
Optional[User(id=1, name=lili, age=11, car=Car(id=1, name=苏A00001))]
从上面的 JPQL 语句我们可以发现,uer 表 和 car 表 是通过left outer jion
进行连接的。这样我们可以通过查询 user 信息来获取其使用的 car 信息。
双向联表
我们除了需要通过 user 信息来获取其 car 信息为,有时还需要通过 car 信息来获取其 user 信息。只要再在 car 的实体中添加 user 字段,并添加@OnetoOne
注解。
user 实体
@Entity @Data public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; private String name; private int age; @OnetoOne @JoinColumn(name = "car_id") @JsonIgnore private Car car; }
car 实体
@Entity @Data public class Car { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; private String name; @OnetoOne @JoinColumn(name = "user_id") @JsonIgnore private User user; }
执行请求 /car/findById?id=1
,控制台打印如下:
Hibernate: select car0_.id as id1_0_0_, car0_.name as name2_0_0_, car0_.user_id as user_id3_0_0_, user1_.id as id1_2_1_, user1_.age as age2_2_1_, user1_.car_id as car_id4_2_1_, user1_.name as name3_2_1_, car2_.id as id1_0_2_, car2_.name as name2_0_2_, car2_.user_id as user_id3_0_2_ from car car0_ left outer join user user1_ on car0_.user_id=user1_.id left outer join car car2_ on user1_.car_id=car2_.id where car0_.id=?
查询结果
Optional[Car(id=1, name=苏A00001, user=com.example.sbjdemo.pojo.User@1c0775ea)]
用户信息可以通过后面的实体类获取
延迟加载(懒加载)
上面是 OnetoOne 的情形,所以请求出来的数据也是比较有限的。试想一下,如果是 OnetoMany,而我们只想获取 one 的信息,但是 many 的数据却跟着一起请求出来的,无论是从数据上还是性能上来讲,都是一种负担。那么,有没有一种方法,让我们能够只获取 one 的信息,而对于 many 可以动态获取呢?这时,我们想到了源码中一个 fetch 方法,他好像可以使用 LAZY 属性来控制数据懒加载。废话少说,上码。
user 实体
User 实体类上的 Car 属性中 @OnetoOne
添加属性 fetch = FetchType.LAZY
@OnetoOne(fetch = FetchType.LAZY) @JoinColumn(name = "car_id") @JsonIgnore private Car car;
执行请求 /user/findById?id=1
,控制台打印如下:
Hibernate: select user0_.id as id1_2_0_, user0_.age as age2_2_0_, user0_.car_id as car_id4_2_0_, user0_.name as name3_2_0_ from user user0_ where user0_.id=?
查询结果:
Optional[com.example.sbjdemo.pojo.User@30c311e6]
通过控制台可以看出,只有一个用户查询的 sql,结果也就是一个 user 的实体类数据。那我们的 car 信息该如何查看呢?其实我们可以使用查询结果 result 去 get 我们所需要的数据,如下图所示:
查询完会发现,控制台又打印了一个 JPQL:
Hibernate: select car0_.id as id1_0_0_, car0_.name as name2_0_0_, car0_.user_id as user_id3_0_0_, user1_.id as id1_2_1_, user1_.age as age2_2_1_, user1_.car_id as car_id4_2_1_, user1_.name as name3_2_1_ from car car0_ left outer join user user1_ on car0_.user_id=user1_.id where car0_.id=?
恍然大悟,原来还是通过 sql 去完成的。
到此,关于“Spring JPA联表查询之OnetoOne源码分析”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程之家网站,小编会继续努力为大家带来更多实用的文章!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。