[SQL Error: 23503] Cascade 설정 후 Parent remove할 때 질문입니다.
해결됨
자바 ORM 표준 JPA 프로그래밍 - 기본편
안녕하세요! 이전 질문에서 영한님 답변을 받고 원인을 해결하여 다른 경우 또한 테스트해보고 있는데 SQL Error: 23503 에러가 발생했고, 구글링 결과 참조 키 제약조건 위배될 때 발생하는 에러라 하는데 아래 상황에서 왜 이 에러가 뜨는지 모르겠어서 질문을 남깁니다. Parent, child 끼리 연관관계 매핑 후, cascadetype.ALL, orphanRemoval=false로 설정한 후, parent를 삭제할 때 발생한 에러입니다. 먼저 Parent, Child, Main 클래스 코드를 보여드리겠습니다! @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); } // getter, setter 생략했습니다 } @Entity public class Child { @Id @GeneratedValue private Long id; private String name; @ManyToOne(fetch = FetchType.LAZY) private Parent parent; // getter, setter 메소드 생략했습니다 } Parent 클래스, Child 클래스는 위와 같이 작성했으며, cascadetype.ALL로 설정해놓았고, 고아 객체 제거는 설정하지 않았습니다. 메인 코드는 아래와 같습니다. public class JpaMain { public static void main(String[] args) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello"); EntityManager em=emf.createEntityManager(); EntityTransaction tx = em.getTransaction(); tx.begin(); try{ Parent parent=new Parent(); parent.setName("kth990303"); Child child1=new Child(); child1.setName("kthbaby1"); Child child2=new Child(); child2.setName("kthbaby2"); parent.addChild(child1); parent.addChild(child2); em.persist(parent); em.flush(); em.clear(); Parent findParent = em.find(Parent.class, parent.getId()); System.out.println("===================1"); findParent.getChildren().remove(0); em.remove(findParent); System.out.println("===================3"); tx.commit(); } catch(Exception e){ e.printStackTrace(); tx.rollback(); } finally{ em.close(); } emf.close(); } } 역시 orphanRemoval=true가 아니었기 때문에 findParent.getChildren().remove( 0 ) ; 코드에서, 아무 일이 일어나지 않고 지연로딩으로 인한 child select 쿼리만 날라가는건 예상대로였는데, 문제는 그 아래 em.remove(findParent); 였습니다. 이미 em.find로 영속성 컨텍스트에 정보가 있어 parent를 지울 때 에러가 발생하지 않은 상태로 parent와 children 모두 지워질 줄 알았는데 아래 사진과 같은 에러가 발생했습니다. 사실 parent를 지울 때 그냥 findParent.getChildren().remove(0); 을 작성하지 않고 em.remove(findParent);만 하면 parent가 지워짐과 동시에 children도 모두 잘 지워지는 성공적인 결과가 보이긴 합니다만,,, 위와 같이 코드를 짠 후 실행했더니 SQL ERROR 23503이 뜨는 이유가 궁금하여 질문드립니다. 금쪽같은 주말에 질문을 좀 많이 하는 듯하네요 ㅠㅠ 죄송합니다. 그리고 감사합니다 :) ===================1 Hibernate: select children0_.parent_id as parent_i3_2_0_, children0_.id as id1_2_0_, children0_.id as id1_2_1_, children0_.name as name2_2_1_, children0_.parent_id as parent_i3_2_1_ from Child children0_ where children0_.parent_id=? ===================3 Hibernate: /* delete hellojpa.Child */ delete from Child where id=? Hibernate: /* delete hellojpa.Parent */ delete from Parent where id=? 5월 15, 2021 8:20:45 오후 org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions WARN: SQL Error: 23503, SQLState: 23503 5월 15, 2021 8:20:45 오후 org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions ERROR: Referential integrity constraint violation: "FKLH67J1N7X7GT59U0PBKWQH6O6: PUBLIC.CHILD FOREIGN KEY(PARENT_ID) REFERENCES PUBLIC.PARENT(ID) (1)"; SQL statement: /* delete hellojpa.Parent */ delete from Parent where id=? [23503-199] 5월 15, 2021 8:20:45 오후 org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl release INFO: HHH000010: On release of batch it still contained JDBC statements 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 hellojpa.JpaMain.main(JpaMain.java:43) Caused by: javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not execute statement 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 statement at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:59) 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.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:99) at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:200) at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:45) at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:3551) at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:3810) at org.hibernate.action.internal.EntityDeleteAction.execute(EntityDeleteAction.java:124) at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:604) 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.JdbcSQLIntegrityConstraintViolationException: Referential integrity constraint violation: "FKLH67J1N7X7GT59U0PBKWQH6O6: PUBLIC.CHILD FOREIGN KEY(PARENT_ID) REFERENCES PUBLIC.PARENT(ID) (1)"; SQL statement: /* delete hellojpa.Parent */ delete from Parent where id=? [23503-200] at org.h2.message.DbException.getJdbcSQLException(DbException.java:459) at org.h2.message.DbException.getJdbcSQLException(DbException.java:429) at org.h2.message.DbException.get(DbException.java:205) at org.h2.message.DbException.get(DbException.java:181) at org.h2.constraint.ConstraintReferential.checkRow(ConstraintReferential.java:373) at org.h2.constraint.ConstraintReferential.checkRowRefTable(ConstraintReferential.java:390) at org.h2.constraint.ConstraintReferential.checkRow(ConstraintReferential.java:265) at org.h2.table.Table.fireConstraints(Table.java:1057) at org.h2.table.Table.fireAfterRow(Table.java:1075) at org.h2.command.dml.Delete.update(Delete.java:153) at org.h2.command.CommandContainer.update(CommandContainer.java:198) at org.h2.command.Command.executeUpdate(Command.java:251) at org.h2.server.TcpServerThread.process(TcpServerThread.java:406) at org.h2.server.TcpServerThread.run(TcpServerThread.java:183) at java.lang.Thread.run(Unknown Source) at org.h2.message.DbException.getJdbcSQLException(DbException.java:457) at org.h2.engine.SessionRemote.done(SessionRemote.java:607) at org.h2.command.CommandRemote.executeUpdate(CommandRemote.java:237) at org.h2.jdbc.JdbcPreparedStatement.executeUpdateInternal(JdbcPreparedStatement.java:200) at org.h2.jdbc.JdbcPreparedStatement.executeUpdate(JdbcPreparedStatement.java:154) at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:197) ... 21 more 5월 15, 2021 8:20:45 오후 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PoolState stop INFO: HHH10001008: Cleaning up connection pool [jdbc:h2:tcp://localhost/~/test] Process finished with exit code 0
- cascade
- remove
- java
- 23503
- JPA





