티스토리 뷰
1. Advanced Mapping Overview
(1) Advanced mappings
지난 게시물에서, Student하나의 테이블에 대해서 Hibernate를 이용하여 데이터를 쓰고, 읽어오고, 수정하고, 삭제하는 과정을 알아보았다.(CRUD features)
하지만 테이블을 관리할때, 테이블 사이에 관계를 같이 관리해야 할때가 있다.
하나의 테이블만 있는것이 아닌 여러개의 테이블이 있을수 있으며, 그 테이블 사이에 대한 관계가 있을수 있기 때문에 이것을 Hibernate로 어떻게 다루는지에 대해서 알아 보겠다.
(2) Advanced mapping의 종류
1) One-To-One mapping
: 테이블 간의 관계가 일대일로 대응되는 형태이다. 예를들어 Instructor 테이블이 있을때, Instructor의 세부 정보를 포함하고 있는 instructor detail entity를 가질 수 있다.(Instructor profile과 유사한)
핵심은 분리된 두 테이블을 가지는 것이다.
이러한 한 Instructor에 오직 하나의 Instructor detail이 연결되는 경우가 One-To-One mapping을 통한 관리를 할 수 있는 경우이다.
2) One-To-Many, Many-To-One mapping
: 테이블 간의 관계가 일대다, 혹은 다대일로 대응되는 형태이다. Instructor테이블과 Course테이블 간의 관계가 이러한 예가 될 수 있다. (Course가 오직 한 Instructor에 의해 진행 될 경우)
오직 한 Instructor에 여러개의 Course가 대응 될 수 있는데, One-To-Many와 Many-To-One은 서로 역의 관계라 보면 된다.
3) Many-To-Many mapping
: 테이블 간의 관계가 다대다로 대응되는 형태이다. 많은 강좌, 즉 Course 테이블과 많은 Student 테이블이 있을때, 학생이 수강신청을 여러 Course를 할수있고, 학생수 또한 많다. 여러개의 Course에 여러개의 Student가 대응될때, Many-To-Many mapping을 통해 관리 할 수 있다.
2. 중요한 데이터베이스 개념
(1) Primary키와 Foreign키
1) Primary key : 테이블에서 유일한 열을 확인할수 있다.
2) Foreign key : 테이블 사이를 연결한다. 한 테이블에서의 필드가 다른 테이블의 primary key를 참조한다.
- 예시 : instructor 테이블과 instructor_detail 테이블이 있을때, instructor테이블에서 foreign key로 instructor_detail_id을 설정해 주고, 이것은 instructor_detail의 primary key인 id 컬럼을 참조한다.
그럼 이 외래키를 사용하면 어떤 점이 좋을까? 위 예시와 같이 외래키를 설정한다면, instructor 테이블의 instructor_detail_id 컬럼에 값이 존재 하지 않는다면, instructor_detail테이블의 id 컬럼의 값은 존재할 수 없다.
따라서 참조무결성(referential integrity)를 유지 할 수 있다.
foreign key 칼럼은 오직 다른 테이블의 PK에 대한 유효한 reference만 가질 수 있다. 그렇지 않으면 데이터베이스가 에러를 발생한다.
(2) Cascade
개체를 변경/삭제할 때 다른 개체가 변경/삭제할 개체를 참조하고 있을 경우 함께 변경/삭제된다.
연관된 개체(Entity)에 같은 적용이 되는 것이다.
- 예시 : 만약 instructor 테이블에 대한 내용을 저장하면, operation이 cascade되어 instructor_detail 테이블도 저장하는 것이다. 마찬가지로 instructor 테이블에 대한 내용을 지우면, foreign key로 연결되어있는 해당 instructor_detail 테이블의 내용도 삭제되는 것이다. 이것을 Cascade Delete라고 부른다.
( ※ Cascade delete는 사용하는 경우에 따라 다르다. 예를들어 Many-To-Mapping이 되어있는 course와 student가 여러개 있을때에는 cascade delete가 되게 하면 안된다. 상황에 따라 다르게 해야하고, 이것을 cascade 설정시 세세하게 설정 가능하다.)
3. Fetch Types : Eager vs Lazy Loading
(1) Eager loading vs Lazy Loading
데이터를 회수할때, 모든 정보를 다 회수 해야 할까?
Eager Loading은 하나의 개체를 DB로 부터 읽어올 때, 참조하고 있는 테이블의 개체들의 데이터 까지 모두 읽어 오는 방식이다. 반면
Lazy Loading은 참조 개체들의 데이터는 무시하고 해당 개체의 데이터만 가지고 온다.
예를들어 instructor 테이블 하나에 해당하는 course테이블이 여러개 일때, instructor 객체를 회수할 때, 그 instructor에 대한 course들도 같이 모두 회수해야 할까? 또는 courses에 대한 데이터는 request(요청)할 때만 반환 할까? Eager는 전자 처럼 하번에 모든 데이터를 회수하고, Lazy는 request할 때만 데이터를 회수한다.
4. Uni-directional 관계와 Bi-directional 관계
(1) Uni-directional(단방향 관계) :
두 엔티티가 연관 관계를 맺고 있을 때, 한 쪽의 엔티티만 다른 쪽을 참조 하고 있는 것을 의미한다.
instructor 테이블과 instructor_detail 테이블이 있을 때, instructor객체를 로드했을때, 거기서 부터 instructor_detail 테이블에 접근할 수 있다. instructor_detail에서 instructor 테이블을 바로 접근하지 못하는것이다.
(Oneway relationship)
(2) Bi-directional(양방향 관계) :
두 엔티티가 연관 관계를 맺고 있을 때, 양 족이 서로를 참조하고 있는 것을 의미한다.
instructor 테이블과 instructor_detail 테이블이 있을 때, 반대로도 갈 수 있다. Instructor_detail을 로드하면, 해당하는 instructor 테이블을 참조 할 수 있는 것이다.
5. Entity Lifecycle
- Entity Lifecycle을 이해하기 위해서는 persistence context라는 개념을 알아야한다.
먼저, JPA에서 Entity라는것은 테이블에 대응하는 하나의 클래스라고 생각하면 된다. DB에서 영속적으로 저장된 데이터를 자바 객체로 매핑하여 인스턴스 형태로 존재하는 데이터를 말한다. 그래서 매핑할 클래스 위에 @Entity라고 붙히는 것이다.
Persistence context란 간단히 말해서 client code와 data 저장사이에 있는, persistent data가 entity로 전환되는 staging area(커밋되기 전의 중간단계)이다. 이론적으로 말해서 persistence context란 *unit of work pattern을 구현한 것이다.
모든 loaded data를 추적한다. 그리고 business transaction끝에 다시 데이터베이스로 변화를 결국 동기화 시키는것에 책임이 있다.
JPA의 Entitymanager와 hibernate의 session이 이러한 persistence context개념의 implementation이다.
따라서 hibernate에서는 session이 persistence context를 나타내는 것이라고 보면된다.
(Session에서 session.beginTransaction()과 session.getTransaction().commit()을 하는 이유가 여기에 있다.)
* Unit of work pattern
: business transaction의 영향을 받은 개체의 리스트를 관리하고 변화의 기록과 동시발생 문제의 해결을 조정하는 패턴이다.
데이터베이스에서 데이터를 넣고 꺼낼때, 바뀐것이 무엇인지 추적하는것이 중요하다. 그것을 추적하지 않으면 데이터가 데이터베이스로 다시 쓰여지지 않을것이기 때문이다. Object를 변경하고 새로만들었으면 새로 만든 object를 데이터베이스에 삽입해야하고 지운 object들은 제거해야한다. 각각의 Object model을 변경시킴으로서 데이터베이스를 변경할 수 있는데, 이렇게 하면 작은 database요청이 매우 많아 짐으로, 결국 매우 느려지는것을 유발한다.
또한 나아가서 전체 transaction을 열어놓는것을 요구하기 때문에 다양한 request가 가로지르는 business transaction이 있을경우 비현실적이다. 만약 이미 읽은 object를 모두 추적하는것은 더 상황을 더악화시키기 때문에 일관성없게 읽는것을 피할 수 있다.
unit of work는 데이터베이스에 영향을 줄 수 있는 business transaction동안 모든것을 추적한다. 내가 끝나면 이것은 끝나야 할것을 알아차리고 너의 work를 database의 결과로 바꾼다.
참고 : martinfowler.com/eaaCatalog/unitOfWork.html
P of EAA: Unit of Work
| P of EAA Catalog | Unit of Work Maintains a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems. For a full description see P of EAA page 184 When you're pulling data in
martinfowler.com
(1) Entity Lifecycle의 종류
1) Detach
2) Merge
3) Persist
4) Remove
5) Refresh
(2) Hibernate에서의 객체의 Lifecycle상태
1) Transient state
: Hibernate session과 아무런 관련이 없는 인스턴스. 데이터베이스와도 아무런 상관이 없고 데이터베이스의 열을 나타내고 있지도 않는 상태. new 키워드로 만들어진 POJO 객체가 바로 그런것이다.
2) Persistent state
: Hibernate session이 연관되어 데이터베이스 테이블의 열을 나타내는 객체나 인스턴스의 상태를 말한다.
session.save(), session.update(), session.persist(), session.saveOrUpdate()같은 메소드를 통해서 transient상태의 객체를 persistent 샅애로 만들 수 있다.
* 오직 persistent 상태에 있는 객체만 transaction이 커밋될때 데이터베이스에 저장된다.
3) Detached state
: persistent 상태의 객체가 session이 닫힌 후에도 존재하는데, 이 상태의 객체를 말한다. 이때에는 POJO 객체에 어떠한 변화를 주더라도 데이터베이스에 반영되지 않는다. session.evict(), session.close(), session.clear()같은 메소드로 session의 persistent 객체를 detach 상태로 만들 수 있다.
4) Removed state
: persistent 객체가 database로부터 제거되었을때, sessoion의 delete()메소드로 전달된다. 이 상태에서 자바 인스턴스는 존재하지만 그 객체에 대한 어떠한 변화가 일어나도 데이터베이스에 저장되지 않는다. session.delete()메소드를 통해 데이터베이스 레코드를 제거할수 있고, 더이상 POJO객체를 다룰수 없다.
Reference :
Udemy에서 chad darby의 Spring & Hibernate for Beginners를 수강 하여 정리
https://blog.ycpark.net/entry/FOREIGN-KEY-%EC%99%80-CONSTRAINT-%EC%9D%98-%EC%82%AC%EC%9A%A9
https://velog.io/@dnjscksdn98/JPA-Hibernate-Bidirectional-Unidirectional-Relationships
'Programming > Spring & Hibernate' 카테고리의 다른 글
🥊 AOP를 활용해 중복코드를 제거해보자! (feat. AOP란?🤔) (1) | 2024.02.08 |
---|---|
SpringBoot를 command line을 통해서 실행하기 (0) | 2022.07.25 |
Hibernate CRUD features: Create, Read, Update and Delete (0) | 2021.03.02 |
Hibernate Configuration with Annotations (0) | 2021.02.26 |
Hibernate Overview & Setting Up Development Environment (0) | 2021.02.26 |
- Total
- Today
- Yesterday