Spring DataIntegrityViolationException

1. Oversikt

I denne artikkelen vil vi diskutere våren org.springframework.dao.DataIntegrityViolationException - dette er et generisk data unntak som vanligvis kastes av våren unntak oversettelsesmekanisme når du arbeider med unntak fra utholdenhet på lavere nivå. Artikkelen vil diskutere de vanligste årsakene til dette unntaket sammen med løsningen for hver enkelt.

2. DataIntegrityViolationException og Spring Exception Translation

Oversettelsesmekanismen for vår unntak kan brukes transparent på alle bønner som er merket med @Oppbevaringssted - ved å definere et unntak for oversettelse av bønner etter prosessorbønner i sammenheng:

Eller i Java:

@Configuration public class PersistenceHibernateConfig {@Bean public PersistenceExceptionTranslationPostProcessor exceptionTranslation () {return new PersistenceExceptionTranslationPostProcessor (); }}

Oversettelsesmekanismen for unntak er også aktivert som standard på den eldre utholdenhetsmalen som er tilgjengelig om våren - HibernateTemplate, JpaTemplate, etc.

3. Hvor er DataIntegrityViolationException Kastet

3.1. DataIntegrityViolationException med dvalemodus

Når våren er konfigurert med dvalemodus, vil unntak blir kastet i unntak oversettelseslaget som er levert av SessionFactoryUtils - convertHibernateAccessException.

Det er tre mulige unntak i dvale som kan føre til DataIntegrityViolationException å bli kastet:

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

3.2. DataIntegrityViolationException Med JPA

Når Spring er konfigurert med JPA som leverandør av utholdenhet, blir DataIntegrityViolationException blir kastet, i likhet med dvalemodus, i unntakets oversettelseslag - nemlig i EntityManagerFactoryUtils - convertJpaAccessExceptionIfPossible.

Det er ett enkelt JPA-unntak som kan utløse a DataIntegrityViolationException å bli kastet - den javax.persistence.EntityExistsException.

4. Årsak: org.hibernate.exception.ConstraintViolationException

Dette er den klart vanligste årsaken til DataIntegrityViolationException blir kastet - dvalemodus ConstraintViolationException indikerer at operasjonen har brutt en begrensning for databasens integritet.

Tenk på følgende eksempel - for en til en kartlegging gjennom en eksplisitt utenlandsk nøkkelkolonne mellom a Foreldre og Barn enheter - følgende operasjoner skal mislykkes:

@Test (forventet = DataIntegrityViolationException.class) offentlig ugyldig nårChildIsDeletedWhileParentStillHasForeignKeyToIt_thenDataException () {Child childEntity = new Child (); childService.create (childEntity); Parent parentEntity = ny foreldre (childEntity); service.create (parentEntity); childService.delete (childEntity); }

De Foreldre enheten har en utenlandsk nøkkel til Barn enhet - slik at det å slette barnet vil bryte foreldrenes nøkkelbegrensning - som resulterer i en ConstraintViolationException - innpakket av våren i DataIntegrityViolationException:

org.springframework.dao.DataIntegrityViolationException: kunne ikke utføre uttalelse; SQL [ikke relevant]; begrensning [null]; nestet unntak er org.hibernate.exception.ConstraintViolationException: kunne ikke utføre uttalelse på o.s.orm.h.SessionFactoryUtils.convertHibernateAccessException (SessionFactoryUtils.java:138) Forårsaket av: org.hibernate.exception.ConstraintViolationException: kunne

For å løse dette, Foreldre bør slettes først:

@Test offentlig ugyldig nårChildIsDeletedAfterTheParent_thenNoExceptions () {Child childEntity = new Child (); childService.create (childEntity); Parent parentEntity = ny foreldre (childEntity); service.create (parentEntity); service.delete (parentEntity); childService.delete (childEntity); }

5. Årsak: org.hibernate.PropertyValueException

Dette er en av de vanligste årsakene til DataIntegrityViolationException - i dvale vil dette komme ned på at en enhet blir vedvarende med et problem. Enten har enheten en nullegenskap som er definert med en ikke null begrensning, eller en forening av enheten kan referere til et ikke-lagret, forbigående forekomst.

For eksempel har følgende enhet en ikke-null Navn eiendom -

@Entity public class Foo {... @Column (nullable = false) private Strengnavn; ...}

Hvis den følgende testen prøver å vedvare enheten med en nullverdi for Navn:

