문제

나는 지금이 문제를 오랫동안 가지고 있습니다. 나는 웹을 검색했고 나가서 아직 해결책을 찾지 못했습니다. 나는 당신이 저를 도울 수 있기를 바랍니다.

다음과 같은 두 개체간에 부모-자식 관계가 있습니다.

@Entity
public class Parent {
    // ...

    @OneToMany(mappedBy = "parent", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
    private Set<Child> children = new HashSet<Child>();

    // ...
}

@Entity
public class Child {
    // ...

    @ManyToOne(fetch = FetchType.LAZY)
    private Parent parent;

    // ...
}

문제는 새 아이를 만들어 부모에게 할당 할 때 부모가 캐시에 이미있을 때 업데이트되지 않는다는 것입니다.

 Parent parent = new Parent();
 em.persist(parent);

 // ...

 Child child = new Child();
 child.setParent(parent);
 em.persist(child);

 parent.getChildren().size(); // returns 0

@preupdate를 사용하여 자녀가 지속될 때 자녀를 부모에게 자동으로 추가하려고했지만 2 개의 다른 스레드 (Jboss와 같은)에 2 명의 엔티티 관리자가있는 경우에도 전화 할 때까지 문제가 여전히 존재합니다. em.refresh(parent)

따라서 문제는 - 문제를 원활하게 제거하고 parent.getChildren() 항상 최신 어린이 목록을 반환합니까?

도움이 되었습니까?

해결책

대부분의 ORM은 이런 식으로 행동 할 것입니다.

캐시의 객체는 데이터베이스에서 업데이트되지 않습니다 (필요하지 않은 추가 읽기). 또한 객체 모델과 지속성을 별도로 생각하십시오. 즉, 객체 모델을 그 자체와 일치하게 유지하고 지속 메커니즘에 의존하지 않도록하십시오.

따라서 컬렉션에 객체를 추가하려면 "SetParent"코드로 수행하십시오.

이 경우 모범 사례는 실제로 관계의 한쪽이 모든 작업을 수행하고 다른 쪽이 연기하도록하는 것입니다. 또한 메소드 액세스 대신 필드 액세스를 사용하는 것이 좋습니다. 따라서 유연성을 높이기 위해 메소드를 사용자 정의 할 수 있습니다.

AddChild라는 부모에게 메소드를 추가하십시오

 public void addChild(Child child) {
    child.setParent0(this);
    getChildren().add(individualNeed);
 }

그런 다음 어린이의 세트 분비자를 만드십시오.

public void setParent(Parent parent) {
   parent.addChild(child);
}

어린이의 setParent0은 자녀의 부모를위한 재산 스터입니다.

public void setParent0(Parent parent) {
   this.parent = parent;
}

또한 "GetChildren"방법은 개발자 가이 방법을 부주의하게 사용하지 않도록 불변의 컬렉션을 반환 할 것을 제안합니다 (이 모든 방법에서 어려운 방법을 배웠습니다).

한 가지 더, 위의 코드에는 무효 점검 코드 및 기타 방어 조각이 있어야합니다. 명확성을 위해 남겨 두었습니다.

다른 팁

여기서 당신의 문제는 당신의 캐스케이드 설정이라고 확신합니다.

@Entity
public class Parent {
   // ...

   @OneToMany(mappedBy = "parent", fetch = FetchType.LAZY, 
      cascade = {CascadeType.REMOVE, CascadeType.PERSIST})
   @Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE})
   private Set<Child> children = new HashSet<Child>();

   // ...
}

@Entity
public class Child {
    // ...

    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
    @Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE})
    private Parent parent;

    // ...
}

이러한 캐스케이드 설정을 사용하면 캐스케이드가 지속되고 어린이 물체가 업데이트됩니다.

예를 들어.

Parent parent = new Parent();
em.persist(parent);

// ...

Child child = new Child();
child.setParent(parent);
em.persist(child); //will cascade update to parent

parent.getChildren().size(); // returns 1

또는

Parent parent = new Parent();
Child child = new Child();
parent.setChild(parent);
em.persist(parent); //will cascade update to child

child.getParent(); // returns the parent

이에 대한 자세한 정보는 다음에서 확인할 수 있습니다 최대 절전 모드 주석

캐싱 문제와 관련하여, 이것은 별도의 캐시가있는 동일한 데이터베이스에 대해 여러 VM이 실행될 때 매우 일반적인 문제입니다. "캐시 드리프트"라고합니다.

대부분의 최대 절전 모드 친화적 인 캐시 구현 (Ehcache, Oscache 및 Swarmcache)에는 캐시를 동기화하는 데 사용할 수있는 분산 캐시가 내장되어 있습니다. 분산 캐시는 일반적으로 캐시 상태를 업데이트하는 멀티 캐스트 메시지를 보냅니다. 예를 들어 SessionFactory.evict.evict (클래스, id)에 의해 두 번째 레벨 캐시 퇴거를 수행하면 무효화 메시지가 클러스터의 다른 캐시로 전송되어 다른 캐시에서 해당 객체의 다른 사본을 무효화합니다.

배포에 따라 멀티 캐스트는 귀하에게 허용되지 않을 수도 있고 아닐 수도 있습니다. 그렇지 않은 경우 Memcached와 같은 단일 캐시 솔루션을 사용해야 할 수도 있습니다.

개인적으로 EH 캐시의 분산 캐시 구성을 매우 간단하게 발견했습니다.

EH 캐시는 여기에서 문제에 대해 좀 더 자세히 설명합니다. http://ehcache.org/documentation/distributed_caching.html

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top