(제거 관련이없는 물건을)은 다음과 같이 나는 정의 된 두 개의 엔티티 빈을 다음과 같이정지 최대 절전 모드에서가 변경되지 않은 경우 컬렉션을 업데이트
@Entity
@Table(...)
public class MasterItem implements java.io.Serializable {
private Set<CriticalItems> criticalItemses = new HashSet<CriticalItems>(0);
@OneToMany(fetch = FetchType.EAGER, mappedBy = "masterItem", orphanRemoval = true,
cascade = {javax.persistence.CascadeType.DETACH})
@Cascade({CascadeType.SAVE_UPDATE, CascadeType.DELETE})
public Set<CriticalItems> getCriticalItemses() {
return this.criticalItemses;
}
}
CriticalItems가 정의 :
@Entity
@Table(...)
public class CriticalItems implements java.io.Serializable {
private MasterItem masterItem;
@ManyToOne(fetch = FetchType.LAZY, optional = false,
cascade = {javax.persistence.CascadeType.DETACH})
@Cascade({CascadeType.SAVE_UPDATE})
@JoinColumn(name = "mi_item_id", nullable = false)
public MasterItem getMasterItem() {
return this.masterItem;
}
}
그리고에 내 DAO 코드 - 나는이 방법을 가지고있다.
public MasterItem load(int id) {
MasterItem results = (MasterItem) getSessionFactory().getCurrentSession()
.get("com.xxx.MasterItem", id);
}
public void save(MasterItem master) {
// master has been changed by the UI since it
getSessionFactory().getCurrentSession().saveOrUpdate(master);
}
내가 MasterItem을로드 할 때 올바르게로드된다. d는 지정된대로 데이터가있는 CriticalItems Set를로드합니다. 그런 다음이 데이터를 UI로 보내고 업데이트 된 복사본을 얻은 다음 계속 유지하려고합니다. 사용자는 MasterItem 개체의 필드를 업데이트하지만 그 안에있는 어떠한 항목도 건드리지 않습니다. 변경되지 않은 상태로 유지됩니다.
내 save() 메소드가 호출 될 때, Hibernate는 어떤 식 으로든 변경된 것이 없더라도 Set of CriticalItems의 각 항목에 대해 SQL 업데이트를 보내야한다고 주장하고 있습니다.
일부 파기 후, 여기 내가 생각하는 바가 있습니다. Hibernate는 saveOrUpdate()를 수행 할 때 MasterItem 객체가 detached 상태에 있음을보고 디스크에서 다시로드하려고 시도합니다. 그러나 이렇게 할 때 준비된 문 (시작시 Hibernate에 의해 자동 생성됨)을 사용하는 것처럼 보입니다.이 준비된 문은 CriticalItems 데이터에 조인을 시도하지 않습니다.
그래서 Hibernate는 전체 CriticalItems 세트를 가진 나의 업데이트 된 MasterItem 객체를 가지고 있지만, collections없이 그것의 "previousState"객체로 MasterItem을 사용한다. 따라서 모든 CriticalItem은 SQL을 통해 업데이트됩니다 (삽입되지 않음, 그 자체로 흥미 롭습니다).
이 동작을 일으키는 특수 효과에서 내가 뭔가를 했습니까? 나는 인터셉터를 사용하여 아이템이 실제로 변경되었거나, Hibernate의 디폴트 알고리즘을 오버라이드하도록 더티 플래그를 변경했다는 것을 알았다. 그러나 이것은 Hibernate가 내 간섭없이 독자적으로 처리해야하는 것으로 보인다.
어떤 통찰력도 인정 될 것입니다.
업데이트 : 의견을 바탕으로 saveOrUpdate()와 merge()의 차이점을 이해하고 있다고 생각합니다. 나는 saveOrUpdate()가 모든 경우에 SQL INSERT 또는 SQL UPDATE를 초래할 것이고, 객체가 영속 상태에서 변경된 경우에만 이론상 병합을 업데이트 할 것이라고 생각하지만이를 확인하기 위해 최대 절전 모드 SQL SELECT를 통해 먼저 객체를 다시로드해야합니다.
그래서 내 코드로 돌아가서 saveOrUpdate()를 merge()로 변경하면 작동 할 것이라고 생각했지만 실제로는 그렇지 않습니다.
내가 병합(), 내가org.springframework.orm.hibernate3.HibernateSystemException: could not initialize proxy - no Session; nested exception is org.hibernate.LazyInitializationException: could not initialize proxy - no Session
을 얻고 있었다를 사용하는 경우 그러나 나는 될 saveOrUpdate로 다시 변경 한 경우는 괜찮 았는데().
나는 마침내 왜 - 내 @Cascade
어노테이션 (우)에 CascadeType.MERGE
을 포함시키지 않았 음을 알게되었습니다. 일단 내가 그것을 고쳤다면, 예외는 사라졌다.
낙관적 인 잠금 열 (date od int 형식의 @version 주석이 달린 열) – lweller