有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java DropWizard Hibernate doc想说什么?

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

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

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

Important

The Hibernate session is closed before your resource method’s return value (e.g., the Person from the database), which means your resource method (or DAO) is responsible for initializing all lazily-loaded collections, etc., before returning. Otherwise, you’ll get a LazyInitializationException thrown in your template (or null values produced by Jackson).

首先The Hibernate session is closed before your resource method’s return value。这怎么可能?如果在我的资源的return语句周围有一个try-finally块,这是可能的,但这里不是这样

我的资源应该被另一个方法调用,我猜它会在调用我的资源方法之前打开Hibernate会话,然后在我的资源方法返回后关闭会话。它怎么能在我的方法返回之前关闭它呢。我不明白

最重要的是,我没有冬眠的经验。我现在是第一次使用它。我该如何初始化,或者更确切地说,在Hibernate上下文中“初始化”的确切含义是什么?一个代码示例将非常有用

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

编辑: 添加了文档中的代码块,否则任何人都无法理解。我还从问题中删除了一段,这在我发帖后立即变得清晰起来


共 (1) 个答案

  1. # 1 楼答案

    First The Hibernate session is closed before your resource method’s return value. How is this possible? This would have been possible had there been a try-finally block around my resource's return statement, but that is not the case here.

    我对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.beforeStart(unitOfWork)unitOfWorkAspect.afterEnd()来自源UnitOfWorkAspect

    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();
            }
    
        }
    }
    

    The most important part - which means your resource method (or DAO) is responsible for initializing all lazily-loaded collections, etc., before returning. I have no Hibernate experience. I am using it for the first time now. How do I initialize, or rather what is exactly is meant by "initialize" in context of Hibernate?

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

    一,。例如,使用渴望加载

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

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

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