Spring DataIntegrityViolationException – Spring DataIntegrityViolationException

最后修改: 2013年 5月 17日


1. Overview


In this article, we will discuss the Spring org.springframework.dao.DataIntegrityViolationException – this is a generic data exception typically thrown by the Spring exception translation mechanism when dealing with lower level persistence exceptions. The article will discuss the most common causes of this exception along with the solution for each one.

在这篇文章中,我们将讨论Spring org.springframework.dao.DataIntegrityViolationException – 这是一个通用的数据异常,通常由Spring异常转换机制在处理低级别的持久性异常时抛出。这篇文章将讨论这种异常最常见的原因,以及每个原因的解决方案。

2. DataIntegrityViolationException and Spring Exception Translation

2.DataIntegrityViolationException和Spring Exception翻译

The Spring exception translation mechanism can be applied transparently to all beans annotated with @Repository – by defining an exception translation bean post processor bean in the Context:


<bean id="persistenceExceptionTranslationPostProcessor" 
   class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />

Or in Java:


public class PersistenceHibernateConfig{
   public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){
      return new PersistenceExceptionTranslationPostProcessor();

The Exception translation mechanism is also enabled by default on the older persistence template available in Spring – the HibernateTemplate, JpaTemplate, etc.


3. Where Is DataIntegrityViolationException Thrown


3.1. DataIntegrityViolationException with Hibernate

When Spring is configured with Hibernate, the exception is thrown in the exception translation layer provided by Spring – SessionFactoryUtils – convertHibernateAccessException.

当Spring与Hibernate配置在一起时,异常会在Spring提供的异常转换层中抛出 – SessionFactoryUtils – convertHibernateAccessException

There are three possible Hibernate exceptions that may cause the DataIntegrityViolationException to be thrown:


  • org.hibernate.exception.ConstraintViolationException
  • org.hibernate.PropertyValueException
  • org.hibernate.exception.DataException

3.2. DataIntegrityViolationException With JPA

When Spring is configured with JPA as its persistence provider, the DataIntegrityViolationException is thrown, similar to Hibernate, in the exception translation layer – namely in EntityManagerFactoryUtils – convertJpaAccessExceptionIfPossible.

当Spring被配置为JPA作为其持久化提供者时,DataIntegrityViolationException被抛出,与Hibernate类似,在异常转换层–即在EntityManagerFactoryUtils – convertJpaAccessExceptionIfPossible

There is a single JPA exception that may trigger a DataIntegrityViolationException to be thrown – the javax.persistence.EntityExistsException.


4. Cause: org.hibernate.exception.ConstraintViolationException

4.原因 org.hibernate.exception.ConstraintViolationException

This is by far the most common cause of DataIntegrityViolationException being thrown – the Hibernate ConstraintViolationException indicates that the operation has violated a database integrity constraint.


Consider the following example – for One to One mapping through an explicit foreign key column between a Parent and Child entities – the following operations should fail:


@Test(expected = DataIntegrityViolationException.class)
public void whenChildIsDeletedWhileParentStillHasForeignKeyToIt_thenDataException() {
   Child childEntity = new Child();

   Parent parentEntity = new Parent(childEntity);


The Parent entity has a foreign key to the Child entity – so deleting the child would break the foreign key constraint on the Parent – which results in a ConstraintViolationException – wrapped by Spring in the DataIntegrityViolationException:


could not execute statement; SQL [n/a]; constraint [null]; 
nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
    at o.s.orm.h.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:138)
Caused by: org.hibernate.exception.ConstraintViolationException: could not execute statement

To solve this, the Parent should be deleted first:


public void whenChildIsDeletedAfterTheParent_thenNoExceptions() {
   Child childEntity = new Child();

   Parent parentEntity = new Parent(childEntity);


5. Cause: org.hibernate.PropertyValueException

5.原因 org.hibernate.PropertyValueException

This is one of the more common causes of the DataIntegrityViolationException – in Hibernate, this will come down to an entity being persisted with a problem. Either the entity has a null property which is defined with a not-null constraint, or an association of the entity may reference an unsaved, transient instance.


For example, the following entity has a not-null name property –

例如,以下实体有一个非空的name属性 –

public class Foo {

   @Column(nullable = false)
   private String name;


If the following test tries to persist the entity with a null value for name:


@Test(expected = DataIntegrityViolationException.class)
public void whenInvalidEntityIsCreated_thenDataException() {
   fooService.create(new Foo());

A database integrigy constraint is violated, and so the DataIntegrityViolationException is thrown:


not-null property references a null or transient value: 
nested exception is org.hibernate.PropertyValueException: 
not-null property references a null or transient value: 
	at o.s.orm.h.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:160)
Caused by: org.hibernate.PropertyValueException: 
not-null property references a null or transient value: 
	at o.h.e.i.Nullability.checkNullability(Nullability.java:103)

6. Cause: org.hibernate.exception.DataException

6.原因 org.hibernate.exception.DataException

A Hibernate DataException indicates an invalid SQL Statement – something was wrong with the statement or the data, in that particular context. For example, using or Foo entity from before, the following would trigger this exception:

Hibernate DataException 表示一个无效的SQL语句–在那个特定的环境中,语句或数据出了问题。例如,使用之前的Foo实体,下面的内容会触发这个异常。

@Test(expected = DataIntegrityViolationException.class)
public final void whenEntityWithLongNameIsCreated_thenDataException() {
   service.create(new Foo(randomAlphabetic(2048)));

The actual exception for persisting the object with a long name value is:


could not execute statement; SQL [n/a]; 
nested exception is org.hibernate.exception.DataException: could not execute statement
   at o.s.o.h.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:143)
Caused by: org.hibernate.exception.DataException: could not execute statement
	at o.h.e.i.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:71)

In this particular example, the solution is to specify the max length of the name:


@Column(nullable = false, length = 4096)

7. Cause: javax.persistence.EntityExistsException

7.原因 javax.persistence.EntityExistsException

Simillarly to Hibernate, the EntityExistsException JPA exception will also be wrapped by the Spring Exception Translation into a DataIntegrityViolationException. The only difference is that JPA itself is already high level which makes this JPA exception the only potential cause of data integrity violations.

与Hibernate类似,EntityExistsException JPA异常也会被Spring异常翻译包装成DataIntegrityViolationException。唯一不同的是,JPA本身已经是高水平的,这使得这个JPA异常成为数据完整性违规的唯一潜在原因。

8. Potentially DataIntegrityViolationException


In some cases where the DataIntegrityViolationException may be expected, another exception may be thrown – one such case is if a JSR-303 validator, such as hibernate-validator 4 or 5 exists on the classpath.

在某些情况下,DataIntegrityViolationException可能被预期,另一个异常可能被抛出–其中一个情况是如果JSR-303验证器,例如hibernate-validator 4或5存在于classpath上。

In that case, if the following entity is persisted with a null value for name, it will no longer fail with a data integrity violation triggered by the persistence layer:


public class Foo {
    @Column(nullable = false)
    private String name;


This is because the execution won’t get to the persistence layer – it will fail before that with a javax.validation.ConstraintViolationException:


Validation failed for classes [org.baeldung.spring.persistence.model.Foo] 
during persist time for groups [javax.validation.groups.Default, ]
List of constraint violations:[ ConstraintViolationImpl{
    interpolatedMessage='may not be null', propertyPath=name, 
    rootBeanClass=class org.baeldung.spring.persistence.model.Foo, 
    at o.h.c.b.BeanValidationEventListener.validate(BeanValidationEventListener.java:159)
    at o.h.c.b.BeanValidationEventListener.onPreInsert(BeanValidationEventListener.java:94)

9. Conclusions


At the end of this article, we should have a clear map to navigate the variety of causes and problems that may lead to a DataIntegrityViolationException in Spring, as well as a good grasp on how to fix all of these problems.


The implementation of all exceptions examples can be found in the github project – this is an Eclipse based project, so it should be easy to import and run as it is.

所有异常的实现都可以在github项目中找到 – 这是一个基于Eclipse的项目,所以应该很容易导入并按原样运行。