Hibernate(괄호 내에 있는 비교 가능한 용어들)에서처럼, 하나의 엔티티 인스턴스는 다음 방도들 중 하나이다:
New (transient): 하나의 엔티티가 new 연산자를 사용하여 방금 초기화 되었다면, 그 엔티티는 새로운 것(new)이고, 그것은 하나의 영속 컨텍스트와 연관되어 있지 않다. 그것은 데이터베이스 내에 영속 표상을 갖지 않으며 식별자 값이 할당되지 않았다.
Managed (persistent): 하나의 관리되는 엔티티 인스턴스는 현재 하나의 영속 컨텍스트와 연관되어 있는 하나의 영속 동일성(identity)를 가진 하나의 인스턴스이다.
Detached: 대개 영속 컨텍스트가 영속 컨텍스트가 닫혔거나 인스턴스가 그 컨텍스트로부터 퇴거되었기 때문에, 엔티티 인스턴스는 더 이상 하나의 영속 컨텍스트와 연관되어 있지 않은 하나의 영속 동일성(identity)을 가진 하나의 인스턴스이다.
Removed: 하나의 제거된 엔티티 인스턴스는 하나의 영속 컨텍스트와 연관되어 있지만, 데이터베이스로부터 제거되도록 일정이 잡혀져 있는 하나의 영속 동일성(identity)를 한 개의 인스턴스이다.
EntityManager API는 엔티티의 상태를 변경시키는 것, 달리 말해, 객체들을 로드시키고 저장시키기는 것을 당신에게 허용해준다. 만일 당신이 SQL 문장들을 관리하는 것이 아니라, 객체 상태 관리에 대해 생각할 경우에 이해하는 것이 더 쉬운 EJB3에 대한 영속성을 발견하게 될 것이다.
일단 당신이 (공통 new 연산자를 사용하여) 하나의 새로운 엔티티 인스턴스를 생성시켰다면 그것은 new 상태에 있다. 당신은 그것을 하나의 엔티티 관리자에 연관시켜서 그것을 영속화 시킬 수 있다:
DomesticCat fritz = new DomesticCat();
fritz.setColor(Color.GINGER);
fritz.setSex('M');
fritz.setName("Fritz");
em.persist(fritz);만일 DomesticCat 엔티티 타입이 하나의 산출된 식별자를 갖고 있다면, 그 값은 persist()이 호출될 때 그 인스턴스에 연관된다. 만일 그 식별자가 자동적으로 산출되지 않는다면, 어플리케이션에 의해 할당된(대개 natural) 키 값이 persist()이 호출되기 전에 그 인스턴스에 설정되어야 한다.
엔티티 관리자의 find() 메소드로서 엔티티 인스턴스의 식별자 값으로 하나의 엔티티 인스턴스를 로드시켜라:
cat = em.find(Cat.class, catId); // You may need to wrap the primitive identifiers long catId = 1234; em.find( Cat.class, new Long(catId) );
몇몇 경우들에서, 당신은 객체 상태를 로드시키는 것을 진정 원하지 않고, 단지 그것에 대한 하나의 참조를 갖고자 원한다(예를 들면 하나의 프락시). 당신은 getReference() 메소드를 사용하여 이 참조를 얻을 수 있다. 이것은 부모를 로드시키지 않고서 하나의 자식을 그것의 부모에 링크시키는 것에 특히 유용하다.
child = new Child();
child.SetName("Henry");
Parent parent = em.getReference(Parent.class, parentId); //no query to the DB
child.setParent(parent);
em.persist(child);당신은 em.refresh() 연산을 사용하여 아무때든지 하나의 엔티티 인스턴스와 그것의 콜렉션들을 다시 로드시킬 수 있다. 이것은 데이터베이스 트리거들이 그 엔티티의 프로퍼티들 중 몇몇을 초기화 시키는데 사용될 때 유용하다. 당신이 임의의 연관들에 대한 하나의 케스케이드 스타일로서 REFRESH를 지정하지 않는 한 오직 엔티티 인스턴스와 그것의 콜렉션들 만이 재생(reflesh)된다는 점을 노트하라:
em.persist(cat); em.flush(); // force the SQL insert and triggers to run em.refresh(cat); //re-read the state (after the trigger executes)
만일 당신이 당신이 찾고 있는 객체들의 식별자 값들을 알지 못할 경우, 당신은 질의를 필요로 한다. Hibernate EntityManager 구현은 HQL (그리고 기타)에 의해 영감을 받았던 사용이 쉽지만 강력한 객체-지향 질의 언어(EJB3-QL)를 지원한다. 두 질의 언어들 양자들 데이터베이스들 사이에 이식 가능하고, (테이블 이름과 컬럼 이름 대신에) 식별자들로서 엔티티 이름과 프로퍼티 이름을 사용한다. 당신은 또한 Java 비지니스 객체들로의 결과 셋 변환을 위한 EJB3에 있는 옵션 지원으로서, 당신의 데이터베이스의 native SQL로 당신의 질의를 표현할 수도 있다.
EJB3QL 질의와 SQL 질의들은 javax.persistence.Query의 인스턴스에 의해 표현된다. 이 인스턴스는 파라미터 바인딩, 결과 셋 핸들링, 그리고 질의의 실행을 위한 메소드들을 제공한다. 질의들은 항상 현재의 엔티티 관리자를 사용하여 생성된다:
List cats = em.createQuery(
"select cat from Cat as cat where cat.birthdate < ?")
.setParameter(0, date, TemporalType.DATE)
.getResultList();
List mothers = em.createQuery(
"select mother from Cat as cat join cat.mother as mother where cat.name = ?")
.setParameter(0, name)
.getResultList();
List kittens = em.createQuery(
"from Cat as cat where cat.mother = ?")
.setEntity(0, pk)
.getResultList();
Cat mother = (Cat) em.createQuery(
"select cat.mother from Cat as cat where cat = ?")
.setParameter(0, izi)
.getSingleResult();하나의 질의는 대개 getResultList()를 호출하여 실행된다. 이 메소드는 질의의 귀결되는 인스턴스들을 전체 메모리 내로 로드시킨다. 하나의 질의에 의해 검색된 엔티티 인스턴스들은 영속 상태에 있다. 만일 당신의 질의가 한 개의 객체 만을 반환할 것임을 당신이 알고 있다면 getSingleResult() 메소드는 단축형을 제공한다.
만일 투영(projection)이 사용될 경우에 EJB3QL query 질의들은 객체들의 튜플들을 반환할 수 있다. 각가의 결과 튜플은 하나의 객체 배열로서 반환된다:
Iterator kittensAndMothers = sess.createQuery(
"select kitten, mother from Cat kitten join kitten.mother mother")
.getResultList()
.iterator();
while ( kittensAndMothers.hasNext() ) {
Object[] tuple = (Object[]) kittensAndMothers.next();
Cat kitten = tuple[0];
Cat mother = tuple[1];
....
}질의들은 하나의 엔티티 alias 가 아닌, select 절 내에 하나의 엔티티에 대한 하나의 특별한 프로퍼티를 지정할 수 있다. 당신은 SQL 집계 함수들도 호출할 수 있다. 반환된 비-트랜잭션 객체들이나 집계 결과들은 "스칼라" 결과들로서 간주되며 영속 상태 내에 있는 엔티티들이 아니다 (달리 말해 그것들은 "읽기 전용"으로 간주된다):
Iterator results = em.createQuery(
"select cat.color, min(cat.birthdate), count(cat) from Cat cat " +
"group by cat.color")
.list()
.iterator();
while ( results.hasNext() ) {
Object[] row = results.next();
Color type = (Color) row[0];
Date oldest = (Date) row[1];
Integer count = (Integer) row[2];
.....
}명명된 질의 파라미터와 위치 질의 파라미터 모두 지원되며, Query API는 아규먼트들을 바인드 시키는 몇몇 메소드들을 제공한다. JDBC와는 대조적으로 , EJB3 명세서는 위치 파라미터들을 1이 아닌, 0에서 시작한다. 명명된 파라미터들은 질의 문자열 내에서 :paramname 형식의 식별자들이다. 명명된 파라미터들이 선호되며, 그것드은 읽고 이해하는데 보다 강점을 갖고 보다 쉽다:
// Named parameter (preferred)
Query q = em.createQuery("select cat from DomesticCat cat where cat.name = :name");
q.setParameter("name", "Fritz");
List cats = q.getResultList();
// Positional parameter
Query q = em.createQuery("select cat from DomesticCat cat where cat.name = ?");
q.setParameter(0, "Izi");
List cats = q.getResultList();
// Named parameter list
List names = new ArrayList();
names.add("Izi");
names.add("Fritz");
Query q = em.createQuery("select cat from DomesticCat cat where cat.name in (:namesList)");
q.setParameter("namesList", names);
List cats = q.list();만일 당신이 당신의 결과 셋에 경계점들(당신이 검색하고자 원하는 행들의 최대 개수 그리고/또는 당신이 검색하고자 원하는 첫 행의 최대 개수)를 지정할 필요가 있다면, 다음 메소드들을 사용하라:
Query q = em.createQuery("select cat from DomesticCat cat");
q.setFirstResult(20);
q.setMaxResults(10);
List cats = q.list(); //return cats from the 20th position to 29thHibernate는 이 limit 질의를 당신의 DBMS의 native SQL로 변환시키는 방법을 알고 있다.
당신은 또한 주해들(annotations)을 통해 명명된 질의들을 정의할 수도 있다:
@javax.persistence.NamedQuery(name="eg.DomesticCat.by.name.and.minimum.weight", queryString="select cat from eg.DomesticCat as cat where cat.name = ? and cat.weight > ?")
Parameters are bound programatically to the named query, before it is executed:
Query q = em.createNamedQuery("eg.DomesticCat.by.name.and.minimum.weight");
q.setString(0, name);
q.setInt(1, minWeight);
List cats = q.list();실제 프로그램 코드는 사용되는 질의 언어에 독립적이며, 당신은 또한 메타 데이터로 native SQL 질의들을 정의할 수도 있거나 그것들을 XML 매핑 파일들 내에 위치지움으로써 Hibernate의 native 편의설비들을 사용할 수도 있음을 노트하라.
당신은 createNativeQuery()를 사용하여 하나의 질의를 표현할 수도 있고 Hibernate로 하여금 JDBC 결과 셋들로부터 비지니스 객체들로의 매핑을 처리하도록 할 수 있다. @SqlResultSetMapping (SQL 결과셋 매핑을 매핑시키는 방법에 대해서는 Hibernate Annotations 참조 문서를 보길 바란다) 또는 엔티티 매핑(질의 결과의 컬럼 이름들이 엔티티 매핑 내에 선언된 이름들과 동일할 경우;모든 엔티티 컬럼들이 이 메커니즘이 동작하도록 반환 되어야 함을 기억하라)을 사용하라:
@SqlResultSetMapping(name="getItem", entities =
@EntityResult(name="org.hibernate.ejb.test.Item", fields= {
@FieldResult(name="name", column="itemname"),
@FieldResult(name="descr", column="itemdescription")
})
)
Query q = em.createNativeQuery("select name as itemname, descr as itemdescription from Item", "getItem");
item = (Item) q.getSingleResult(); //from a resultset
Query q = em.createNativeQuery("select * from Item", Item.class);
item = (Item) q.getSingleResult(); //from a class columns names match the mappingnative 질의들에 대한 현재 구현은 스칼라 결과들을 지원하지 않으며, 오직 트랜잭션적인 엔티티들 만을 지원한다.
(대개 퍼포먼스 최적화를 위한) 질의 힌트들은 구현 지정적이다. 힌트들은 query.setHint(String name, Object value)를 사용하여 선언된다. 이것들은 SQL 질의 힌트들이 아님을 노트하라! Hibernate EJB3 구현은 다음 질의 힌트들을 제공한다:
표 3.1. Hibernate 질의 힌트들
| 힌트 | 설명 |
|---|---|
| org.hibernate.timeout | 초 단위의 질의 타임아웃 ( 예를 들면. new Integer(10) ) |
| org.hibernate.fetchSize | 라운드트립 당 JDBC 드라이버에 의해 페치되는 행들의 개수 ( 예를 들면. new Integer(50) ) |
| org.hibernate.comment | DBA에게 유용한 주석을 SQL 질의에 추가한다 ( 예를 들면. new String("fetch all orders in 1 statement") ) |
| org.hibernate.cacheable | 질의가 캐시 가능한지 여부 ( 예를 들면. new Boolean(true) ), 디폴트는 false |
| org.hibernate.cacheMode | 이 질의에 대한 캐시 모드를 오버라이드 시킨다 ( 예를 들면. CacheMode.REFRESH ) |
| org.hibernate.cacheRegion | 이 질의의 캐시 영역 ( 예를 들면. new String("regionName") ) |
| org.hibernate.readOnly | Hibernate가 그것들에 대해 dirty-check를 결코 행하지 않거나 변경들을 결코 영속화 시키지 않는 곳에서 이 질의에 의해 검색된 엔티티들은 읽기 전용 모드로 로드될 것이다( 예를 들면. new Boolean(true) ), 디폴트는 false |
추가 정보는 Hibernate 참조 문서를 참조하길 바란다.
트랜잭션 관리되는 인스턴스들(예를 들면. 엔티티 관리자에 의해 로드되고, 저장되고, 생성되거나 질의되는 객체들)은 어플리케이션에 의해 처리될 수 있고 영속 상태에 대한 임의의 변경들은 Entity 관리자가 flush될 때 영속화 될 것이다(이 장의 뒷 부분에서 논의됨). 당신의 수정들을 영속화 시키기 위한 어떤 특별한 메소드 호출이 필요하지 않다. 하나의 엔티티 인스턴스의 상태를 업데이트시키는 간단한 방법은 영속 컨텍스트가 열려져 있는 동안에 그것을 find() 하고 나서, 그것을 직접 처리하는 것이다:
Cat cat = em.find( Cat.class, new Long(69) );
cat.setName("PK");
em.flush(); // changes to cat are automatically detected and persisted때때로 이 프로그래밍 모형은 불충분하다. 왜냐하면 그것은 동일 세션 내에서 (하나의 객체를 로드시키는) 하나의 SQL SELECT와 (그것의 업데이트된 상태를 영속화 시키기 위한) 하나의 SQL UPDATE 양자를 필요로 할 것이기 때문이다. 그러므로 Hibernate는 분리된 인스턴스들(detached instances)를 사용하여 대안적인 접근법을 제공한다.
많은 어플리케이션들은 하나의 트랜잭션 내에서 하나의 객체를 검색하고 그것을 처리를 위한 프리젠테이션 게층으로 전송하고, 나중에 새로운 트랜잭션 내에서 변경들을 저장하는 것을 필요로 한다. 두 트랜잭션들 사이의 사용자 생각 시간과 대기 시간이 중요해질 수 있다. 고도의 동시성 환경에서 이런 종류의 접근법을 사용하는 어플리케이션들은 대개 "장기간의" 작업 단위에 대한 격리를 보장하는데 버전화 된 데이터를 사용한다.
EJB3 명세서들은 EntityManager.merge() 메소드를 사용하여 분리된 인스턴스들(detached instances)에 대해 행해진 수정들의 영속화를 제공함으로써 이 개발 모형을 지원한다:
// in the first entity manager Cat cat = firstEntityManager.find(Cat.class, catId); Cat potentialMate = new Cat(); firstEntityManager.persist(potentialMate); // in a higher layer of the application cat.setMate(potentialMate); // later, in a new entity manager secondEntityManager.merge(cat); // update cat secondEntityManager.merge(mate); // update mate
merge() 메소드는 영속 컨텍스트의 상태를 고려하지 않고서 분리된 인스턴스들(detached instances)에 대해 행해진 수정들을 대응하는 관리되는 인스턴스(managed instance) 속으로 병합시킨다. 달리 말해, 병합된 객체들 상태는 그것이 존재할 경우에 영속 컨텍스트 내에 있는 영속 엔티티 상태를 오버라이드 시킨다. 어플리케이션은 그것이 분리된 인스턴스들의 상태가 또한 영속화 되기를 원하는 경우에만 주어진 분리된 인스턴스로부터 도달가능한 분리된 인스턴스들(detached instances)을 하나씩 merge() 시킬 것이다. 이것은 전이 영속(transitive persistence)을 사용하여 연관된 엔티티들과 콜렉션들로 케스케이드 될 수 있으며, Transitive persistence를 보라.
merge 연산은 분리된 인스턴스에 대한 병합이 insert로 귀결되어야 하는지 update로 귀결되어야 하는지 여부를 자동적으로 검출해낼 만큼 충분히 영리하다. 달리 말해, 당신은 하나의 새로운 인스턴스를 merge()에 전달하는 것(과 하나의 분리된 인스턴스를 전달하지 않는 것)에 대해 걱정하지 않아도 되며, 엔티티 관리자가 당신을 위해 이것을 해석할 것이다:
// In the first entity manager Cat cat = firstEntityManager.find(Cat.class, catID); // In a higher layer of the application, detached Cat mate = new Cat(); cat.setMate(mate); // Later, in a new entity manager secondEntityManager.merge(cat); // update existing state secondEntityManager.merge(mate); // save the new instance
merge()의 사용법 및 의미는 신규 사용자들에게는 혼동스러워 보인다. 먼저 당신이 하나의 엔티티 관리자 내에서 로드된 객체 상태를 또 다른 엔티티 관리자 내에서 사용하려고 시도하는 한, 당신은 merge()를 전혀 사용할 필요가 없을 것이다. 몇몇 전체 어플리케이션들은 이 메소드들을 전혀 사용하지 않을 것이다.
대개 merge()는 다음 시나리오들 내에서 사용된다:
어플리케이션이 첫 번째 엔티티 관리자 내에 한 개의 객체를 로드시킨다
그 객체는 프리젠테이션 계층으로 전달된다
몇몇 수정들이 그 객체에 대해 행해진다
그 객체는 다시 비지니스 로직 계층으로 전달된다
어플리케이션은 두 번째 엔티티 관리자 내에서 merge()를 호출하여 이들 수정들을 영속화 시킨다
다음은 merge()의 정확한 의미이다:
만일 영속 컨텍스트에 현재 연관된 동일한 식별자를 가진 하나의 관리되는 인스턴스가 존재한다면, 주어진 객체의 상태를 관리되는 인스턴스 상으로 복사하라
만일 영속 컨텍스트와 현재 연관된 관리되는 인스턴스가 존재하지 않을 경우, 데이터베이스로부터 그것을 로드시키거나 하나의 새로운 관리되는 인스턴스를 생성시키려고 시도하라
관리되는 인스턴스가 반환된다
주어진 인스턴스는 영속 컨텍스트에 연관되지 않으며, 그것은 분리된 채로 (detached 상태로) 유지되고 대개 폐기된다
EJB3에서 병합(Merging)은 native Hibernate에서 saveOrUpdateCopy() 메소드와 유사하다. 하지만 그것은 saveOrUpdate() 메소드와 동일하지 않으며, 주어진 인스턴스는 영속 컨텍스트에 다시첨부되지 않지만, 하나의 관리되는 인스턴스가 merge() 메소드에 의해 반환된다.
EntityManager.remove()는 데이터베이스로부터 객체들 상태를 제거할 것이다. 물론 당신의 어플리케이션은 여전히 하나의 삭제된 객체에 대한 하나의 참조를 소유하고 있을 수 있다. 당신은 remove()를 하나의 영속 인스턴스를 다시 새롭게(별칭은 transient로) 만드는 것으로서 간주할 수 있다.그것은 분리된(detached) 것이 아니고, 병합은 하나의 insert로 귀결될 것이다.
시간이 지남에 따라 엔티티 관리자는 메모리 내에 유지되는 객체들의 상태를 데이터 저장소와 동기화 시키는데 필요한 SQL DML 문장들을 실행시킬 것이다. 이 과정, 즉 flush는 디폴트로(이것은 Hibernate에 특징적인 것이고 명세서에 정의된 것은 아니다) 다음 시점들에서 일어난다:
질의 실행 전
javax.persistence.EntityTransaction.commit() 시에
EntityManager.flush()가 호출될 때
SQL 문장들은 다음 순서로 일어난다
EntityManager.persist()를 사용하여 저장되었던 대응하는 객체들과 동일한 순서로 모든 엔티티 삽입들
모든 엔티티 업데이트들
모든 콜렉션 삭제들
모든 콜렉션 요소 삭제들, 업데이트들, 삽입들
모든 콜렉션 삽입들
EntityManager.remove()를 사용하여 삭제되었던 대응하는 객체들과 동일한 순서로 모든 엔티티 삭제들
(예외: 어플리케이션에 의해 할당된 식별자들을 사용하는 엔티티 인스턴스들은 그것들이 저장될 때 insert된다.)
당신이 명시적으로 flush() 시키는 때를 제외하면, 엔티티 관리자가 JDBC 호출들을 실행시키는 시점에 대한 절대적인 보장은 존재하지 않으며, 오직 그것들이 실행되는 순서 만이 보장된다. 하지만 Hibernate는 Query.getResultList()/Query.getSingleResult() 가 손상된 데이터를 결코 반환하지 않을 것임을 보장할 것이거나; 그것들은 잘못된 데이터를 반환하지 않을 것이다.
flush가 자주 발생하지 않도록 하기 위해 디폴트 특징을 변경시키는 것이 가능하다. 엔티티 관리자에 대한 FlushModeType은 세 개의 다른 모드들을 정의한다: 확약(commit) 시에만 flush 시키는 모드, 설명된 루틴을 사용한 자동적인 flush 모드, 또는 flush()가 명시적으로 호출되지 않는 한 결코 flush 시키지 않는 모드. 마지막 모드는 장기간 실행되는 확장된 영속 컨텍스트들에 유용하며, 여기서 컨텍스트와 그것의 엔티티 관리자가 열려진 채로 유지된다(그러나 JDBC 데이터소스로부터 연결 해제된다). TODO: 연결해제에 대한 링크를 추가할 것이지만, 연결해제는 구현 지정적이다.
em = emf.createEntityManager();
Transaction tx = em.getTransaction().begin();
em.setFlushMode(FlushModeType.COMMIT); // allow queries to return stale state
Cat izi = em.find(Cat.class, id);
izi.setName(iznizi);
// might return stale data
em.createQuery("from Cat as cat left outer join cat.kittens kitten").getResultList();
// change to izi is not flushed!
...
em.getTransaction().commit(); // flush occursflush 동안에, 하나의 예외상황이 발생할 수도 있다 (예를 들어. 하나의 DML 연산이 제약(컨스트레인트)을 위반할 경우). TODO: 예외상황 핸들링에 대한 링크 추가할 것.
개별 객체들을 저장하고, 삭제하고, 또는 재첨부하는 것은 특히 당신이 연관 객체들의 그래프를 다룰 때 꽤 귀찮다. 하나의 공통된 경우는 하나의 부모/자식 관계이다. 다음 예제를 검토하자:
만일 부모/자식 관계에서 자식이 값 타입일 경우(예를 들면. 주소 또는 문자열을 가진 하나의 콜렉션), 그것들의 생명주기는 부모에 의존할 것이고 상태 변경들에 대한 편리한 "케스케이딩"에 더 이상의 액션이 없을 것이다. 부모가 영속화 될 때, 값-타입의 자식 객체들도 마찬가지로 영속화 되고, 부모가 제거될 때, 자식이 제거될 것이다. 기타 마찬가지. 이것은 심지어 콜렉션으로부터 하나의 자식을 제거하는 것과 같은 연산들에 대해서도 동작한다; Hibernate는 이것을 검출해낼 것이고, 값-타입의 객체들이 공유된 참조들을 가질 수 없기 때문에, 데이터베이스로부터 자식을 제거할 것이다.
이제 값-타입이 아닌, 엔티티들인 부모 객체와 자식 객체에 대해 동일한 시나리오를 검토하자(예를 들면. 카테고리들과 아이템들, 또는 부모 고양이와 자식 고양이). 엔티티들은 그것들 자신의 생명주기를 갖고, 공유된 참조들을 지원하고(따라서 콜렉션으로부터 하나의 엔티티를 제거하는 것은 그것이 삭제될 수 있음을 의미하지 않는다), 하나의 엔티티로부터 임의의 다른 연관된 엔티티들로의 상태에 대한 케스케이딩이 디폴트로 존재하지 않는다. EJB3 명세서는 도달가능성(reachability)에 따른 영속성을 요구하지 않는다. 그것은 Hibernate에서 처음 보았듯이, 전이 영속에 대한 보다 유연한 모형을 지원한다.
엔티티 관리자의 각각의 기본 연산들- persist(), merge(), remove(), refresh()을 포함하여 - 의 경우, 하나의 대응하는 케스케이드 스타일이 존재한다. 케스케이드 스타일들은 각각 PERSIST, MERGE, REMOVE, REFRESH로 명명된다. 만일 당신이 하나의 연산이 연관된 엔티티 (또는 엔티티들을 가진 콜렉션)에 대해 케스케이드되기를 원한다면, 당신은 연관 주해(association annotation) 속에 그것을 진술해야 한다:
@OneToOne(cascade=CascadeType.PERSIST)
Cascading options can be combined:
@OneToOne(cascade= { CascadeType.PERSIST, CascadeType.REMOVE, CascadeType.REFRESH } )당신이 하나의 특별한 연관에 대해 모든 연산들이 케스케이드 되어야 함을 지정하는데 CascadeType.ALL을 사용할 수도 있다. 디폴트로 연산은 케스케이드되지 않음을 기억하라.
Hibernate는 보다 많은 native 케스케이딩 옵션들을 제공하는데, 추가 정보들은 Hibernate Annotations 매뉴얼과 Hibernate 참조 안내서를 참조하길 바란다.
권장사항들:
@ManyToOne 또는 @ManyToMany 연관에 대해 케스케이드를 사용 가능하도록 하는 것은 대개 의미가 없다. 케스케이드는 흔히 @OneToOne 연관과 @OneToMany 연관에 유용하다.
만일 자식 객체의 생명주기가 부모 객체의 생명주기에 의해 제한되어 있다면, CascadeType.ALL과 org.hibernate.annotations.CascadeType.DELETE_ORPHAN을 지정하여 부모를 하나의 완전한 생명주기 객체로 만들어라. (orphan delete의 의미에 대해서는 Hibernate 참조 안내서를 참조하길 바란다)
그 밖의 경우, 당신은 케스케이드를 전혀 필요로 하지 않을 수 있다. 그러나 당신이 자주 동일 트랜잭션 내에서 부모와 자식에 대해 함께 동작되어야 할 것이라고 당신이 생각할 경우, 그리고 당신 스스로 어떤 타입화를 저장하고자 원한다고 당신이 생각할 경우, cascade={PERSIST, MERGE} 사용을 고려하라. 이들 옵션들은 many-to-many 연관에 대해서조차 의미있게 만들 수 있다.