This can be achieved by keeping transaction at thread level. However u would require a shared object between all those threads. This shared object will keep a track of status of all this threads and notify them if either fails. If failure notification is recieved by this threads they themselves can throw an exception and their transaction will be rollbacked.
Example code
Code in individual threads
@Transactional(rollbackFor = Exception.class)
public void saveData(Product product, ProductStatusObject productStatusObject) throws Exception {
productDao.persist(product);
if(product.getId() == 5) {
productStatusObject.updateCounter(false);
} else {
productStatusObject.updateCounter(true);
}
if(!productStatusObject.getStatus()) {
throw new Exception();
}
}
Code in shared class
private final int totalThreads;
private int executedThreads = 0;
private Boolean finalStatus = true;
public ProductStatusObject(int totalThreads) {
this.totalThreads = totalThreads;
}
public synchronized void updateCounter(Boolean threadStatus) throws InterruptedException {
executedThreads ++;
if(!threadStatus) {
this.finalStatus = false;
}
if(totalThreads == executedThreads) {
notifyAll();
} else {
wait();
}
}
public synchronized Boolean getStatus() {
return finalStatus;
}
Here the failure condition is if any of thread is saving data with id 5 all threads will rollback their code. Else all will succeed