0
votes

I have class based config so for roll back transaction.I have used jdbcTemplate.My bean declaration are as follows:

    @Bean
    public DriverManagerDataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("oracle.jdbc.driver.OracleDriver");
        dataSource.setUrl("jdbc:oracle:thin:@192.168.1.5:1521:DCGCDB");
        dataSource.setUsername("PCA_OWNER");
        dataSource.setPassword("PCA_OWNER");

        return dataSource;
    }
<!--for transaction bean-->
@Bean
public PlatformTransactionManager txManager() {
    return new DataSourceTransactionManager(dataSource());
}

So in my Service class I have declared the @Transactional but it is not working:

@Service
public class ProcessAnexOneServiceImpl implements ProcessAnexOneService {

 @Autowired
 private SelectionCustomOfficeService selectionCustomOfficeService;

 @Autowired
 private LetterDocService letterDocService;

 @Autowired
 private LetterService letterService;

 @Override
 @Transactional
 public void insertProcessAnexOne(ProcessAnexOne processAnexOne, String entryBy) {

  BigDecimal zeroValue = new BigDecimal(0);

  Letter letter = new Letter(processAnexOne.getLetter().getLetterId(), processAnexOne.getLetter().getInout(),
   processAnexOne.getLetter().getInoutNo());
 letter.setEntryBy(entryBy);

  //1st insert Transaction happens here
  BigDecimal letterNo = letterService.insertLetter(letter);
  //1st insert Transaction ends here
  System.out.println("letterNo from db is" + letterNo);


    //2nd insert Transaction happens here 
  for (BigDecimal docId: processAnexOne.getDocId()) {
   LetterDoc letterDoc = new LetterDoc(letterNo, singledocId, null, null);

   letterDocService.insertLetterDoc(letterDoc, entryBy);


  }
 //2nd insert Transaction ends here 

   //3rd insert Transaction happens here 
  for (LetterDocOther letterDoc: processAnexOne.getLetterDocOthers()) {
   System.out.println("entered hereasfdsafsdsdfg");
   LetterDoc letterD = new LetterDoc(letterNo, letterDoc.getDocId(), null, "I",
    letterDoc.getOthersDescription());
   letterD.setEntryBy(entryBy);
   letterDocService.insertLetterDocWithDescription(letterD);
  }
 //3rd insert Transaction ends here 
 }

}

I have three transactions which will hit on three different table in this service class.So my problem is that when the 1st transaction is done and there is error in 2nd transaction,then there is no any roll back happening in 1st transaction.At that condition,I still see the data of 1st transaction in my table but error is coming in 2nd transaction. I have declared @Transaction annotation for rollback and also tried (rollbackOn=Exception.class) but it is not rollbacking the first transaction if there is error.

In my pom.xml I have added:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>4.3.7.RELEASE</version>
</dependency>

LetterServiceImpl.java

@Service
public class LetterServiceImpl implements LetterService {

    @Autowired
    private LetterDao letterDao;

    @Override
    @Transactional(rollbackOn=Exception.class)
    public BigDecimal insertLetter(Letter letter) {
        BigDecimal letter1=letterDao.saveLetter(letter);
        return letter1;
    }
}

LetterDaoImpl.java

@Override
    public BigDecimal saveLetter(Letter letter) {
        try {
        System.out.println("hitted123 here");
        SimpleJdbcCall simpleJdbcCall = new SimpleJdbcCall(jdbcTemplate).withProcedureName("PCPR_ADD_LETTER");
        Map<String, Object> inParamMap = new HashMap<String, Object>();
        System.out.println(letter.getLetterId());
        inParamMap.put("P_LETTER_NO",null);
        inParamMap.put("P_LETTER_ID",letter.getLetterId());
        inParamMap.put("P_SIGNATARY",letter.getSignatary());
        inParamMap.put("P_LETTER_BOX",letter.getLetterBox());
        inParamMap.put("P_ENTRY_BY",letter.getEntryBy());
        inParamMap.put("P_R_STATUS","I");
        inParamMap.put("P_REMINDER_YES_NO","N");

        System.out.println("hitted1234 here");
        SqlParameterSource in = new MapSqlParameterSource(inParamMap);
        System.out.println("hitted123456789 here");
        //Map<String, Object> out = simpleJdbcCall.execute(in);
        BigDecimal letterNO =  (BigDecimal) simpleJdbcCall.execute(in).get("P_LETTER_NO");

        System.out.println("hitted12345 here"+letterNO);
        return letterNO;
        } catch(Exception e) {
            e.printStackTrace();
        }
        return null;

    }
2
Show how insertLetter is defineduser7294900
the method of insertLetter is working fine which returns me a BigDecimal (number) value and is used by other methods.ashwin karki
Does it have @Transactional annotation on it and it methods?user7294900
No wait i will edit the post and see itashwin karki
ok see i have added the codesashwin karki

2 Answers

0
votes

The problem is on LetterDaoImpl.java, you are catching any exception in the method saveLetter. If you catch the exception and you don't throw it back, you don't get the rollback.

Also, you should check the annotation @Transactional because I'm pretty sure the syntax is rollbackFor() instead of rollbackOn().

For debug purposes with transactions, I usually enable the log at DEBUG level for org.springframework.jdbc.datasource.DataSourceTransactionManager.

0
votes

According to Spring Doc, Rollback is done automatically for unhandled exceptions. In this case, you are handling it so the transaction manager won't see there was an error.

On the other hand, Rollback will happen with any kind of unchecked exception(the ones extending RuntimeException) withouth need to declare them in the @Transactional annotation. However, checked annotation (the ones that you need to handle in catch blocks) needs to be declare in the @Transactional annotation.

Finally I would suggest you to add the rollback in the highest level method, that is, the one that starts the transacction, to ensure the transactional behavior.