엔지니어로 가는 길

hibernate.hbm2ddl-auto 옵션이 제대로 동작하지 않을 때 본문

프로그래밍/ORM

hibernate.hbm2ddl-auto 옵션이 제대로 동작하지 않을 때

탐p슨 2021. 7. 7. 22:11
728x90

ddl-auto가 언제 적용되는지 알아보고, 이를 테스트해봄으로써 ddl-auto 옵션이 제대로 동작하지 않는 문제를 해결해보자.

 

* 이제부터 편의상 hibernate.hbm2ddl-auto를 ddl-auto라고 부른다.

 

ddl-auto 옵션이 적용되는 시점

ddl-auto 옵션은 Hibernate의 SchemaManagementTool이 관리한다. 그런데 SchemaManagementTool은 SessionFactory 라이프사이클의 일부로, SessionFactory가 생성되거나 종료될 때 자동으로 동작한다. 다시 말해, ddl-auto 옵션이 적용되는 시점은 SessionFactory가 생성되거나 종료되는 시점이다. 애플리케이션이 실행됐더라도, SessionFactory가 생성되기 전이라면 ddl-auto가 적용되지 않는다.

 

https://docs.jboss.org/hibernate/orm/5.5/userguide/html_single/Hibernate_User_Guide.html#configurations-hbmddl

 

create 테스트(update도 마찬가지)

* 테스트에 사용한 언어는 kotlin이다.

 

 

테스트에 사용할 entity 클래스이다.

 

 

테스트를 진행하는 main 함수이다.

 

* Hibernate를 초기화하고 시작하는 방법(SessionFactory를 얻는 방법)은 다음의 문서에 잘 나와있다.

Hibernate Bootstrap

 

 

ddl-auto 옵션을 create로 주었고, 어노테이션을 이용하여 entity 클래스에 대한 정보를 제공했기 때문에 Book 테이블이 만들어져야 한다. 하지만 SessionFactory가 생성되기 전 시점에서 확인해보면 아직 Book 테이블이 생성되지 않았음을 확인할 수 있다.

 

 

SessionFactory가 생성된 후에야 ddl-auto가 적용되어 Book 테이블이 생성된다.


create-drop 테스트

ddl-auto 옵션이 create 이거나 update인 경우는 SessionFactory가 생성될 때만 신경쓴다면 문제없이 동작한다. 하지만 create-drop 옵션을 사용하는 경우는 생성될 때 뿐만 아니라 종료되는 것까지 신경써야 한다. create-drop 옵션에서 drop하는 시점이 바로 SessionFactory가 종료되는 시점이기 때문이다.

 

 

ddl-auto 옵션을 create-drop으로 놓은 뒤, 테스트를 진행해보자. 애플리케이션이 종료될 때 알아서 SessionFactory가 닫힐거라고 기대했지만, 테스트 결과 명시적으로 SessionFactory를 close하지 않으면 drop이 제대로 동작하지 않음을 확인하였다. (drop이 제대로 동작했다면 마지막에 drop 쿼리가 날아갔을 것이다.)

 

 

SessionFactory를 명시적으로 close한 결과 drop이 정상적으로 동작함을 확인하였다.

 

결론

ddl-auto는 애플리케이션을 실행하면 자동으로 적용되는 것이 아니라, SessionFactory가 만들어질 때(종료될 때) 적용된다. 따라서 DB 연결도 잘 되어있고, 매핑도 잘 되어있고, 매핑 정보도 확실히 Hibernate에게 알려주었는데도 ddl-auto 옵션이 제대로 적용이 안된다면, SessionFactory가 언제 만들어지는지 추적해보자. 예를 들어, SessionFactory가 특정 요청이 도착하고 난 뒤에야 만들어지도록 lazy하게 구현했다면 애플리케이션의 라이프사이클과 SessionFactory의 라이프사이클이 일치하지 않게 되고, 따라서 애플리케이션을 실행해도(종료돼도) SessionFactory가 생성되지(종료되지) 않아 ddl-auto가 적용되지 않을 수 있다.

* 테스트해본 결과, SessionFactory가 만들어지지 않아서 아직 ddl-auto가 적용되지 않았을 때 쿼리를 날려도 에러는 발생하지 않는다. 쿼리를 날리려면 SessionFactory로부터 Session을 얻어야하므로 결국 SessionFactory가 생성되고, SessionFactory가 생성될 때 ddl-auto가 적용되기 때문에 쿼리를 실행하는 시점은 결국 ddl-auto가 적용된 이후이기 때문인 것 같다.

728x90
Comments