簡體   English   中英

數據庫約束違規未在Hibernate中引發異常

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM