Dropwizard-Hibernate doc试图说什么?

时间:2016-05-03 20:14:29

标签: java hibernate dropwizard

我遇到了LazyInitializationException然后我遇到了来自官方doc的以下段落。不幸的是,这对我来说毫无意义。请帮忙。

(文档中段落上方的代码块)

@GET
@Timed
@UnitOfWork
public Person findPerson(@PathParam("id") LongParam id) {
    return dao.findById(id.get());
}
  

重要

     

在资源方法返回之前,Hibernate会话已关闭   值(例如,数据库中的Person),表示您的资源   方法(或DAO)负责初始化所有延迟加载的   收藏品等,在返回之前。否则,你会得到一个   在模板中抛出LazyInitializationException(或null值   杰克逊制作。

首先The Hibernate session is closed before your resource method’s return value。这怎么可能?如果围绕我的资源返回语句有try-finally块,这本来是可能的,但这不是这种情况。

我的资源应该由另一个方法调用,我猜测在调用资源方法之前会打开Hibernate会话,然后在我的资源方法返回后关闭会话。如何在我的方法返回之前关闭它。我不明白。

最重要的部分 - which means your resource method (or DAO) is responsible for initializing all lazily-loaded collections, etc., before returning.我没有Hibernate经验。我现在是第一次使用它。我如何初始化,或者更确切地说是"初始化"在Hibernate的背景下?代码示例将有很多帮助。

PS :这个问题可能看起来很奇怪,粗略看一眼的人甚至可能会建议将其移至"英语语言和用法",但请仔细阅读。这是一个技术问题,而不是段落剖析。

修改 添加了文档中的代码块,否则它对任何人都没有意义。此外,我在发布问题后立即从我的问题中删除了一个段落,这个段落很明显。

1 个答案:

答案 0 :(得分:2)

  

首先在资源方法之前关闭Hibernate会话   回报价值。这怎么可能?这本来是可能的   围绕我的资源返回声明进行了try-finally阻止,   但这不是这种情况。

我对Dropwizard一无所知。所以,让我们看一下来源(我稍微改变一下)。

来自UnitOfWorkAwareProxyFactory

class UnitOfWorkAwareProxyFactory {

public <T> T create(Class<T> clazz) {
        final ProxyFactory factory = new ProxyFactory();
        factory.setSuperclass(clazz);

        final Proxy proxy = (Proxy) factory.createClass().newInstance();

        proxy.setHandler(new MethodHandler() {
            @Override
            public Object invoke(Object self, Method overridden, 
                    Method proceed, Object[] args) {
                final UnitOfWork unitOfWork = overridden.getAnnotation(UnitOfWork.class);
                final UnitOfWorkAspect unitOfWorkAspect = new UnitOfWorkAspect(sessionFactories);
                try {
                    unitOfWorkAspect.beforeStart(unitOfWork);
                    Object result = proceed.invoke(self, args);
                    unitOfWorkAspect.afterEnd();
                    return result;
                } catch (Exception e) {
                    unitOfWorkAspect.onError();
                    throw e;
                }
            }
        });
        return (T) proxy;
}

}

如果你有一个班级

class PersonDao {

    @UnitOfWork
    public Person findPerson(LongParam id) {
        return dao.findById(id.get());
    }

}

你可以做这样的事情

UnitOfWorkAwareProxyFactory factory = new UnitOfWorkAwareProxyFactory();

PersonDao proxy = factory.create(PersonDao.class);

当你做

Person person = proxy.findPerson(1L);

该行变为

unitOfWorkAspect.beforeStart(unitOfWork);
Object result = findPerson.invoke(proxy, 1L);
unitOfWorkAspect.afterEnd();

return result;  

来自来源UnitOfWorkAspect

的方法unitOfWorkAspect.beforeStart(unitOfWork)unitOfWorkAspect.afterEnd()
class UnitOfWorkAspect {

    public void beforeStart(UnitOfWork unitOfWork) {
        session = sessionFactory.openSession();

        configureSession();
        beginTransaction();
    }

    public void afterEnd() {
        try {
            commitTransaction();
        } catch (Exception e) {
            rollbackTransaction();
            throw e;
        } finally {
            session.close();
        }

    }
}
  

最重要的部分 - 这意味着您的资源方法(或DAO)负责在返回之前初始化所有延迟加载的集合等。我没有Hibernate经验。我现在是第一次使用它。我如何初始化,或者更确切地说是&#34;初始化&#34;在Hibernate的背景下?

在此上下文中初始化意味着应从数据库加载集合数据。一些初始化方法

1.使用急切加载,例如

class User {

  @ManyToMany(fetch = FetchType.EAGER)
  private List<Role> roles; 

}

当你获得roles实体时,Hibernate将通过连接或子选择加载User

  1. 使用Hibernate.initialize(user.getRoles())
  2. 在HQL中使用join fetch - from User user left join fetch user.roles
  3. CriteriasetFetchMode()
  4. 一起使用
  5. 使用获取配置文件,实体图表。不知道实体图可以与会话一起使用,它是JPA功能:http://docs.jboss.org/hibernate/orm/5.1/userguide/html_single/chapters/fetching/Fetching.html
  6. 如果您不需要获取集合,则可以使用部分对象加载并转换为根实体:How to transform a flat result set using Hibernate