Jpa中常见的问题和解决方案

// JPA中经常出现懒加载Lazy异常? 为什么会出现这种问题呢?
// 因为在JPA中,当前SQL执行完成之后,事务就会提交,Session就会关闭,此时懒加载的对象还没加载,Session就关闭了
// 解决方案:
//  1. fetch = FetchType.EAGER,直接提前加载
//  2. 使用open-in-view,当请求一来就开启Session,直到请求结束,关闭session,同意请求session不会立刻关闭,延长了事务的生命周期
//     缺点: 就是事务占用的事件过长,同时,如果是异步线程的话,就不适用了,因为不同的线程session不共享
//  3. 将可能发生Lazy的操作放在同一事务内,事务没有提交就不会关闭session
//     缺点: 在Controller层返回实体对象的时候,会进行JSON序列化的时候,也会触发实体的加载此时没有session,也会出现懒加载依赖
//  4. Service,Controller层不直接使用Entity,使用对应的VO和DTO来处理,这样就不会改变实体的状态,也不会出现这种情况
//  5. 对于JSON序列化,使用JSONIgnoreProperties注解以及@ToString排除会出现异常的字段


// SQL的N+1问题,一个主SQL,N个通过主ID查询的子SQL
// 1. 设置批量拉取的数据大小,默认为-1
//      spring.jpa.properties.hibernate.default_batch_fetch_size = 20
// 2 使用@BatchSize(size = 20)注解,关联查询一次性批量需要拉去的数据
//   该注解只能作用于ManyToMany注解上,他是通过"in"来完成的
//   定义批量加载集合或惰性实体的大小,加载在类上,表示其他类引用该类会被一次性加载的数据量
//   定义在方法上,表示关联的属性批量拉取的数据大小
// 3. 使用@Fetch(FetchMode.JOIN)注解完成
//      FetchMode.SELECT: 默认策略,新增一个sql查询数据,也是N+1问题
//      FetchMode.JOIN: 通过关联关系join一条sql查询出来(只能通过联合唯一键或者Id关联查询才有效果),对懒加载不起作用,因为是一条sql查询出来
//      FetchMode.SUBSELECT: 通过一条子查询完成(只能通过*ToMany的关联关系),然后主表中通过"in"来完成
// 4. 使用1+1SQL,查询出主表数据,在过滤主表的Id,再查询关联表的数据,然后在内存中过滤组装
// 5. 使用@NamedEntityGraph + @EntityGraph 解决
//  在实体类中添加: @NamedEntityGraphs({
//        // 单独处理idCard
//        @NamedEntityGraph(name = "User.idCard", attributeNodes = {
//                @NamedAttributeNode("idCard")
//        }),
//        // 单独处理roles
//        @NamedEntityGraph(name = "User.roles", attributeNodes = {
//                @NamedAttributeNode("roles"),
//        }),
//        // 单独处理addresses
//        @NamedEntityGraph(name = "User.addresses", attributeNodes = {
//                @NamedAttributeNode("addresses"),
//        }),
//        // 处理当前关联的所有对象
//        @NamedEntityGraph(name = "User.detail",
//                attributeNodes = {
//                        @NamedAttributeNode("addresses"),
//                        @NamedAttributeNode("idCard"),
//                        @NamedAttributeNode("roles")
//                }
//        )
//   })
// 在Repository接口中添加
//   @EntityGraph(value = "User.detail", type = EntityGraph.EntityGraphType.LOAD)
//   List<User> findAll();

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值