I have the following code:
try {
userDAO1.save(userRecord);
userDAO2.save(userRecord);
}
catch(DataIntegrityViolationException e) {
throw new App
Ok, this is a bit of a tricky one, but I'll do my best.
Hibernate will only commit a transaction when the method annotated with @Transactional exits. Hence your DataIntegrityViolationException will only be catchable after that method returns. There is no way that you can get Hibernate to not call UserDAO2.save()
because it can't detect that a violation has occurred. I'll provide an example below
@Service
/*These variable names are used for clarity's sake, I don't actually use these names myself*/
public UserServiceImpl implements UserService{
@Autowired
private HibernateUserDAO1 userDao1;
@Autowired
private HibernateUserDAO2 userDao2
@Transactional
/*Put your try catch block around where this method is called*/
public void saveUserDao1(User user){
userDao1.saveOrUpdate(user);
}
@Transactional
/*Only call this if saveUserDao1 succeeds*/
public void saveUserDao2(User user){
userDao2.saveOrUpdate(user)
}
}
Then in your HibernateUserDAO1:
public void saveOrUpdate(User user){
currentSession().saveOrUpdate(user);
}
The exception can only be caught above your service layer. Ideally what you want to be doing, is individual saves using 2 different DAO's and checking that the first succeeded before doing the second.
EDITED: Also be aware that Hibernate will not pick up private methods annotated with @Transactional because Hibernate depends on creating Proxy objects from the interface that your class implements. No interface definition = no proxy object = no Hibernate Session. So you can't call a private method annotated with @Transactional. I'd try to make your SessionFactory an object in an abstract superclass and have both DAO's inherit from this. A better option is to use 2 transaction managers each pointing to your different databases, then specify which database things are saving too. That way you can use just 1 DAO, and use whichever session factory you require to do your saves.
What made you to believe that DataIntegrityViolationException was not thrown while the statement userDAO1.save() was executed? Also, why do you believe that the statement userDAO2.save() was executed as well?
If the above opinions were made upon observations of code execution progression in an IDE debug console such as that of Eclipse then the interpretations might be wrong.
Please try to observe the results by punching-in some debug statements like the ones below, and executing the code. This may help you to find out the root cause of the failure -
try {
userDAO1.save(userRecord);
System.out.println("-- After userDAO1.save(userRecord) --");
userDAO2.save(userRecord);
System.out.println("-- After userDAO2.save(userRecord) --");
} catch(DataIntegrityViolationException e) {
e.printStackTrace();
throw new ApplicationException("Contraint violated")
}