转载

spring-boot data jpa

问题:

1、一般情况下,配置好映射@OneToOne @OneToMany @ManyToMany。

2、在配置下fetch类型,Lazy或者Eager。

3、然后from one 或者from many时候的就能正常查询。

但是以上查询,

1:在N-1或者1-1的时候,会出现两条查询sql(不管是Lazy还是Eager,只要使用one方)

对于N-1,先查询Many方实体,其次再查询one方的实体;

对于1-1,先查询当前one实体,其次再查询关联方one实体;

这两种方式性能都可以忽略不计,因为不管怎么样Lazy也好,Eager也好,都是两条sql, 其实一条sql也可以解决,下面再说,可以忽略不计

2:在1-N或者N-N的时候,会出现性能问题, 不管是Lazy还是Eager

对于1-N,先查询one方实体,其次再查询many方实体,也是两条sql(只要使用many方),

如果是Lazy,那么只查询one方实体,内存中只加载one方,而不会加载many,只在需要的时候加载,内存占用小;

如果是Eager,那么不仅加载one方,仍然要加载many方,内存占用会大,且立刻执行两条sql;

如果满足条件的one方有100个,那么也就意味着many方也需要查询100次,因为是100个(1-N),这会影响效率,应该是一条sql搞定!

为什么N-1或者1-1不会出现这种问题? 因为右边都是1啊,只查一个啊,左边再多,右边都只有一个

对于N-N,其实就是两个1-N,跟上面效果一样。

解决方法: 加fetch

示例:

@Query(value = "select b from Booking as b " +

"left join fetch b.account as a " +

"left join fetch a.userInfo as u where b.careType=?1 and b.typeId=?2")

List<Booking> findAllByCareTypeAndTypeId(Integer careType, Long typeId);

关系:Booking关联Account(ManyToOne),Account关联UserInfo(OneToOne)

结果:这个查询的结果是,不管满足条件的Booking有多个还是一个,但是同时立刻抓取出与之相关的account实体值以及account实体关联的userInfo值

适用于任意关系(1-N/N-1/1-1/N-N)

注意点:

1、第一个left join fetch后面必须跟b.account而不是Account实体!

2、第二个left join fetch后面必须跟a.userInfo而不是UserInfo实体也不是b.account.userInfo这种方式!

3、通过这种方式会无视fecth类型,避免出现多条sql,避免N-1问题

4、这种方式同样适用与N-1或者1-1,因为默认查询会出现两条sql,这种方式自始至终只会是一条sql!

完!

原文  http://www.blogjava.net/liuguly/archive/2017/11/13/432890.html
正文到此结束
Loading...