【问题标题】:How can I initialize lazy associations using Spring Data JPA when the query is specified in @Query annotation?在 @Query 注释中指定查询时,如何使用 Spring Data JPA 初始化惰性关联?
【发布时间】:2012-11-08 20:10:00
【问题描述】:

这是我的查询之前我转换为 Spring Data JPA。请注意我过去是如何使用Hibernate.initialize() 手动获取小部件的消息的。

public Object findWidget(final Widget findMe) {
    Widget widget = getJpaTemplate().execute(new JpaCallback<Widget>() {
        public Widget doInJpa(EntityManager em) throws PersistenceException {
            Query q = em.createQuery("SELECT h FROM " + entityClass.getName() + " h where h.widgetId = ? ");
            q.setParameter(1, findMe.getId());

            Widget found = (Widget)q.getSingleResult();

            //Initialize lazy associations
            if(found!= null){
                Hibernate.initialize(widget.getMessages());
            }

            return found;
        }
    });
    return widget;
}

这就是我的查询函数现在的样子。请注意,没有将 Hibernate.initialize() 放入的正文。

@Query("SELECT h FROM Widget h where h.widgetId = ?1 ")
public AccessPoint findWidget(String widgetId);

那么如何指定小部件的消息是主动获取而不是延迟获取呢?

【问题讨论】:

    标签: spring hibernate jpa spring-data-jpa


    【解决方案1】:

    尝试 fetch 连接,如下所示:

    @Query("SELECT h FROM Widget h LEFT JOIN FETCH h.messages WHERE h.widgetId = ?1 ")
    public AccessPoint findWidget(String widgetId);
    

    http://docs.oracle.com/html/E24396_01/ejb3_langref.html#ejb3_langref_fetch_joins

    【讨论】:

    【解决方案2】:

    发布此问题后不久,我意识到我正在尝试将功能放入真正属于服务层的 DAO 层。

    所以现在我在调用WidgetDAO.findWidget() 之后,在我的WidgetService 类中使用Hibernate.initialize(widget.getMessages()) 初始化惰性关联。

    我真的应该一直这样做。

    编辑:@MikeN 有一个很好的观点。 fetch join 是真正的答案,因为它独立于实现并在原始查询中获取所有必要信息。

    【讨论】:

    • 你真的不应该,因为你的显式初始化使你的代码依赖于休眠,并且比获取连接慢,因为它执行单独的查询来初始化每个连接(批量获取并不完全正确) .
    猜你喜欢
    • 2014-05-28
    • 2019-12-19
    • 1970-01-01
    • 2015-06-28
    • 1970-01-01
    • 1970-01-01
    • 2019-10-01
    • 2017-05-16
    • 2021-08-27
    相关资源
    最近更新 更多