최상의 실전 경험들
fine-grained 클래스들을 작성하고 <component>를 사용하여 그것들을 매핑하라.
street, suburb, state, postcode를
캡슐화 시키는데 Address 클래스를 사용하라. 이것은 코드 재사용성을 촉진시키고 리팩토링을 단순화 시킨다.
영속 클래스들에 대해 식별자 프로퍼티들을 선언하라.
Hibernate는 식별자 프로퍼티들을 옵션으로 만든다. 왜 우리가 그것들을 사용해야 하는가에 대한 모든 종류의 이유들이 존재한다.
우리는 식별자들이 '합성(synthetic)'이 되는(비지니스 의미 없이 생성되는) 것을 권장한다.
고유 키들을 식별하라.
모든 엔티티들에 대해 고유 키들을 식별하고, <natural-id>를 사용하여 그것들을 매핑하라.
고유 키를 구성하는 프로퍼티들을 비교하기 위해 equals()와 hashCode()를
구현하라.
각각의 클래스 매핑을 그것 자신의 파일 내에 위치지워라.
하나의 한덩어리 매핑 문서를 사용하지 말라. com/eg/Foo.hbm.xml 파일 속에
com.eg.Foo를 매핑하라. 이것은 팀 환경에서 특히 좋은 의미를 준다.
매핑들을 리소스들로서 로드시켜라.
그것들이 매핑하는 클래스들에 따라서 매핑들을 배치하라
질의 문자열들을 객관화 시키는 것을 고려하라.
당신의 질의들이 ANSI 표준이 아닌 SQL 함수들을 호출하는 경우는 좋은 실전연습이다. 질의 문자열들을 매핑 파일들에다가
외부화 시키는 것은 어플리케이션을 보다 이식성 있도록 만들어줄 것이다.
바인드 변수들을 사용하라.
JDBC에서처럼, 상수 아닌 값들을 "?"로 대체시켜라. 질의 속에 상수 아닌 값을 바인드 시키는데 문자열 처리를 결코
사용하지 말라! 더 좋게는 질의들 속에 명명된 파라미터들을 사용하는 것을 고려하라.
당신 자신의 JDBC 커넥션들을 관리하지 말라.
Hibernate는 어플리케이션으로 하여금 JDBC 커넥션들을 관리하도록 한다. 이 접근법은 마지막 수단으로서 고려되어야 한다.
만일 당신이 미리 만들어진 커넥션 프로바이더들을 사용할 수 없을 경우, org.hibernate.connection.ConnectionProvider에
대한 당신 자신의 구현을 제공하는 것을 고려하라.
맞춤형 타입 사용을 고려하라.
당신이 자바 타입을 갖고 있고, 어떤 라이브러리로부터 말하고, 그것이 영속화 될 필요가 있지만 그것을 컴포넌트로서 매핑시키는데
필요한 accessor들을 제공할 필요가 없다고 가정하자. 당신은 org.hibernate.UserType을 구현하는
것을 고려해야 할 것이다. 이 접근법은 Hibernate 타입으로/으로부터 변환들을 구현하는 것으로부터 어플리케이션 코드를 자유롭게
해준다.
병목 지점들에서 수작업으로 코딩된 JDBC를 사용하라.
시스템의 퍼포먼스가 중대한 영역들에서, 몇몇 종류의 오퍼레이션들은 직접적인 JDBC에서 이득을 본다. 그러나 당신이 어떤 것이 병목인지를
알기 전까지 기다리길 바란다. 그리고 직접적인 JDBC가 반드시 더 빠르다고 가정하지 말라. 만일 당신이 직접적인
JDBC를 사용할 필요가 있을 경우, Hibernate Session을 열고 그 SQL 커넥션을 사용할 가치가 있다. 그 방법으로
당신은 동일한 트랜잭션 방도와 기본 커넥션 프로바이더를 여전히 사용할 수 있다
Session flushing을 이해하라.
시간이 지남에 따라 Session은 그것의 영속 상태를 데이터베이스와 동기화 시킨다. 만일 이 과정이 너무 자주 발생할 경우 퍼포먼스가
영향을 받을 것이다. 당신은 때때로 자동적인 flushing을 사용 불가능하게 만들거나 특정 트랜잭션 내에서 질의들의 순서와 다른
오퍼레이션들의 순서를 변경시켜서 불필요한 flushing을 최소화 시킬 수 있다.
3-tier 아키텍처에서, saveOrUpdate() 사용을 고려하라.
servlet / session 빈 아키텍처를 사용할 때, 당신은 sesson bean 내에 로드된 영속 객체들을 서블릿/JSP 계층으로/으로부터
전달할/받을 수 있다. 각각의 요청을 서비스하는데 새로운 세션을 사용하라. 객체들을 데이터베이스와 동기화 시키기 위해서
Session.merge() 또는 Session.saveOrUpdate()를 사용하라.
2-tier 아키텍처에서, 수명이 긴 영속 컨텍스트들을 사용하는 것을 고려하라.
데이터베이스 트랜잭션들은 최상의 가용성을 위해 가능한 한 짧아야 한다. 하지만 장기간 실행되는 어플리케이션 트랜잭션들,
사용자의 뷰 관점에서 한 개의 단위 작업을 구현하는 것이 가끔 필수적이다. 하나의 어플리케이션 트랜잭션은 몇 개의 클라이언트 요청들과
응답 주기들에 걸칠 수도 있다. 어플리케이션 트랜잭션들을 구현하는데 detached 객체들을 사용하는 것이 공통적이다. 2-티어 아키텍처에서
매우 적절한 대안은 어플리케이션 트랜잭션의 전체 생명주기 동안에 한 개의 열려진 영속 접속 (세션)을 유지하는 것이고 각각의 요청의 끝에서
JDBC 커넥션을 간단하게 연결해제하고 차후의 요청의 시작 시에 다시 연결하는 것이다. 한 개 이상의 어플리케이션 트랜잭션을 가로질러서
하나의 단일 세션을 결코 공유하지 말라. 공유할 경우에 당신은 실효성이 없는 데이터로 작업하게 될 것이다.
예외상황들을 복구가능한 것으로서 다루지 말라.
이것은 "최상의" 실전이 아닌 보다 필수적인 실전이다. 예외상황이 발생할 때, Transaction을 롤백시키고
Session을 닫아라. 만일 당신이 그렇게 하지 않을 경우, Hibernate는 메모리 내 상태가 영속 상태를 정확하게
표현하는 것을 보증할 수 없다. 이 특별한 경우처럼, 만일 주어진 식별자를 가진 인스턴스가 데이터베이스 상에 존재하는지 여부를 결정하는데
Session.load()를 사용하지 말라; 대신에 Session.get() 또는 하나의 질의를
사용하라.
연관들에 대한 lazy 페칭을 선호하라.
eager 페칭을 관대하게 사용하라. second-level 캐시 내에 완전하게 보관되지 않을 것 같은 클래스들에 대한 대붑분의 연관들에
대해 프락시들과 lazy 콜렉션들을 사용하라. 캐시된 클래스들에 대한 연관들의 경우, 이곳은 캐시 성공의 매우 높은 확률이 존재하는
곳이며, lazy="false"를 사용하여 eager 페칭을 명시적으로 사용 불가능하게 하라. 한의 join 페칭이
특정 쓰임새에 대해 적절할 때, 하나의 left join fetch를 가진 질의를 사용하라.
페치되지 않은 데이터 문제점들을 피하기 위해 뷰 내에 열려진 세션(open session in view) 패턴 또는
하나의 정리된 어셈블리 단계(assembly phase)를 사용하라.
Hibernate는 개발자들이 Data Transfer Objects (DTO)를 지루하게 작성하는 것으로부터
자유롭게 해준다. 전통적인 EJB 아키텍처에서, DTO는 이중 용도로 기능한다: 첫 번째로 그것들은 엔티티 빈즈가 직렬화 가능하지 않는
문제점에 대해 착수한다; 두 번째로 그것들은 뷰에 의해 사용되는 모든 데이터가 프리젠테이션 티어로 컨트롤을 반환하기 전에 DTO들 속으로
페치되고 마샬링되는 어셈블리 단계를 암묵적으로 정의한다. Hibernate는 첫 번째 용도를 제거시킨다. 하지만 당신이 뷰 렌더링 프로세스를
가로질러 열려져 있는 영속 컨텍스트(세션)을 보관할 준비가 되어 있지 않는 한, 당신은 여전히 어셈블리 단계를 필요로 할 것이다(detached
객체들에서 이용가능한 데이터가 무엇인지에 대해 프리젠테이션 티어와 엄격하게 계약을 갖도록 당신의 비지니스 메소드들을 고려하라)
이것은 Hibernate의 한계점이 아니다! 그것은 안전한 트랜잭션 데이터 접근의 필수 조건이다.
Hibernate에서 당신의 비지니스 로직을 추상화 시키는 것을 고려하라.
(Hibernate) 데이터 액세스 코드를 인터페이스 이면에 은폐시켜라. DAO와
Thread Local Session 패턴들을 결합시켜라. 당신은 심지어 UserType을
통해 Hibernate에 연관된, 수작업으로 코딩된 JDBC로서 몇몇 클래스들을 영속화 시킬 수도 있다. (이 충고는 "충분히 큰"
어플리케이션들에 대한 것이다; 그것은 5개의 테이블들을 가진 어플리케이션에 대해서는 적절하지 않다!)
신종의 연관 매핑을 사용하지 말라.
실제의 many-to-many 연관들에 대한 좋은 쓰임새들은 드물다. 대부분의 시간 동안 당신은 "연결 테이블" 내에 저장된 추가적인 정보를 필요로 한다.
이 경우에, 매개하는 연결 클래스에 대해 두 개의 one-to-many 연관들을 사용하는 것이 훨씬 더 좋다. 사실 우리는 대부분의 연관들이 one-to-many와
many-to-one이라고 생각하며, 당신은 다른 연관 스타일을 사용할 때 주의해야 하고 그것이 진정 필수적인지를 당신 스스로 질문하라.
양방향 연관들을 선호하라.
단방향 연관들은 질의하기가 더 어렵다. 많은 어플리케이션에서, 거의 모든 연관들은 질의들 내에서 양 방향으로 네비게이트 가능해야 한다.