최대 절전 모드-모든 오르파반으로 컬렉션을 지우고 추가하면 제약 ViolationException이 발생합니다.

StackOverflow https://stackoverflow.com/questions/2065254

  •  20-09-2019
  •  | 
  •  

문제

나는이 엔티티가 있습니다

class Foo{
    Set<Bar> bars;
}

class Bar{
    Foo parent;
    String localIdentifier;
}

이 매핑으로 (죄송합니다, 주석이없고, 구식입니다) :

<class name="Foo">
    ...
    <set name="bars" cascade="all-delete-orphan" lazy="false" inverse="true">
        <key>...</key>
        <one-to-many class="Bar"/>
    </set>
</class>


<class name="Bar">
    ...
    <property name="localIdentifier" column="local_identifier"/>
    <many-to-one name="parent" column="parent_id" />
</class>

또한 두 열에 고유 한 제약 조건이 있습니다. local_identifier 그리고 parent_id (각각에 대한 고유 한 제약 조건은 아니지만 동일한 부모와 동일한 LocalIndifier가있는 2 행이 허용되는 단일 고유 한 제약 조건이 허용됩니다)

alter table bar add constraint unique_bar unique (parent_id, local_identifier)

그리고이 코드를 사용하는 코드 :

//foo is persistent, foo id = 1
Bars bars = foo.getBars();
bars.clear(); // bars contained 1 item [parent_id = 1, local_identifier = "a"]
Bar newBar = new Bar();
newBar.setParent(foo);
newBar.setLocalIdentifier("a");
bars.add(newBar);

이제 어떤 이유로, Hibernate는 그들이 호출 된 순서대로 사물을 실행하지 않습니다. 그것은 실행되지 않습니다 clear() (삭제) 전에 add() (삽입) 그러나 그 반대도 마찬가지로, 먼저 삽입하려고 시도하고 ConstraintViolationException

나는 조금 추가한다는 것을 안다 session.flush() ~ 후에 bars.clear(); , 이것을 고칠 수는 있지만,이 경우, 나는 추악한 방식으로 세션에 액세스 할 수 없습니다.

플러시가 유일한 솔루션입니까? 아니면 행동 순서를 존중하는 최대 절전 모드 버전이 있습니까?

업데이트:그건 그렇고, 컬렉션을 해독하는 것은 https://www.hibernate.org/117.html#a3:

HibernateException을 얻습니다 : Cascade = "All-Delete-Orphan"이있는 컬렉션을 해석하지 마십시오. 캐스케이드 = "All-Delete-Orphan"컬렉션이있는 객체를로드 한 다음 컬렉션에 대한 참조를 제거하면 발생합니다. 이 컬렉션을 교체하지 말고 Clear ()를 사용하여 Orphan Deletion 알고리즘이 변경 사항을 감지 할 수 있습니다.

도움이 되었습니까?

해결책

플러싱에 대한 대안이 없다고 생각합니다

에서 여기:

최대 절전 모드는 독특한 제약을 위반하고 있습니다!

최대 절전 모드는 외국 키와 마찬가지로 고유 한 제약으로 영리하지 않습니다. 때로는 약간의 힌트를 주어야 할 수도 있습니다.

두 객체가 모두 업데이트되는 경우 고유 한 제약 조건 위반이 발생할 수 있으며, 하나는 값을 "발표"하고 다른 하나는 동일한 값을 얻는 것 "입니다. 해결 방법은 다음과 같습니다 플러시() 첫 번째 객체를 업데이트 한 후 수동으로 세션이 및 두 번째 객체를 업데이트하기 전에 수동으로 세션입니다.

(이런 종류의 문제는 실제로 거의 발생하지 않습니다.)

다른 팁

여기에서 세션을 플러시하지 않으려면 전체 목록을 교체하십시오 (new List<Bar>() 대신에 Clear()). 최대 절전 모드는 실제로 새로운 추가하기 전에 한 번의 모든 항목을 한 번으로 제거해야합니다. 작동하는지 확실하지 않습니다.

Oracle을 사용하는 경우 연기 가능한 제약 조건을 사용하여 거래가 커밋 될 때까지 제약 조건을 연기 할 수도 있습니다. 다른 데이터베이스에서 이것이 어떻게 지원되는지 확실하지 않습니다.

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