Data SpringIntegrityViolationException

1. Gambaran keseluruhan

Dalam artikel ini, kita akan membincangkan org.springframework.dao.DataIntegrityViolationException Spring - ini adalah pengecualian data generik yang biasanya dilemparkan oleh mekanisme terjemahan pengecualian Spring ketika berurusan dengan pengecualian ketekunan tahap yang lebih rendah. Artikel ini akan membincangkan sebab-sebab yang paling biasa dari pengecualian ini bersama-sama dengan penyelesaiannya.

2. TerjemahanIntegrityViolationException dan Spring Exception

Mekanisme terjemahan pengecualian musim bunga dapat diterapkan secara telus ke semua kacang yang dijelaskan dengan @Repository - dengan menentukan kacang pemprosesan pasca terjemahan pengecualian dalam Konteks:

Atau di Jawa:

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

Mekanisme terjemahan Pengecualian juga diaktifkan secara lalai pada templat ketekunan lama yang terdapat pada Musim Bunga - HibernateTemplate, JpaTemplate, dll.

3. Di Mana DataIntegrityViolationException Dilempar

3.1. DataIntegrityViolationException dengan Hibernate

Apabila Spring dikonfigurasi dengan Hibernate, pengecualian dilemparkan di lapisan terjemahan pengecualian yang disediakan oleh Spring - SessionFactoryUtils - convertHibernateAccessException .

Terdapat tiga kemungkinan pengecualian Hibernate yang boleh menyebabkan DataIntegrityViolationException dibuang:

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

3.2. DataIntegrityViolationException Dengan JPA

Apabila Spring dikonfigurasi dengan JPA sebagai penyedia kegigihannya, DataIntegrityViolationException dilemparkan, serupa dengan Hibernate, pada lapisan terjemahan pengecualian - iaitu di EntityManagerFactoryUtils - convertJpaAccessExceptionIfPossible .

Terdapat satu pengecualian JPA yang boleh mencetuskan DataIntegrityViolationException - javax.persistence.EntityExistsException .

4. Sebab: org.hibernate.exception.ConstraintViolationException

Jauh ini adalah penyebab yang paling biasa dilancarkan DataIntegrityViolationException - Hibernate ConstraintViolationException menunjukkan bahawa operasi tersebut telah melanggar kekangan integriti pangkalan data.

Pertimbangkan contoh berikut - untuk pemetaan One to One melalui lajur kunci asing eksplisit antara entiti Ibu Bapa dan Anak - operasi berikut akan gagal:

@Test(expected = DataIntegrityViolationException.class) public void whenChildIsDeletedWhileParentStillHasForeignKeyToIt_thenDataException() { Child childEntity = new Child(); childService.create(childEntity); Parent parentEntity = new Parent(childEntity); service.create(parentEntity); childService.delete(childEntity); }

The Parent entiti mempunyai kunci asing kepada Child entiti - jadi memotong kanak-kanak itu akan memecahkan kekangan asing utama dalam Parent - yang keputusan dalam ConstraintViolationException - dibalut dengan Spring dalam DataIntegrityViolationException :

org.springframework.dao.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

Untuk menyelesaikannya, Ibu Bapa harus dihapuskan terlebih dahulu:

@Test public void whenChildIsDeletedAfterTheParent_thenNoExceptions() { Child childEntity = new Child(); childService.create(childEntity); Parent parentEntity = new Parent(childEntity); service.create(parentEntity); service.delete(parentEntity); childService.delete(childEntity); }

5. Sebab: org.hibernate.PropertyValueException

Ini adalah salah satu penyebab DataIntegrityViolationException yang lebih biasa - dalam Hibernate, ini akan menyebabkan entiti mengalami masalah. Entah entiti mempunyai harta batal yang didefinisikan dengan kekangan tidak nol , atau persatuan entiti boleh merujuk contoh sementara yang belum disimpan .

Sebagai contoh, entiti berikut mempunyai harta nama tidak kosong -

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

Sekiranya ujian berikut cuba mengekalkan entiti dengan nilai nol untuk nama :

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

Kekangan integrigy pangkalan data dilanggar, dan DataIntegrityViolationException dilemparkan:

org.springframework.dao.DataIntegrityViolationException: not-null property references a null or transient value: org.baeldung.spring.persistence.model.Foo.name; nested exception is org.hibernate.PropertyValueException: not-null property references a null or transient value: org.baeldung.spring.persistence.model.Foo.name at o.s.orm.h.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:160) ... Caused by: org.hibernate.PropertyValueException: not-null property references a null or transient value: org.baeldung.spring.persistence.model.Foo.name at o.h.e.i.Nullability.checkNullability(Nullability.java:103) ...

6. Sebab: org.hibernate.exception.DataException

Hibernate DataException menunjukkan Penyataan SQL yang tidak betul - ada yang tidak kena dengan pernyataan atau data, dalam konteks tertentu. Contohnya, menggunakan atau entiti Foo dari sebelumnya, perkara berikut akan mencetuskan pengecualian ini:

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

Pengecualian sebenar untuk meneruskan objek dengan nilai nama panjang adalah:

org.springframework.dao.DataIntegrityViolationException: 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)

Dalam contoh khusus ini, penyelesaiannya adalah dengan menentukan panjang maksimum nama:

@Column(nullable = false, length = 4096)

7. Sebab: javax.persistence.EntityExistsException

Sama seperti Hibernate, pengecualian EntityExistsException JPA juga akan dibungkus oleh Spring Exception Translation menjadi DataIntegrityViolationException . Satu-satunya perbezaan adalah bahawa JPA itu sendiri sudah berada di tahap tinggi yang menjadikan pengecualian JPA ini satu-satunya kemungkinan penyebab pelanggaran integriti data.

8. Berpotensi DataIntegrityViolationException

Dalam beberapa kes di mana DataIntegrityViolationException mungkin diharapkan, pengecualian lain mungkin dilemparkan - satu kes seperti itu adalah jika validator JSR-303, seperti validator hibernate 4 atau 5 ada di classpath.

Dalam kes tersebut, jika entiti berikut dikekalkan dengan nilai nol untuk nama , ia tidak akan gagal lagi dengan pelanggaran integriti data yang dipicu oleh lapisan kegigihan:

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

Ini kerana pelaksanaannya tidak akan sampai ke lapisan kegigihan - ia akan gagal sebelum itu dengan javax.validation.ConstraintViolationException :

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, messageTemplate="{javax.validation.constraints.NotNull.message}"} ] at o.h.c.b.BeanValidationEventListener.validate(BeanValidationEventListener.java:159) at o.h.c.b.BeanValidationEventListener.onPreInsert(BeanValidationEventListener.java:94)

9. Kesimpulan

Pada akhir artikel ini, kita harus mempunyai peta yang jelas untuk menavigasi pelbagai sebab dan masalah yang mungkin menyebabkan Pengecualian DataIntegrityViolationException pada Musim Semi, serta pemahaman yang baik tentang bagaimana menyelesaikan semua masalah ini.

Pelaksanaan semua contoh pengecualian boleh didapati di projek github - ini adalah projek berasaskan Eclipse, jadi mudah untuk diimport dan dijalankan sebagaimana adanya.