2017-11-15 15 views
0

1つ以上のクエリが失敗した場合、トランザクションロールバックを達成しようとしています。私のサービス実装クラスに@Transactionalと注釈を付けました。私は意図的に間違ったデータ型amountpaid1(この場合String、Doubleは正しいデータ型です)を送信しました。Spring Jpa @ Transactional not working

今、私の最初の更新クエリとchallanへの挿入が正常に完了しました。
2番目のクエリ、つまりクエリ1が間違ったデータ型を受け取ったときに更新できないため、トランザクション全体がロールバックされることが予想されます。

リポジトリ

@Repository 
public class UpdatePaymentImpl implements UpdatePayment { 


@PersistenceContext 
EntityManager em; 

public PaymentResponse getFcgoApiResponse(FcgoUpdateParam updateParam){ 
    PaymentResponse paymentResponse = new PaymentResponse(); 
    try { 
     final String uri = "http://a.b.c.d:xxxx/FcgoApi/api/savePayment"; 
     RestTemplate restTemplate = new RestTemplate(); 
     paymentResponse = restTemplate.postForObject(uri, updateParam, 
     PaymentResponse.class); 
      if (paymentResponse.getVoucherNo() != null) { 
       int status = updatePayment(updateParam, 
       paymentResponse.getVoucherNo()); 
       if (status == 0) { 
        vc.setVoucherNo(paymentResponse.getVoucherNo()); 
       } 
      } 
    }catch (Exception ex){ 
     ex.printStackTrace(); 
     logger.info(ex.getMessage()); 
    } 
    return paymentResponse; 

} 


