繁体   English   中英

Spring Jpa @Transactional无法正常工作

[英]Spring Jpa @Transactional not working

如果一个或多个查询失败,我试图实现事务回滚。 所以我在服务实现类上注释了@Transactional 我明知发送了错误的数据类型amountpaid1(在这种情况下为String,Double是正确的数据类型)。

但是现在,我的第一个更新查询加上在challan上的插入已成功完成。
第二个查询,即query1无法更新,因为它接收到错误的数据类型,因此我希望整个事务回滚。

知识库

@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>

如果从Transactional方法抛出异常,则事务将回滚。

运行时异常的回滚是自动的。

需要明确配置检查异常的回滚。

当您捕获其中的所有异常时,您的Transactional方法绝不会引发异常。 因此,您需要从catch块中抛出或重新抛出。

@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框架的事务基础结构指示要回滚事务的建议方法是从事务上下文中当前正在执行的代码中引发Exception。 Spring Framework的事务基础结构代码将在气泡堆积到调用堆栈时捕获任何未处理的Exception,并确定是否将事务标记为回滚。

在默认配置中,Spring框架的事务基础结构代码仅在运行时,未经检查的异常的情况下将事务标记为回滚。 也就是说,当抛出的异常是RuntimeException的实例或子类时。 (默认情况下,错误也会导致回滚)。 从事务方法引发的检查异常不会导致默认配置中的回滚。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM