2017-09-15 74 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

相關問題