随笔-95  评论-31  文章-10  trackbacks-0
问题:
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;
       如果一条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!


完!
posted on 2017-11-13 18:12 朔望魔刃 阅读(428) 评论(0)  编辑  收藏 所属分类: java

只有注册用户登录后才能发表评论。


网站导航:
博客园   IT新闻   Chat2DB   C++博客   博问