Issue
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;
}
Solution
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.
Answered By - Jose Luis
Answer Checked By - Candace Johnson (JavaFixing Volunteer)