2017-09-15 7 views
0

私は、多層アーキテクチャ設計でSpring 3.2.9を使用しており、Web、サービス、リポジトリの3つのモジュールに分かれています。リポジトリでは、私は他のエンティティ固有のDAOクラスを継承するジェネリックDAOクラスを定義しました。LazyInitializationExceptionと@Transactionalが動作しない

問題は、サービスレイヤから自分のエンティティのコレクションを取得しようとすると、常にLazyInitializationExceptionが発生することです。私はサービスクラスに@Transactionalを置こうとしましたが、うまくいかないようです。 DAOクラスのメソッドですぐにすべての遅延コレクションを初期化して(@TransactionalでDAOクラスに注釈を付ける場合のみ)例外を避けることができますが、それらはすべてbussinessロジックで必要とされるときにのみ取得したいあらかじめ。

@TransactionalはDAOレイヤーでのみ動作しますが、使用すべきサービスレイヤーでは動作しないというのは奇妙なことです。私はこの問題を回避する方法をいくつか見つけましたが、私は本当にこの問題を軽視し解決することに興味があり、コードを作るだけではありません。

リポジトリMODULE:

@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を(アクセスしようとする)と、例外が発生します。その代わりに、DBへの追加のクエリを使用してコレクションを取得する必要があります。

構成:

リポジトリの構成: ......データソースのようないくつかの他の構成...

<!--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からその親Springコンテキストであるため、-servlet.xmlをディスパッチャに: は、私が移動しなければなりませんでした。

ありがとうございました。

0

ユーザーと遅延ロードされているチームとの間の@OneToManyの関連付けのように見えます。それらをDtoに割り当てると、まだプロキシではなく実際のコレクションになります。そこにブレークポイントを置き、デバッグモードで参照してください。どんな要請にも気をつけてください(チームやそのサイズを生かしてください)。 1つの方法はクエリで取得することですが、

entityManager.find(entityClass, id) 

にはオプションがありません。あなたが使用するかもしれない

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

はい、それはgetTeams()。size()を呼び出すのと同じです。 – zozo

関連する問題