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