2017-09-15 76 views
0

我使用Spring 3.2.9将多层架构设计分解为3个模块web,service,repository。在仓库中,我定义了一个通用的DAO类,我通过其他实体特定的DAO类继承。LazyInitializationException和@Transactional不起作用

问题是,当我尝试懒惰地从服务层获取我的实体集合时,我总是得到LazyInitializationException。我曾尝试将@Transactional放在我的服务类上,但它似乎不起作用。我只能避免异常,如果我立即在DAO类方法中初始化所有惰性集合(并且仅在我使用@Transactional注释DAO类时),但我只想在商业逻辑中需要它们时才获取这些集合,而不是所有集合提前。

奇怪的是@Transactional只能在DAO层中工作,而不能在服务层中使用。我发现了一些解决此问题的方法,但我有兴趣真正取消解决并解决此问题,而不仅仅是使代码工作。

储存库模块:

@Repository 
public abstract class GenericDao<T> { 

    protected Class<T> entityClass; 

    @PersistenceContext 
    protected EntityManager entityManager; 

    ......... 

    public T findById(long id) { 
     T entity = entityManager.find(entityClass, id); 
     if (entity == null) { 
      throw new EntityNotFoundException(entityClass.getSimpleName(), id); 
     } 

     return entity; 
    } 
} 

我的服务模块服务类:

@Service 
public class UserServiceImpl implements UserService { 

    private UserDao userDao; 

    @SuppressWarnings("SpringJavaAutowiringInspection") 
    @Autowired 
    public UserServiceImpl(UserDao userDao) { 
     this.userDao = userDao; 
    } 

    @Transactional(readOnly = true) 
    @Override 
    public UserDto getUserById(long id) { 
     User user = userDao.findById(id); 

     return new UserDto(user); 
    } 

的DTO构造函数试图访问user.getTeams(),然后发生异常。取而代之的是,集合应该通过对数据库的额外查询来获取。

配置:

库配置: ......一些其他配置一样的数据源...

<!--EntityManagerFactory--> 
<bean id="entityManagerFactory" 
     class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
    <property name="dataSource" ref="dataSource"/> 
    <property name="persistenceXmlLocation" value="classpath:./META-INF/persistence.xml"/> 
    <property name="jpaVendorAdapter"> 
     <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/> 
    </property> 
    <property name="jpaPropertyMap"> 
     <map> 
      <entry key="hibernate.dialect" value="${hibernate_dialect}"/> 
      <entry key="hibernate.hbm2ddl.auto" value="${hibernate_Hbm2ddlAuto}"/> 
      <entry key="hibernate.show_sql" value="${hibernate_showSql}"/> 
      <entry key="hibernate.format_sql" value="${hibernate_formatSql}"/> 
     </map> 
    </property> 
</bean> 

的persistence.xml:

<persistence-unit name="persistenceUnit"> 
    ...other classes.. 
    <class>com.example.entity.User</class> 
    <exclude-unlisted-classes>true</exclude-unlisted-classes> 
    <properties> 
    </properties> 
</persistence-unit> 

服务配置:

<import resource="classpath*:META-INF/repositoryApplicationContext.xml"/> 

<tx:annotation-driven/> 
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
    <property name="entityManagerFactory" ref="entityManagerFactory"/> 
</bean> 
+0

检查配置。请参阅:https://stackoverflow.com/questions/10538345/spring-transactional-annotations-ignored –

+0

<属性名=” entityManagerFactory的” REF = “myEmf”/> 试试这个 – user1601401

+0

@AlanHay谢谢你,我找到了答案有 – zozo

回答

0

经过几天的头痛后找到答案。 我不得不搬到:

<import resource="classpath*:META-INF/repositoryApplicationContext.xml"/> 
<tx:annotation-driven/> 

从repositoryConfiguration.xml到调度员servlet.xml中,因为这是父Spring上下文。

感谢您的帮助。

0

它看起来像用户和他或她的团队之间的@OneToMany关联,它是懒加载的。当你将它们分配给Dto时,它仍然是代理而不是真正的集合。在那里放一个中断点,并在调试模式下看到它。请记住任何请求(获得团队或其大小使其活跃)。一种方法是在查询中获取它们,但是

entityManager.find(entityClass, id) 

没有它的选项。您可以使用

Hibernate.initialize(user.getTeams()) 
+0

是的,我知道这一点,就像调用getTeams()。size()。 – zozo

相关问题