栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring JPA could not initialize proxy - no Session

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring JPA could not initialize proxy - no Session

Spring JPA could not initialize proxy - no Session

JPA 通过谓词分析的方式来快速地实现数据库访问相关的操作,优点是提高了开发速度,但是如果遇到问题,排查起来会很麻烦


本次遇到的问题如下图所示:

Exception in thread "main" org.hibernate.LazyInitializationException: could not initialize proxy [org.xhliu.demo.entity.CustomerInfo#1] - no Session
	at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:176)
	at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:322)
	at org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor.intercept(ByteBuddyInterceptor.java:45)
	at org.hibernate.proxy.ProxyConfiguration$InterceptorDispatcher.intercept(ProxyConfiguration.java:95)
	at org.xhliu.demo.entity.CustomerInfo$HibernateProxy$zwCU7ed1.toString(Unknown Source)
	at org.xhliu.demo.Application.main(Application.java:29)

这种异常一般发生在使用 JPA 执行一对多的连接查询的情况,这是由于在执行查询时,本次一对多的实体类字段属性可能未完成初始化,如 List、Collection 等,而此时 JPA 的持久化上下文已经被关闭了,因此抛出了 “no session” 这样的异常


解决方案:

    添加全局 JPA 配置 enable_lazy_load_no_trans

    本解决方案极度不推荐

    在全局配置文件中添加如下的配置项:

    spring:
      jpa:
        properties:
          hibernate:
            enable_lazy_load_no_trans: true
    

    如果配置了这个属性,那么 JPA 就会为每一个一对多的关联字段分配一个单独的临时 Session,使得这个字段能够通过这个临时会话拿到对应的属性。

    这是一种 ”反模式“,因为如果这么配置了,当一对多的字段属性变多时,为了维护这些临时 Session 将会给底层的连接池带来很大的压力,严重的话将会明显地影响到性能,如果有别的解决方案尽量不要使用该方案

    定义数据拉取策略

    JPA 定义了如下的获取列数据的策略:

    public enum FetchType {
        // 该策略表示数据可以被延迟获取
        LAZY,
    
        // 该策略表示必须被尽早地获取
        EAGER
    }
    

    对于一对多的集合集合属性字段,使用 EAGER 来确保能够即使获取数据,从而解决这个问题,具体使用如下所示:

    @Entity
    @Table(name = "user_info")
    public class UserInfo {
         @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "user_id", nullable = false)
        private long userId;
        
        @Basic(fetch = FetchType.LAZY)
        @Column(name = "user_phone")
        private String userPhone;
        
        @OneToMany(fetch = FetchType.EAGER)
        private Set holdingFeatures = new HashSet<>();
    
        @OneToMany(fetch = FetchType.EAGER)
        private Set bookSet = new HashSet<>();
    }
    

    @NamedEntityGrap 和 @EntityGraph

    具体使用如下所示:

    对于实体 Item:

    @Entity
    @NamedEntityGraph(
        name = "Item.characteristics",
        attributeNodes = @NamedAttributeNode("characteristics")
    )
    public class Item {
        @Id
        private Long id;
        private String name;
    
        @OneToMany(mappedBy = "item")
        private List characteristics = new ArrayList<>();
    }
    

    对于实体 Characteristic:

    @Entity
    public class Characteristic {
        @Id
        private Long id;
        private String type;
    
        @ManyToOne(fetch = FetchType.LAZY)
        @JoinColumn
        private Item item;
    }
    

    对于 JPA 接口 ItemRepository:

    public interface ItemRepository extends JpaRepository {
        @EntityGraph(value = "Item.characteristics")
        Item findByName(String name);
    }
    

    对于 JPA 接口 CharacteristicsRepository:

    public interface CharacteristicsRepository extends JpaRepository {
        @EntityGraph(attributePaths = {"item"})
        Characteristic findByType(String type);    
    }
    

    这样也可以解决由于存在的级联关系导致的 “no session” 的问题


参考:

[1] https://stackoverflow.com/questions/36583185/spring-data-jpa-could-not-initialize-proxy-no-session-with-methods-marke

[2] https://www.baeldung.com/spring-data-jpa-named-entity-graphs

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/711821.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号