Java/JPA with Error

[해결 방법] org.hibernate.exception.ConstraintViolationException

HJ0216 2023. 9. 10. 19:44

👉 기본 환경

- Language: Java

- DB: H2 Database

- IDE: IntelliJ

 

 

⌨️ 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class Main {
    public static void main(String[] args) {
 
        // 생략
 
        try {
            Child child1 = new Child();
            Child child2 = new Child();
 
            Parent parent = new Parent();
            parent.addChild(child1);
            parent.addChild(child2);
 
            em.persist(parent);
            em.persist(child1);
            em.persist(child2);
 
            em.flush();
            em.clear();
 
            Parent findParent = em.find(Parent.class, parent.getId());
            em.remove(findParent);
 
            tx.commit();
        } catch (Exception e) {
            tx.rollback();
            e.printStackTrace();
        } finally {
            em.close();
        }
 
        emf.close();
 
    }
 
}
 
 

 

 

🖨️오류

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
ERROR: Referential integrity constraint violation: "FKLH67J1N7X7GT59U0PBKWQH6O6: PUBLIC.CHILD FOREIGN KEY(PARENT_ID) REFERENCES PUBLIC.PARENT(ID) (1)"; SQL statement:
/* delete jpa_basic.Parent */ delete from Parent where id=? [23503-200]
javax.persistence.RollbackException: Error while committing the transaction
    at org.hibernate.internal.ExceptionConverterImpl.convertCommitException(ExceptionConverterImpl.java:81)
    at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:104)
    at jpa_basic.Main.main(Main.java:446)
Caused by: javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not execute batch
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:154)
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181)
    at org.hibernate.internal.ExceptionConverterImpl.convertCommitException(ExceptionConverterImpl.java:65)
    ... 2 more
Caused by: org.hibernate.exception.ConstraintViolationException: could not execute batch
    at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:109)
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:113)
    at org.hibernate.engine.jdbc.batch.internal.BatchingBatch.performExecution(BatchingBatch.java:129)
    at org.hibernate.engine.jdbc.batch.internal.BatchingBatch.doExecuteBatch(BatchingBatch.java:105)
    at org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl.execute(AbstractBatchImpl.java:148)
    at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.executeBatch(JdbcCoordinatorImpl.java:198)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:633)
    at org.hibernate.engine.spi.ActionQueue.lambda$executeActions$1(ActionQueue.java:478)
    at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:684)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:475)
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:348)
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:40)
    at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:102)
    at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1352)
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:443)
    at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3202)
    at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2370)
    at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:447)
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:183)
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$300(JdbcResourceLocalTransactionCoordinatorImpl.java:40)
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:281)
    at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:101)
    ... 1 more
Caused by: org.h2.jdbc.JdbcBatchUpdateException: Referential integrity constraint violation: "FKLH67J1N7X7GT59U0PBKWQH6O6: PUBLIC.CHILD FOREIGN KEY(PARENT_ID) REFERENCES PUBLIC.PARENT(ID) (1)"; SQL statement:
/* delete jpa_basic.Parent */ delete from Parent where id=? [23503-200]
    at org.h2.jdbc.JdbcPreparedStatement.executeBatch(JdbcPreparedStatement.java:1235)
    at org.hibernate.engine.jdbc.batch.internal.BatchingBatch.performExecution(BatchingBatch.java:119)
    ... 20 more
 
 

 

 

📡 원인

Parent 객체를 삭제하려고 했으나, 외래키 제약 조건에 의해서 오류 발생

 

 

📰 해결 방법

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
@Entity
public class Parent {
 
    @Id @GeneratedValue
    private long id;
 
    private String name;
 
    @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL)
    private List<Child> children = new ArrayList<>();
 
    public void addChild(Child child){
        children.add(child);
        child.setParent(this);
    }
 
    public long getId() {
        return id;
    }
 
    public void setId(long id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public List<Child> getChildren() {
        return children;
    }
 
    public void setChildren(List<Child> children) {
        this.children = children;
    }
}
 
 

CascadeType.All을 선언하여, Parent 객체 삭제 시, Child도 함께 삭제

 

 

🖨️ 실행 결과

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Hibernate: 
    /* delete jpa_basic.Child */ delete 
        from
            Child 
        where
            id=?
 
Hibernate: 
    /* delete jpa_basic.Child */ delete 
        from
            Child 
        where
            id=?
 
Hibernate: 
    /* delete jpa_basic.Parent */ delete 
        from
            Parent 
        where
            id=?