【问题标题】:Hibernate Lazy Initialization exception even using Join Fetch in HQL queries即使在 HQL 查询中使用 Join Fetch,休眠延迟初始化异常
【发布时间】:2019-02-11 07:46:44
【问题描述】:

我想用惰性获取模式初始化一个集合并在我的查询中使用 Join Fetch,但我有时(并非总是)遇到惰性初始化异常???

org.hibernate.LazyInitializationException: 延迟初始化失败 角色集合:xxx.entity.Product.producerEntities,不能 初始化代理 - 没有会话 ...

例如这个查询:

"select p from Product p left join fetch p.producerEntities"

还有我的持久性课程:

    class Product
    {
        Set<Producer> producerEntities = new HashSet<>();
        ....
        @OneToMany(fetch = FetchType.LAZY)
        @JoinColumn(name="pid")
        public Set<Producer> getProducerEntities(){
         return producerEntities;
         }
    ....

}

我不明白这是什么问题?

【问题讨论】:

  • @OneToMany 的默认获取类型是惰性的。
  • 我知道 Angad Bansode,为了清楚起见,我写了 fetch = FetchType.LAZY。
  • 您能否添加一个示例说明该异常何时发生?在Producer 中获取一些嵌套元素时会发生这种情况吗?
  • 您可以使用动态实体图可能是更好的解决方案,如果您需要定义一个用例特定的图。如果加入提取不起作用。

标签: java hibernate hql


【解决方案1】:

如果 join fetch 抛出 LIEX,那么我可以建议使用动态实体图,因为如果您需要定义特定于用例的图。

让我们试试这个,我做过并为我工作。

public class DynamicEntityGraphDemo {

    public static void main(String[] args) {

        EntityManager em = HibernateUtil.getEntityManager();
        EntityGraph graph = em.createEntityGraph(Product.class);
        Subgraph itemGraph = graph.addSubgraph("producerEntities");

        Map hints = new HashMap();
        hints.put("javax.persistence.loadgraph", graph);

        Product pro = em.find(Product.class, 1, hints);
        System.out.println("DynamicEntityGraphDemo pro  = " + pro.toString() + 
                 "producer =  " + pro.getProducerEntities().toString());
    }
}

注意:动态实体图在检索子实体时使用 LEFT OUTER JOIN。 (子图 itemGraph = graph.addSubgraph("producerEntities");)

【讨论】:

    【解决方案2】:

    加入获取 p.producerEntities,而不是 p.producer..

    【讨论】:

    • 你是对的。这只是我的语法错误(大多数时候查询工作)。
    【解决方案3】:

    问题出在我的集合 setter 和 getter 方法名称上。解决了。​​

    【讨论】:

    • 您能否详细说明您必须更改的内容。
    【解决方案4】:

    有很多方法可以解决,使用hibernate属性

    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource(); 
        return dataSource;
    }
    
    @Bean
    public LocalSessionFactoryBean getSessionFactory() throws IOException {
        LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean();
        factoryBean.setDataSource(dataSource()); 
    
        Properties hibernateProperties = new Properties(); 
        hibernateProperties.setProperty("hibernate.enable_lazy_load_no_trans", "true"); 
        factoryBean.setHibernateProperties(hibernateProperties);
        factoryBean.afterPropertiesSet();
    
        return factoryBean;
    }
    
    @Bean
    public HibernateTransactionManager getTransactionManager() throws IOException {
        HibernateTransactionManager transactionManager = new HibernateTransactionManager();
        transactionManager.setSessionFactory(getSessionFactory().getObject());
        return transactionManager;
    }
    

    或者你可以使用

    org.hibernate.annotations.@Proxy 
    
    @Entity
    @Table(name = "ACTOR")
    @Proxy(lazy = false)
    public class Actor 
    

    【讨论】:

    • "hibernate.enable_lazy_load_no_trans" 被认为是一种反模式,就像使用 n+1 查询的急切加载一样。 FetchType.LAZY 和 JOIN FETCH 的全部意义在于解决这个问题。
    猜你喜欢
    • 2012-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-10
    • 1970-01-01
    • 1970-01-01
    • 2012-07-27
    相关资源
    最近更新 更多