即使在 HQL 查询中使用 Join Fetch,休眠延迟初始化异常

Posted

技术标签:

【中文标题】即使在 HQL 查询中使用 Join Fetch,休眠延迟初始化异常【英文标题】:Hibernate Lazy Initialization exception even using Join Fetch in HQL queries 【发布时间】: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 中获取一些嵌套元素时会发生这种情况吗? 您可以使用动态实体图可能是更好的解决方案,如果您需要定义一个用例特定的图。如果加入提取不起作用。 【参考方案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 的全部意义在于解决这个问题。

以上是关于即使在 HQL 查询中使用 Join Fetch,休眠延迟初始化异常的主要内容,如果未能解决你的问题,请参考以下文章

HQL Fetch Join 不知道对象实现

HQL连接查询和注解

Hibernate left join fetch 对子集执行附加查询

hibernate hql update操作

Hibernate--抓取策略

如何使用“构造函数”在“选择子句”中为多个表的选定列编写HQL JOIN查询