当前位置: 首页 > 面试题库 >

数据库约束违规未在Hibernate中引发异常

东方方伟
2023-03-14
问题内容

我有以下代码:

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对象。没有接口定义=没有代理对象=没有hibernate会话。因此,您不能调用带有@Transactional注释的私有方法。我将尝试使您的SessionFactory成为抽象超类中的对象,并让DAO都继承自此。更好的选择是使用2个事务管理器,每个事务管理器都指向您的不同数据库,然后指定要保存的数据库内容。这样,您可以只使用1个DAO,并使用进行保存所需的任何会话工厂



 类似资料:
  • 我正在使用Spring和Hibernate,我得到了这个例外。以下是我试图获得的:我有User和UserSettings类,它们以OneToMany和ManyToOne注释为界,如下所示: 现在,我想为用户添加设置,我是这样做的: 问题来了:UserSettings中的用户持有旧设置和新设置的集合(设置,我刚刚创建并想要添加),但旧设置持有用户的集合,其中没有新设置。我想这就是为什么我会遇到异常,

  • 我已经研究了许多其他关于不捕捉异常的问题(包括不能捕捉约束违反异常),但没有一个问题和我一样。 使用RestEasy联网和Hibernate链接Postgres db。 我有一个目标: db服务通过OutcomResource.save输出发送一个输出: 然后由OutcomRepository.save保存在db中: 当为用户发布并保存第一个结果时,它成功地保存在数据库中。如果发布了第二个结果,则

  • 我有一个MathematicsAnswer引用的实体数学。如果对数学执行post请求,我会得到一个例外,即MathsAnswer上的字段不能为空。但我确实在球场上跳了起来。拜托,我需要这个解决方案<代码>java.sql。SQLIntegrityConstraintViolationException:列'question_id'不能为空。 sql架构: 实体类: MathsAnswers.jav

  • 问题内容: 我正在使用Oracle数据库。我们的服务呼叫频繁失败。当我查看日志时,在表上看到以下异常 java.sql.BatchUpdateException:ORA-00001:违反了唯一约束(DBSCHEMA.IDX_CO_DETAILS)。 我已经检查了表上索引的索引名称DBSCHEMA.IDX_CO_DETAILS。 它不包含任何列的(INCLUDE_COLUMN为null)。我怎么知道

  • 我有一个spring项目,想在数据库中强制一个字段的唯一性,并将错误消息返回给UI。 我已经阅读了这个SO答案,它是有意义的,所以@Col的(唯一=真)使表上的约束,但不强制它。 因此,问题变成了如何创建一个@Unique注释,该注释与数据库进行检查,并在POST处理程序上向BindingResult返回错误消息。 一个例子会很棒。 更新 我尝试了以下方法来制作自定义验证器: 对象(请注意,我添加

  • 我刚接触laravel,尝试存储数据,但不断出现以下错误: 在控制器中的存储方法: 店铺请求: 数据库: 错误指向控制器: 但不确定怎么解决。请帮忙。提前谢谢。