// 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();
Jpa中常见的问题和解决方案
最新推荐文章于 2024-07-13 18:10:19 发布