为什么我的集合初始化不起作用?

时间:2017-01-19 15:23:05

标签: java spring hibernate jpa orm

我有一个用@Transactional注释的服务类调用DAO层方法来返回一个对象,其中包含一个延迟加载的集合。当我尝试使用Hibernate.inititialize(..)在服务层初始化此集合时,hibernate不会加载集合。 DAO配置为使用实体管理器,对象类使用JPA注释进行注释。我有以下spring应用程序上下文..

<beans xmlns="http://www.springframework.org/schema/beans"...">

<orcl:pooling-datasource id="dataSource" url="..." username="..." password="..."/>

<context:annotation-config/>

<!-- Hibernate entity manager -->
<bean id="myEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
  <property name="dataSource" ref="dataSource" />
  <property name="packagesToScan" value="org.gmp.webapp.model" />
  <property name="jpaVendorAdapter">
     <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
  </property>
  <property name="jpaProperties">
     <props>
        <prop key="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</prop>  
        <prop key="hibernate.hbm2ddl.auto">update</prop>  
        <prop key="hibernate.show_sql">true</prop> 
     </props>
  </property>
 </bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
  <property name="entityManagerFactory" ref="myEmf" />
</bean>

<tx:annotation-driven transaction-manager="transactionManager" /> 

<bean id="persistenceExceptionTranslationPostProcessor"
  class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />

<bean id="dao" class="org.gmp.webapp.dao.impl.HibDAOImpl" />
</beans>

我的DAO界面和实现......

package org.gmp.webapp.dao;

import java.util.List;
import org.gmp.webapp.model.Crime;

public interface DAO {
    public Crime getCrime(String crimeNo);
}

import org.gmp.webapp.dao.DAO;
import org.gmp.webapp.model.Crime;

public class HibDAOImpl implements DAO {

    @PersistenceContext
    protected EntityManager em;

    public Crime getCrime(String crimeNo) {
        return this.em.find(Crime.class, crimeNo);
    }

}

我的对象看起来像这样..

@Entity
@Table(name="CRIME_TABLE")
public class Crime {
    @Id
    @Column(name = "CRIME_NO")
    private String crimeNo;
    @OneToMany
    @JoinColumn(name="PER_CRIME_NO", referencedColumnName="CRIME_NO")
    private List<PersonCrimeLink> personLinks;
    ....
    public List<PersonCrimeLink> getPersonLinks() {
        return personLinks;
    }
}

服务类用transactional(spring)注释,所以我认为对DAO的调用和初始化是在同一个事务中,这应该有效。 我的服务..

@Service
@Transactional(readOnly=true)
public class CrimeServiceImpl implements CrimeService {

    @Autowired private CrimeDAO crimeDAO;

    public Crime getCrime(String crimeNo) {
        Crime crime = crimeDAO.getCrime(crimeNo);
        Hibernate.initialize(crime.getPersonLinks());
        return crime;
    }
}

当我对DAO方法进行测试时,在调用集合的getter时会加载该集合。我用@Transactional注释了测试方法。 personLinks对象被省略,但就像我说它返回测试中的记录。我认为我不理解我正在使用的事务管理器,因为当我使用会话工厂和HibernateTransactionManager时此过程有效。 非常感谢您提供任何指导。

1 个答案:

答案 0 :(得分:1)

这是一个快速提示,因为您决定使用JPA的EntityManagerFactory而不是Hibernate的SessionFactory作为您的orm API,那么我会在应用程序的其他层上坚持使用该API。

也就是说,使用EntityManager获取数据然后切换到使用实现API(Hibernate.initialize)并不是一致/可维护的方法。

就像你在帖子中所说的那样,如果你坚持使用JPA规范,这是第一次访问时初始化集合,那么你不会收到任何错误并加载列表:

  

LAZY策略是对持久性提供程序运行时的暗示   首次访问时应该懒洋洋地获取数据

从JPA规范开始,您只需要这样做:

public Crime getCrime(String crimeNo) {
        Crime crime = crimeDAO.getCrime(crimeNo);
        crime.getPersonLinks().size(); // any access method
        return crime;
    }