2011-12-08 19 views
0

を更新2011年12月12日春にHibernateのトランザクションの例外のロールバック

アプリケーションがhere見つけることができるジェネリックDAOクラスを利用しています。

@Repositoryの使用方法についてspring manualを再読したところ、例外翻訳を処理するためにGenericDAOの実装にこれを追加する必要があるようです。

@RepositoryをGenericDAOに追加しましたが、結果は変更されませんでした。親オブジェクトはまだデータベースに保持されています。

私は私の取引は例外が発生した場合に正しくロールバックされますことを確認するためにいくつかのテストをやって春2.5.6、その休止バージョン、春のMVCでのJBoss 5.1、MySQLの

を使用して


。以下のコードでは、2番目のメソッド:createProfileはメソッドの完了を妨げるNullPointerExceptionをスローします。私はその取引がロールバックされることを期待していました。私が探しているのは、ユーザーオブジェクトがデータベースに保持されているということです。私が望むのは、2番目の操作が失敗した場合、最初の操作もロールバックする必要があるということです。

私は親メソッドのREQUIRED_NEWへの伝播を変更したが、動作に変更は見られなかったいくつかの変更を行いました。

私は春の取引のログを有効にしました。

私は別の投稿を見直して、what spring has to say on transactions as wellを確認しています。私はトランザクションの行為に沿って何かが欠けているようです。

私はここで間違っています。

私は次のように定義さ

@Transactional(propagation = Propagation.SUPPORTS) 
    public class ProfileServiceImpl implements ProfileService 
    { 

     @Transactional(propagation=Propagation.REQUIRED, readOnly=false) 
     public boolean createProfile(UserDTO pUserDTO, ContactInfoDTO pContactInfoDTO) 
     { 
      boolean retVal = false; 

      if(this.createProfile(pUserDTO)) 
      { 
       if(this.addAddressToUser(pContactInfoDTO, pUserDTO.getId())) 
       { 
        retVal = true; 
       } 
      } 
      return retVal; 
     } 

    @Transactional(propagation=Propagation.REQUIRED, readOnly=false) 
    public boolean createProfile(UserDTO userDTO) 
    { 
     boolean retVal = false; 

     if(this.getProfileQueries().isLoginUnique(userDTO.getLogin(),userDTO.getSiteInfoId())) 
     { 
      User user = new User(); 
      BeanUtils.copyProperties(userDTO, user); 
      user.setPassword(this.stringDigester.digest(userDTO.getPassword())); 
      user.setSiteInfo(this.getSiteInfoDao().read(userDTO.getSiteInfoId())); 
      user.setSecurityLevel(SecurityLevel.ROLE_USER); 
      user.setStatus(Status.ACTIVE); 

      Long pk = this.getUserDao().create(user); 
      userDTO.setId(pk); 

      retVal = true; 
     } 
     return retVal; 
    } 
    @Transactional(propagation=Propagation.REQUIRED, readOnly=false) 
    public boolean addAddressToUser(ContactInfoDTO pAddress, Long pProfileId) 
    { 
     boolean retVal = false; 

     if(null != pAddress && null != pProfileId) 
     { 
      ContactInfo contactInfo = new ContactInfo(); 
      BeanUtils.copyProperties(pAddress, contactInfo); 

      User user = this.getUserDao().read(pProfileId); 
      contactInfo.setUser(user); 
      this.getContactInfoDao().create(contactInfo); 

      user.getUserAddress().setProfileAddress(contactInfo); 
      user.getUserAddress().setBillingAddress(contactInfo); 
      this.getUserDao().update(user); 

      retVal = true; 

     } 
     return retVal; 
    } 
} 

データ設定

 <!-- TRANSACTION MANAGER--> 
     <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 
     <property name="sessionFactory" ref="sessionFactory" /> 
     </bean> 

     <!-- ANNOTATION DRIVEN TRANSACTIONS --> 
     <tx:annotation-driven transaction-manager="transactionManager" /> 


    <bean id="jndiDataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> 
    <property name="jndiName" value="java:/MySqlDS"/> 
    </bean> 

    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> 
    <property name="dataSource" ref="jndiDataSource"/> 
    <property name="annotatedClasses"> 
     <list> 
     <value>com.vsg.dataaccess.user.entity.User</value> 
     <value>com.vsg.dataaccess.user.entity.ContactInfo</value> 
     <value>com.vsg.dataaccess.user.entity.UserAddress</value> 
    </list> 
    </property> 


    <property name="hibernateProperties"> 
     <props> 
     <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> 
     <prop key="hibernate.hbm2ddl.auto">update</prop> 
     <prop key="hibernate.show_sql">${hibernate.show_sql}</prop> 
     <prop key="hibernate.format_sql">${hibernate.format_sql}</prop> 
     <prop key="hibernate.use_sql_comments">${hibernate.use_sql_comments}</prop> 
     <prop key="hibernate.jdbc.batch_size">20</prop> 
     <prop key="hibernate.cache.provider_class">net.sf.ehcache.hibernate.SingletonEhCacheProvider</prop> 
     <prop key="net.sf.ehcache.configurationResourceName">ehcache.xml</prop> 
     <prop key="hibernate.cache.use_second_level_cache">true</prop> 
     <prop key="hibernate.cache.use_structured_entries">true</prop> 
     <prop key="hibernate.cache.use_query_cache">true</prop> 
     <prop key="hibernate.generate_statistics">true</prop> 
     <prop key="org.hibernate.envers.audit_table_suffix">_aud</prop> 
     <prop key="org.hibernate.envers.revision_field_name">rev_number</prop> 
     <prop key="org.hibernate.envers.revision_type_field_name">rev_type</prop> 
     <prop key="org.hibernate.envers.revision_on_collection_change">true</prop>   
     </props> 
    </property> 
    <property name="entityInterceptor"> 
     <bean class="vsg.ecotrak.dataaccess.framework.hibernate.interceptor.AuditTrailInterceptor"/> 
    </property> 
    </bean> 
+0

実際にメソッドをどのように呼び出すかを確認する必要があります。実際にプロキシの境界を越える前に、サービスが自己呼び出しして例外をキャッチしていると推測できます。 (コンテキストがちょうど間違って設定されていて、トランザクションマネージャがentitymanagerファクトリに接続されていないので、自動コミットモードでユーザを作成しています) – Affe

+0

コントローラクラスからメソッドが呼び出されています – boyd4715

+0

UserDao - 休止状態のセッションをどのように管理していますか。あなたはhibernateTemplateを使用していますか? – gkamal

答えて

0

を持っている(これがあることを意味するクラスのインスタンスがProfileServiceImplがSpringのAOPプロキシによって包まれる(IDEでデバッグモードで)確認してくださいSpringトランザクションが正しく設定されているかどうか)、トランザクションマネージャとデータソース(*など)の* .xml設定も提供してください。

0

私は自動コミットが問題の原因となります。 2番目に失敗したときに最初のクエリでロールバックしたい場合は、トランザクションをオフにしてトランザクションを手動で管理する必要があります。それ以外の場合、最初のクエリは自動的にコミットされます。これについて考えます 。