@Test (forventet = DataIntegrityViolationException.class) offentlig ugyldig nårInvalidEntityIsCreated_thenDataException () {fooService.create (ny Foo ()); }

En begrensning for databasens integrering er brutt, og så DataIntegrityViolationException blir kastet:

org.springframework.dao.DataIntegrityViolationException: ikke-null-egenskap refererer til en null eller forbigående verdi: org.baeldung.spring.persistence.model.Foo.name; nestet unntak er org.hibernate.PropertyValueException: ikke-null-egenskap refererer til en null eller forbigående verdi: org.baeldung.spring.persistence.model.Foo.name på osorm.h.SessionFactoryUtils.convertHibernateAccessException (SessionFactoryUtils.java:160). .. Forårsaket av: org.hibernate.PropertyValueException: ikke-null-egenskap refererer til en null eller forbigående verdi: org.baeldung.spring.persistence.model.Foo.name at oheiNullability.checkNullability (Nullability.java:103) ...

6. Årsak: org.hibernate.exception.DataException

Et dvale DataException indikerer en ugyldig SQL-setning - noe var galt med utsagnet eller dataene, i den spesielle sammenhengen. For eksempel ved å bruke eller Foo enhet fra før, vil følgende utløse dette unntaket:

@Test (forventet = DataIntegrityViolationException.class) offentlig endelig ugyldig nårEntityWithLongNameIsCreated_thenDataException () {service.create (ny Foo (randomAlphabetic (2048))); }

Det faktiske unntaket for å vedvare objektet med en lang Navn verdien er:

org.springframework.dao.DataIntegrityViolationException: kunne ikke utføre uttalelse; SQL [ikke relevant]; nestet unntak er org.hibernate.exception.DataException: kunne ikke utføre uttalelse på osohSessionFactoryUtils.convertHibernateAccessException (SessionFactoryUtils.java:143) ... Forårsaket av: org.hibernate.exception.DataException: kunne ikke utføre uttalelse ved oheiSQLExate. (SQLExceptionTypeDelegate.java:71)

I dette spesielle eksemplet er løsningen å spesifisere maks lengde på navnet:

@Column (nullable = false, length = 4096)

7. Årsak: javax.persistence.EntityExistsException

Til å ligge i dvale, er det EntityExistsException JPA-unntak blir også innpakket av Spring Exception Translation i en DataIntegrityViolationException. Den eneste forskjellen er at JPA i seg selv allerede er høyt nivå, noe som gjør dette JPA-unntaket til den eneste potensielle årsaken til dataintegritetsbrudd.

8. Potensielt DataIntegrityViolationException

I noen tilfeller der DataIntegrityViolationException kan forventes, kan et annet unntak kastes - en slik sak er hvis en JSR-303 validator, for eksempel dvalemodus 4 eller 5 finnes på klassestien.

I så fall, hvis følgende enhet er vedvarende med en nullverdi for Navn, det vil ikke lenger mislykkes med et dataintegritetsbrudd utløst av utholdenhetslaget:

@Entity public class Foo {... @Column (nullable = false) @NotNull private Strengnavn; ...}

Dette er fordi utførelsen ikke kommer til utholdenhetslaget - det vil mislykkes før det med en javax.validation.ConstraintViolationException:

javax.validation.ConstraintViolationException: Validering mislyktes for klasser [org.baeldung.spring.persistence.model.Foo] under vedvarende tid for grupper [javax.validation.groups.Default,] Liste over begrensningsbrudd: [ConstraintViolationImpl {interpolatedMessage = "kan ikke være null ", propertyPath = name, rootBeanClass = class org.baeldung.spring.persistence.model.Foo, messageTemplate =" {javax.validation.constraints.NotNull.message} "}] at ohcbBeanValidationEventListener.validate (BeanValidationEventListener.jpg : 159) at ohcbBeanValidationEventListener.onPreInsert (BeanValidationEventListener.java:94)

9. Konklusjoner

På slutten av denne artikkelen bør vi ha et tydelig kart for å navigere i de mange årsakene og problemene som kan føre til a DataIntegrityViolationException om våren, samt en god forståelse av hvordan du kan løse alle disse problemene.

Implementeringen av alle eksempler på unntak finnes i github-prosjektet - dette er et formørkelsesbasert prosjekt, så det skal være enkelt å importere og kjøre som det er.


$config[zx-auto] not found$config[zx-overlay] not found