[英]DB constraint violation not throwing Exception in Hibernate
我有以下代碼:
try {
userDAO1.save(userRecord);
userDAO2.save(userRecord);
}
catch(DataIntegrityViolationException e) {
throw new ApplicationException("Contraint violated")
}
userDAO1.save(userRecord)違反了完整性約束-因此,在運行了整個代碼之后,沒有任何內容寫入到userDAO1所引用的表中。
但是,userDAO1.save()語句不會引發錯誤/異常-因此,也會執行userDAO2.save()。
但是捕獲了DataIntegrityViolationException,並且堆棧跟蹤為null 。
如何檢查從何處拋出DataIntegrityViolationException,並在userDAO1.save()違反約束的情況下阻止執行userDAO2.save()?
我嘗試在此代碼周圍添加@Transactional批注,但這也不起作用。
堆棧跟蹤:
org.springframework.dao.DataIntegrityViolationException: ORA-00001: unique constraint (UNIQUE_EMAIL) violated
; SQL [n/a]; constraint [UNIQUE_EMAIL]; nested exception is org.hibernate.exception.ConstraintViolationException: ORA-00001: unique constraint (UNIQUE_EMAIL) violated
at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:643)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:104)
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:516)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:393)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at com.sun.proxy.$Proxy76.updateUser(Unknown Source)
at com.osiris.UserReg.UpdateUserCommand.execute(UpdateUserCommand.java:63)
我發布的代碼在UpdateUserCommand中,該代碼用@Transactional(rollbackFor=Exception.class, propagation=Propagation.REQUIRES_NEW)
注釋。
好的,這有點棘手,但我會盡力而為。 Hibernate僅在使用@Transactional注釋的方法退出時才提交事務。 因此,只有在該方法返回后,您的DataIntegrityViolationException才能被捕獲。 您無法讓Hibernate不調用UserDAO2.save()
因為它無法檢測到已發生沖突。 我將在下面提供一個示例
@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)
}
}
然后在您的HibernateUserDAO1中:
public void saveOrUpdate(User user){
currentSession().saveOrUpdate(user);
}
只能在服務層之上捕獲異常。 理想情況下,您要執行的操作是使用兩個不同的DAO進行個人保存,並在執行第二個操作之前檢查第一個操作是否成功。
編輯:還請注意,Hibernate將不會使用@Transactional注釋的私有方法,因為Hibernate依賴於從類實現的接口創建Proxy對象。 沒有接口定義=沒有代理對象=沒有休眠會話。 因此,您不能調用帶有@Transactional注釋的私有方法。 我將嘗試使您的SessionFactory成為抽象超類中的對象,並讓DAO都繼承自此。 更好的選擇是使用2個事務管理器,每個事務管理器都指向您的不同數據庫,然后指定要保存的數據庫內容。 這樣,您可以只使用1個DAO,並使用進行保存所需的任何會話工廠。
是什么讓您相信在執行語句userDAO1.save()時未引發DataIntegrityViolationException ? 另外,為什么您還認為語句userDAO2.save()也已執行?
如果上述意見是基於在諸如Eclipse之類的IDE調試控制台中對代碼執行進度的觀察得出的,則說明可能是錯誤的。
請嘗試通過插入一些調試語句(如下面的語句)並執行代碼來觀察結果。 這可以幫助您找出失敗的根本原因-
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")
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.