Java 数据库约束冲突未在Hibernate中引发异常
我有以下代码:Java 数据库约束冲突未在Hibernate中引发异常,java,spring,hibernate,jpa,Java,Spring,Hibernate,Jpa,我有以下代码: try { userDAO1.save(userRecord); userDAO2.save(userRecord); } catch(DataIntegrityViolationException e) { throw new ApplicationException("Contraint violated") } save(userRecord)违反了完整性约束,因此在整个代码运行之后,就不会向userDAO1引用的表写入任何内容 但是,userDA
try {
userDAO1.save(userRecord);
userDAO2.save(userRecord);
}
catch(DataIntegrityViolationException e) {
throw new ApplicationException("Contraint violated")
}
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(rollboor=Exception.class,propagation=propagation.REQUIRES\u NEW)注释是什么让您相信在执行语句userDAO1.save()时没有抛出DataIntegrityViolationException?另外,为什么您认为语句userDAO2.save()也被执行了
如果上述观点是在IDE调试控制台(如Eclipse)中对代码执行进度进行观察后得出的,那么解释可能是错误的
请尝试通过插入一些调试语句(如下面的语句)并执行代码来观察结果。这可能有助于您找出故障的根本原因-
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")
}
是什么让您相信在执行语句userDAO1.save()时没有抛出DataIntegrityViolationException?另外,为什么您认为语句userDAO2.save()也被执行了
如果上述观点是在IDE调试控制台(如Eclipse)中对代码执行进度进行观察后得出的,那么解释可能是错误的
请尝试通过插入一些调试语句(如下面的语句)并执行代码来观察结果。这可能有助于您找出故障的根本原因-
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")
}
好吧,这有点棘手,但我会尽力的。
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进行单独保存,并在执行第二个DAO之前检查第一个DAO是否成功
编辑:
还请注意,Hibernate不会选择带有@Transactional注释的私有方法,因为Hibernate依赖于从类实现的接口创建代理对象。无接口定义=无代理对象=无休眠会话。因此,您不能调用带有@Transactional注释的私有方法。我将尝试使您的SessionFactory成为抽象超类中的对象,并使两个DAO都继承自此。更好的选择是使用两个事务管理器,每个事务管理器指向不同的数据库,然后指定要保存的数据库。这样,您可以只使用1个DAO,并使用您需要的任何会话工厂进行保存。好的,这有点棘手,但我会尽全力。
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进行单独保存,并在执行第二个DAO之前检查第一个DAO是否成功
编辑:
还请注意,Hibernate不会选择带有@Transactional注释的私有方法,因为Hibernate依赖于从类实现的接口创建代理对象。无接口定义=无代理对象=无休眠会话。因此,您不能调用带有@Transactional注释的私有方法。我将尝试使您的SessionFactory成为抽象超类中的对象,并使两个DAO都继承自此。更好的选择是使用两个事务管理器,每个事务管理器指向不同的数据库,然后指定要保存的数据库。这样,您可以只使用1个DAO,并使用您需要的任何会话工厂进行保存。请阅读save()或persist()或merge()的javadoc或DAO.save()方法中调用的任何内容。调用此方法时,它不会告诉您是否执行了插入查询。我非常怀疑堆栈跟踪是否为空。将e.printStackTrace()
添加到catch块,您将看到它。并将DataIntegrityViolationException包装在您的ApplicationException中。与应答无关,但您是否正在服务层捕获DataIntegrityViolationException
exception?,查看您的代码,您似乎正在这样做。这不是个好主意。服务层与Dao层异常无关。出于发布目的,我简化了代码-有一个单独的业务层@Nizet-我添加了一个printStackStrace(),提到的唯一类是内部spring类-我没有写任何东西。请阅读save()或persist()或merge()的javadoc或DAO.save()方法中调用的任何内容。调用此方法时,它不会告诉您是否执行了插入查询。我非常怀疑堆栈跟踪是否为空。将e.printStackTrace()
添加到catch块,您将看到它。包装