    @Transactional 
    public int updatePayment(FcgoUpdateParam updateParam, String voucherno){ 

     try{ 
      String amountPaid1 = updateParam.getAmountPaid(); 
      Double amountPaid=Double.parseDouble(updateParam.getAmountPaid()); 
      String masterId= updateParam.getMasterId(); 
      String advCode=updateParam.getAdvCode(); 
      long uuid = getUniqueID(); 
      logger.info("generated uuid "+uuid); 
      DateFormat dateFormat =new SimpleDateFormat("dd-MMM-yy h.mm.ss.000000000 a"); 
      SimpleDateFormat dms = new SimpleDateFormat("dd-MM-yyyy"); 
      String cdate = updateParam.getChallanDate(); 
      Date ddate= dms.parse(cdate); 
      String challandate = dateFormat.format(ddate); 
      String office = updateParam.getOffice(); 
      String username = updateParam.getUsername(); 
      Long id = getIdOnChallanTable()+1L; 

      String challanid = String.valueOf(uuid); 
      ChallanEntity challanEntity = new ChallanEntity(); 
      challanEntity.setAdvtcode(updateParam.getAdvCode()); 
      challanEntity.setAmount(amountPaid); 
      challanEntity.setName(updateParam.getName()); 
      challanEntity.setOffice(office); 
      challanEntity.setUsername(username); 
      challanEntity.setStatus(updateParam.getStatus()); 
      challanEntity.setChallandate(challandate); 
      challanEntity.setChallanid(uuid); 
      challanEntity.setChallantime("null"); 
      challanEntity.setVoucherno(voucher no); 
      Query query= em.createQuery("update 
      CandidateappearagainstadvtcodeEntity cd set 
    cd.paymentstatus='Completed',cd.amountpaid=:depoFee,cd.challanid=:challanid 
      where cd.studentmasterid=:masterid and cd.advertisementcode=:advCode"); 
      logger.info("update parameter advt code: "+updateParam.getAdvCode()); 
      query.setParameter("depoFee",updateParam.getAmountPaid()); 
      query.setParameter("challanid",challanid); 
      query.setParameter("masterid",masterId); 
      query.setParameter("advCode",advCode) 
      .executeUpdate(); 
      Query query1 =em.createQuery(" update CandidateappeartoadvtnumberEntity 
      cnd set cnd.paymentstatus='Completed', cnd.depositedfee=:depofee where 
      cnd.studentmasterid=:masterid and cnd.advertisementcode=:advcode"); 
      String masterId1= updateParam.getMasterId(); 
      String advCode1=updateParam.getAdvCode(); 

      query1.setParameter("depofee",amountPaid1); 
      query1.setParameter("masterid",masterId1); 
      query1.setParameter("advcode",advCode1) 
      .executeUpdate(); 

      em.persist(challanEntity); 
      em.flush(); 
     } 
     catch (Exception e){ 
      logger.info("update error " +e); 
      logger.info(e.getMessage()); 
      return 0; 

     } 
     return 1 ; 
    } 

    } 

サービスクラス

@Service 
    public class UpdatePaymentServiceImpl implements UpdatePaymentService { 

    @Autowired 
    UpdatePayment updatePayment; 

    @Transactional 
    public PaymentResponse getFcgoApiResponse(FcgoUpdateParam updateParam) { 
     return updatePayment.getFcgoApiResponse(updateParam); 
    } 

    } 

applicationContext.xmlを

<bean id="entityManagerFactory" class="org.springframework. 
    orm.jpa.LocalContainerEntityManagerFactoryBean"> 
    <property name="dataSource" ref="dataSource" /> 
    <property name="packagesToScan" value="com.psc" /> 
    <property name="jpaVendorAdapter"> 
     <bean class="org.springframework.orm.jpa.vendor. 
      HibernateJpaVendorAdapter" /> 
    </property> 
    <property name="jpaProperties"> 
     <props> 
      <prop key="hibernate.hbm2ddl.auto">update</prop> 
      <prop key="hibernate.dialect"> 
       org.hibernate.dialect.Oracle10gDialect</prop> 
      <prop key="hibernate.show_sql">true</prop> 
     </props> 
    </property> 
    </bean> 
    <bean id="transactionManager" 
    class="org.springframework.orm.jpa.JpaTransactionManager"> 
    <property name="entityManagerFactory" 
     ref="entityManagerFactory" /> 
    </bean> 

答えて

2

のTransact Transactionalメソッドから例外がスローされた場合、イオンはロールバックされます。

実行時例外のロールバックは自動的です。

チェック例外のロールバックを明示的に設定する必要があります。

Transactionalメソッドは、その中のすべての例外をキャッチするので、例外をスローしません。だからあなたはキャッチブロック内で投げたり、元に戻したりする必要があります。

@Transactional(rollbackFor = MyCustomException.class) // << 
public int updatePayment(FcgoUpdateParam updateParam, String voucherno) 
    throws Exception{ 

    int a = 5/0; unhandled runtime exception : transaction rolls back 

    try{ 
      //runtime exception is caught and never rethrown - no rollback 
      int a = 5/0; 
    } 
    catch (Exception e){ 
      // exception in try block re-thrown: transaction rolls back 
      // throw(e); 
    } 

    throw new MyCustomException(); //checked exception rollback only occurs if configured 

    return 1 ; 
} 

https://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/transaction.html#transaction-declarative-rolling-back

トランザクションの作業はバック 圧延される春のフレームワークのトランザクションインフラストラクチャに指示する推奨方法は、現在 で実行されているコードからの例外をスローすることですトランザクションのコンテキスト。 Springフレームワークのトランザクション インフラストラクチャコードは、コールスタックの上に のバブルが発生したときに未処理の例外をキャッチし、ロールバックのために トランザクションをマークするかどうかを決定します。

デフォルトの設定では、Spring Frameworkのトランザクション インフラストラクチャコードは、ランタイムの の場合にのみロールバックのトランザクションをマークします。つまり、スローされた例外 がRuntimeExceptionのインスタンスまたはサブクラスである場合(エラーはデフォルトで になるので、ロールバックになります)。トランザクションメソッドから がスローされたチェック例外は、デフォルトの 構成ではロールバックしません。