최대 절전 모드에서 분리 된 객체를 다시 부착하는 올바른 방법은 무엇입니까?


186

동일한 ID의 객체가 이미 세션에 존재할 수 있지만 분리 된 객체를 최대 절전 모드 세션에 다시 연결 해야하는 상황이 있습니다. 이로 인해 오류가 발생할 수 있습니다.

지금은 두 가지 중 하나를 수행 할 수 있습니다.

  1. getHibernateTemplate().update( obj ) 최대 절전 모드 세션에 개체가없는 경우에만 작동합니다. 주어진 식별자를 가진 객체가 나중에 필요할 때 세션에 이미 존재한다는 예외가 발생합니다.

  2. getHibernateTemplate().merge( obj ) 최대 절전 모드 세션에 개체가있는 경우에만 작동합니다. 나중에 이것을 사용하면 객체가 세션에 있어야 할 때 예외가 발생합니다.

이 두 가지 시나리오에서 세션을 객체에 일반적으로 어떻게 첨부 할 수 있습니까? 더 우아한 솔루션이 있어야하기 때문에이 문제의 솔루션 흐름을 제어하기 위해 예외를 사용하고 싶지 않습니다.

답변:


181

따라서 JPA에서 오래된 분리 엔티티를 다시 첨부 할 방법이없는 것 같습니다.

merge() 오래된 상태를 DB로 푸시하고 중재 업데이트를 덮어 씁니다.

refresh() 분리 된 엔티티에서 호출 할 수 없습니다.

lock() 분리 된 엔터티에서 호출 할 수없고, 가능한 경우에도 엔터티를 다시 연결하여 'LockMode.NONE'인수와 함께 'lock'을 호출하면 잠금이 아니라 잠금이 아니라는 것을 암시하는 것이 가장 반 직관적 인 API 디자인입니다. 나는 본 적이있다.

그래서 당신은 붙어 있습니다. 없다 detach()방법은 있지만, attach()reattach(). 개체 수명주기의 분명한 단계는 사용할 수 없습니다.

JPA에 대한 비슷한 질문의 수로 판단 할 때 JPA가 일관된 모델을 가지고 있다고 주장하더라도 많은 시간을 낭비하는 저주를받은 대부분의 프로그래머의 정신 모델과 일치하지 않는 것 같습니다. JPA는 가장 간단한 작업을 수행하고 응용 프로그램 전체에서 캐시 관리 코드로 끝납니다.

그것을 수행하는 유일한 방법은 오래된 분리 된 엔티티를 버리고 동일한 ID로 찾기 쿼리를 수행하여 L2 또는 DB에 충돌하는 것입니다.

미크


1
JPA 사양이 refresh()분리 된 엔티티를 허용하지 않는 이유가 있는지 궁금합니다 . 2.0 사양을 살펴보면 어떤 정당화도 보이지 않습니다. 그것은 허용되지 않습니다.
FGreg

11
이것은 정확하지 않습니다. JPwH에서 : *Reattaching a modified detached instance* A detached instance may be reattached to a new Session (and managed by this new persistence context) by calling update() on the detached object. In our experience, it may be easier for you to understand the following code if you rename the update() method in your mind to reattach()—however, there is a good reason it’s called updating.자세한 내용은 섹션 9.3.2
cwash

영구 객체는 훌륭하게 작동하며 더티 플래그는 초기로드와 flush () 시간 값 사이의 델타를 기반으로 설정됩니다. 분리 된 개체는 현재 필요하며 현재이 기능이 없습니다. 최대 절전 모드를 수행하는 방법은 분리 된 객체에 추가 해시 / ID를 추가하는 것입니다. 영구 객체와 마찬가지로 분리 된 객체의 마지막 상태에 대한 스냅 샷을 사용 가능한 상태로 유지하십시오. 따라서 기존의 모든 코드를 활용하여 분리 된 객체에 적용 할 수 있습니다. @mikhailfranco이 언급 한대로 "부실한 상태를 DB에 푸시하고 개입 업데이트를 덮어 쓰지 않습니다"
tom

2
Hibernate javadoc (JPA는 아님)에 따르면 lock(LockMode.NONE)실제로 일시적인 객체에서 호출 될 수 있으며 엔티티를 세션에 다시 연결합니다.
seanf

java.lang.IllegalArgumentException : org.hibernate.internal.SessionImpl.lock (SessionImpl.java:3491)의 지속성 컨텍스트에없는 엔티티가 org.hibernate.internal.SessionImpl.lock (SessionImpl)에 없습니다. com.github.vok.framework.DisableTransactionControlEMDelegate.lock (DB.kt)에서
Martin Vysny

32

이 모든 대답은 중요한 차이점을 놓치고 있습니다. update ()는 객체 그래프를 세션에 (다시) 첨부하는 데 사용됩니다. 전달한 객체는 관리되는 객체입니다.

merge ()는 실제로 (재) 첨부 API가 아닙니다. merge ()에 반환 값이 있습니까? 전달 된 그래프가 아닌 관리되는 그래프를 반환하기 때문입니다. merge ()는 JPA API이며 해당 동작은 JPA 사양에 의해 관리됩니다. merge ()에 전달한 객체가 이미 관리되어있는 경우 (이미 세션과 연결되어 있음) Hibernate가 작동하는 그래프입니다. 전달 된 객체는 merge ()에서 반환 된 것과 동일한 객체입니다. 그러나 merge ()에 전달한 객체가 분리되면 Hibernate는 관리되는 새 객체 그래프를 생성하고 분리 된 그래프의 상태를 새로운 관리 형 그래프로 복사합니다. 다시 말하지만, 이는 모두 JPA 사양에 따라 결정되고 적용됩니다.

"이 엔티티가 관리되는지 또는 관리되도록"에 대한 일반적인 전략의 관점에서 아직 삽입되지 않은 데이터를 고려할 것인지에 따라 다릅니다. 당신이 그렇게 가정하면, 같은 것을 사용하십시오

if ( session.contains( myEntity ) ) {
    // nothing to do... myEntity is already associated with the session
}
else {
    session.saveOrUpdate( myEntity );
}

update () 대신 saveOrUpdate ()를 사용했습니다. 아직 삽입되지 않은 데이터를 처리하지 않으려면 update ()를 대신 사용하십시오.


3
이것이이 질문에 대한 정답입니다-사건이 종결되었습니다!
cwash

2
Session.contains(Object)참조로 확인합니다. 세션에 동일한 행을 나타내는 다른 엔티티가 이미 있고 분리 된 인스턴스를 전달하면 예외가 발생합니다.
djmj

Session.contains(Object)참조 로 확인하면 세션에 동일한 행을 나타내는 다른 엔터티 가 있으면 false를 반환하고 업데이트합니다.
AxelWass

19

외교적 대답 : 아마도 확장 된 지속성 컨텍스트를 찾고있을 것입니다. 이것이 Seam Framework 의 주요 이유 중 하나입니다. 특히 Spring에서 Hibernate를 사용하는 데 어려움을 겪고 있다면 Seam의 문서를 확인하십시오 .

외교적 답변 : 이것은 Hibernate docs에 설명되어있다 . 더 자세한 설명이 필요하면 "분리 된 객체로 작업하기"라는 Hibernate를 사용한 Java Persistence 섹션 9.3.2를 살펴보십시오 . 나는 거라고 강하게 당신이 Hibernate에서 CRUD보다 더 많은 것을하고 있다면이 책을받을 것을 권장합니다.


5
에서 seamframework.org : 링크 "Seam의 문서의이 작품을" "심 3의 적극적인 개발은 Red Hat에서 중지되었습니다."도 죽었어요.
badbishop

14

엔터티가 수정되지 않았다고 확신하는 경우 (또는 수정 내용이 손실 될 것이라는 데 동의 한 경우) 잠금을 사용하여 세션에 다시 연결할 수 있습니다.

session.lock(entity, LockMode.NONE);

아무것도 잠그지 않지만 세션 캐시에서 엔티티를 가져 오거나 (없는 경우) DB에서 엔티티를 읽습니다.

"예를 들어 HttpSession의"엔터티에서 관계를 탐색 할 때 LazyInitException을 방지하는 것이 매우 유용합니다. 먼저 엔티티를 "다시 첨부"하십시오.

상속이 매핑 된 경우 (getId ()에서 이미 예외가 발생 함)를 제외하고 get을 사용하는 것도 가능합니다.

entity = session.get(entity.getClass(), entity.getId());

2
엔터티를 세션과 다시 연결하고 싶습니다. 불행히도 Session.lock(entity, LockMode.NONE)예외적으로 실패합니다. 초기화되지 않은 일시적인 컬렉션을 다시 연결할 수 없습니다. 이것을 어떻게 극복 할 수 있습니까?
dma_k

1
사실 나는 완전히 옳지 않았다. lock ()을 사용하면 엔터티가 다시 연결되지만 다른 엔터티는 바인딩되지 않습니다. 따라서 entity.getOtherEntity (). getYetAnotherEntity ()를 수행하면 LazyInit 예외가있을 수 있습니다. 내가 극복 할 수있는 유일한 방법은 find를 사용하는 것입니다. entity = em.find (entity.getClass (), entity.getId ();
John Rizzo

Session.find()API 메소드 가 없습니다 . 아마도 당신은 의미 Session.load(Object object, Serializable id)합니다.
dma_k

11

이것은 매우 일반적인 질문 이므로이 답변을 기반으로하는이 기사를 작성 했습니다.

엔터티 상태

JPA는 다음 엔티티 상태를 정의합니다.

새로운 (일시적)

Hibernate Session(aka Persistence Context)와 연결되지 않았으며 데이터베이스 테이블 행에 매핑 되지 않은 새로 생성 된 객체 는 New (Transient) 상태 인 것으로 간주됩니다.

지속 되려면 EntityManager#persist메소드 를 명시 적으로 호출 하거나 전이 지속 메커니즘을 사용해야합니다.

지속적 (관리)

지속성 엔티티가 데이터베이스 테이블 행과 연관되었으며 현재 실행중인 지속성 컨텍스트에 의해 관리되고 있습니다. 이러한 엔티티에 대한 모든 변경 사항이 감지되어 세션 세션 시간 동안 데이터베이스에 전파됩니다.

최대 절전 모드를 사용하면 더 이상 INSERT / UPDATE / DELETE 문을 실행할 필요가 없습니다. Hibernate는 트랜잭션 쓰기-비하인드 작업 스타일을 사용하며 현재 Session플러시 시간 동안 가장 마지막 책임있는 순간에 변경 사항이 동기화됩니다 .

분리

현재 실행중인 지속성 컨텍스트가 닫히면 이전에 관리 된 모든 엔티티가 분리됩니다. 연속적인 변경 사항은 더 이상 추적되지 않으며 자동 데이터베이스 동기화가 수행되지 않습니다.

엔터티 상태 전환

EntityManager인터페이스에서 정의한 다양한 방법을 사용하여 엔티티 상태를 변경할 수 있습니다 .

JPA 엔티티 상태 전이를 더 잘 이해하려면 다음 다이어그램을 고려하십시오.

JPA 엔티티 상태 전환

JPA를 사용하는 경우 분리 된 엔티티를 active에 다시 연관시키기 EntityManager위해 병합 조작을 사용할 수 있습니다 .

을 제외하고 기본 Hibernate API를 사용하는 merge경우 다음 다이어그램에 표시된 것처럼 업데이트 방법을 사용하여 분리 된 엔티티를 활성 Hibernate 세션에 다시 연결할 수 있습니다.

최대 절전 모드 상태 전환

분리 된 엔터티 병합

병합이 분리 된 엔티티 상태 (소스)를 관리 엔티티 인스턴스 (대상)에 복사하려고합니다.

다음 Book엔티티 EntityManager를 유지했으며 이제 엔티티를 닫는 데 사용 된 엔티티가 닫히면 엔티티가 분리됩니다 .

Book _book = doInJPA(entityManager -> {
    Book book = new Book()
    .setIsbn("978-9730228236")
    .setTitle("High-Performance Java Persistence")
    .setAuthor("Vlad Mihalcea");

    entityManager.persist(book);

    return book;
});

엔티티가 분리 상태 인 동안 다음과 같이 수정합니다.

_book.setTitle(
    "High-Performance Java Persistence, 2nd edition"
);

이제 변경 사항을 데이터베이스에 전파하여 merge메소드를 호출 할 수 있습니다 .

doInJPA(entityManager -> {
    Book book = entityManager.merge(_book);

    LOGGER.info("Merging the Book entity");

    assertFalse(book == _book);
});

그리고 최대 절전 모드는 다음 SQL 문을 실행합니다.

SELECT
    b.id,
    b.author AS author2_0_,
    b.isbn AS isbn3_0_,
    b.title AS title4_0_
FROM
    book b
WHERE
    b.id = 1

-- Merging the Book entity

UPDATE
    book
SET
    author = 'Vlad Mihalcea',
    isbn = '978-9730228236',
    title = 'High-Performance Java Persistence, 2nd edition'
WHERE
    id = 1

병합 엔티티가 current에 해당하는 것이 없으면 EntityManager데이터베이스에서 새로운 엔티티 스냅 샷을 가져옵니다.

관리 대상 엔티티가 있으면 JPA는 분리 된 엔티티의 상태를 현재 관리되는 엔티티에 복사하고 지속성 컨텍스트flush 동안 더티 검사 메커니즘 이 관리 엔티티가 변경된 것을 발견 하면 UPDATE가 생성됩니다 .

따라서를 사용할 때 merge분리 된 객체 인스턴스는 병합 작업 후에도 분리 된 상태를 유지합니다.

분리 된 엔터티 다시 연결

최대 절전 모드이지만 JPA는이 update방법을 통한 재 연결을 지원합니다 .

최대 절전 모드 Session는 지정된 데이터베이스 행에 대해 하나의 엔터티 개체 만 연결할 수 있습니다. 지속성 컨텍스트는 메모리 내 캐시 (첫 번째 레벨 캐시)로 작동하고 하나의 값 (엔티티) 만 주어진 키 (엔티티 유형 및 데이터베이스 식별자)와 연관되기 때문입니다.

현재 Hibernate와 이미 연결된 다른 JVM 오브젝트 (같은 데이터베이스 행과 일치)가없는 경우에만 엔티티를 다시 첨부 할 수 있습니다 Session.

Book엔터티 가 지속되고 엔터티 Book가 분리 된 상태 일 때 수정 한 것을 고려하면 다음 과 같습니다.

Book _book = doInJPA(entityManager -> {
    Book book = new Book()
    .setIsbn("978-9730228236")
    .setTitle("High-Performance Java Persistence")
    .setAuthor("Vlad Mihalcea");

    entityManager.persist(book);

    return book;
});

_book.setTitle(
    "High-Performance Java Persistence, 2nd edition"
);

분리 된 엔티티를 다음과 같이 다시 첨부 할 수 있습니다.

doInJPA(entityManager -> {
    Session session = entityManager.unwrap(Session.class);

    session.update(_book);

    LOGGER.info("Updating the Book entity");
});

그리고 최대 절전 모드는 다음 SQL 문을 실행합니다.

-- Updating the Book entity

UPDATE
    book
SET
    author = 'Vlad Mihalcea',
    isbn = '978-9730228236',
    title = 'High-Performance Java Persistence, 2nd edition'
WHERE
    id = 1

update방법은 당신을 필요로 하이버 네이트에 .unwrapEntityManagerSession

와 달리 merge제공된 분리 된 엔티티는 현재 지속성 컨텍스트와 다시 연관되며 엔티티가 수정되었는지 여부에 관계없이 플러시 중에 UPDATE가 스케줄됩니다.

이를 방지하기 위해 @SelectBeforeUpdateHibernate 어노테이션을 사용하여 로드 된 상태를 페치 한 SELECT 문을 트리거 한 다음 더티 점검 메커니즘에서 사용합니다.

@Entity(name = "Book")
@Table(name = "book")
@SelectBeforeUpdate
public class Book {

    //Code omitted for brevity
}

NonUniqueObjectException에주의하십시오

update지속성 컨텍스트에 이미 다음 예제에서와 동일한 ID 및 동일한 유형의 엔티티 참조가 포함되어있는 경우 발생할 수있는 한 가지 문제점입니다 .

Book _book = doInJPA(entityManager -> {
    Book book = new Book()
    .setIsbn("978-9730228236")
    .setTitle("High-Performance Java Persistence")
    .setAuthor("Vlad Mihalcea");

    Session session = entityManager.unwrap(Session.class);
    session.saveOrUpdate(book);

    return book;
});

_book.setTitle(
    "High-Performance Java Persistence, 2nd edition"
);

try {
    doInJPA(entityManager -> {
        Book book = entityManager.find(
            Book.class,
            _book.getId()
        );

        Session session = entityManager.unwrap(Session.class);
        session.saveOrUpdate(_book);
    });
} catch (NonUniqueObjectException e) {
    LOGGER.error(
        "The Persistence Context cannot hold " +
        "two representations of the same entity",
        e
    );
}

이제 위의 테스트 케이스를 실행할 때 Hibernate는 NonUniqueObjectException두 번째에 EntityManager이미 Book전달한 것과 동일한 식별자를 가진 엔티티를 포함 update하고 Persistence Context가 동일한 엔티티의 두 가지 표현을 보유 할 수 없기 때문에 a를 던질 것 입니다.

org.hibernate.NonUniqueObjectException:
    A different object with the same identifier value was already associated with the session : [com.vladmihalcea.book.hpjp.hibernate.pc.Book#1]
    at org.hibernate.engine.internal.StatefulPersistenceContext.checkUniqueness(StatefulPersistenceContext.java:651)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:284)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:227)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:92)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:73)
    at org.hibernate.internal.SessionImpl.fireSaveOrUpdate(SessionImpl.java:682)
    at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:674)

결론

merge방법은 당신이 업데이트 손실을 방지 할 수 있습니다 당신이 낙관적 잠금을 사용하는 경우 선호된다. 이 주제에 대한 자세한 내용은 이 기사를 확인 하십시오 .

이는 작업에 update의해 생성 된 추가 SELECT 문을 방지 merge하여 일괄 업데이트 실행 시간을 줄일 수 있으므로 일괄 업데이트에 유용합니다 .


좋은 대답입니다. @SelectBeforeUpdate그래도 주석 에 대해 궁금했습니다 . 선택이 언제 트리거됩니까? update플러시 직전에 호출 하거나 실제로 중요하지 않습니다 (플러시하기 전에 한 번의 호출로 모든 주석이 달린 엔터티를 가져온다면 문제가 될 수 있습니까)?
Andronicus

@SelectBeforeUpdate지속성 문맥 중에 SELECT 트리거 flush동작. 자세한 내용 getDatabaseSnapshot방법을DefaultFlushEntityEventListener 확인 하십시오.
Vlad Mihalcea

10

JavaDoc으로 돌아가서 org.hibernate.Session다음을 발견했습니다.

과도 인스턴스 호출에 의해 영속화 할 수있다 save(), persist()또는 saveOrUpdate(). 을 호출하여 영구 인스턴스를 일시적으로 만들 수 있습니다 delete(). get()또는 load()메소드가 반환 한 모든 인스턴스 는 영구적입니다. 분리 된 인스턴스를 호출하여 영속화 할 수있다 update(), saveOrUpdate(), lock()또는 replicate(). 임시 인스턴스 또는 분리 된 인스턴스의 상태는를 호출하여 새 영구 인스턴스로 유지 될 수도 있습니다 merge().

따라서 update(), saveOrUpdate(), lock(), replicate()merge()후보 옵션이 있습니다.

update(): 식별자가 동일한 영구 인스턴스가 있으면 예외가 발생합니다.

saveOrUpdate(): 저장 또는 업데이트

lock(): 더 이상 사용되지 않음

replicate(): 현재 식별자 값을 재사용하여 주어진 분리 된 인스턴스의 상태를 유지합니다.

merge(): 식별자가 동일한 영속 객체를 반환합니다. 주어진 인스턴스가 세션과 연관되지 않습니다.

따라서, lock()곧바로 사용되어서는 안되며 기능 요구 사항에 따라 하나 이상을 선택할 수 있습니다.


7

NHibernate를 사용하여 C #에서 그렇게했지만 Java에서 동일한 방식으로 작동해야합니다.

public virtual void Attach()
{
    if (!HibernateSessionManager.Instance.GetSession().Contains(this))
    {
        ISession session = HibernateSessionManager.Instance.GetSession();
        using (ITransaction t = session.BeginTransaction())
        {
            session.Lock(this, NHibernate.LockMode.None);
            t.Commit();
        }
    }
}

Contains가 항상 false이므로 모든 객체에서 첫 번째 잠금이 호출되었습니다. 문제는 NHibernate가 데이터베이스 ID와 유형별로 객체를 비교한다는 것입니다. 포함 equals하지 않은 경우 참조로 비교 하는 메소드를 사용합니다 . 이 equals방법을 사용하면 예외없이 작동합니다.

public override bool Equals(object obj)
{
    if (this == obj) { 
        return true;
    } 
    if (GetType() != obj.GetType()) {
        return false;
    }
    if (Id != ((BaseObject)obj).Id)
    {
        return false;
    }
    return true;
}

4

Session.contains(Object obj) 참조를 확인하고 동일한 행을 나타내고 이미 연결된 다른 인스턴스를 감지하지 않습니다.

여기에 식별자 속성이있는 엔티티에 대한 일반적인 해결책이 있습니다.

public static void update(final Session session, final Object entity)
{
    // if the given instance is in session, nothing to do
    if (session.contains(entity))
        return;

    // check if there is already a different attached instance representing the same row
    final ClassMetadata classMetadata = session.getSessionFactory().getClassMetadata(entity.getClass());
    final Serializable identifier = classMetadata.getIdentifier(entity, (SessionImplementor) session);

    final Object sessionEntity = session.load(entity.getClass(), identifier);
    // override changes, last call to update wins
    if (sessionEntity != null)
        session.evict(sessionEntity);
    session.update(entity);
}

이것은 내가 좋아하는 .Net EntityFramework의 몇 가지 측면 중 하나이며 변경된 엔티티 및 해당 속성에 관한 다른 첨부 옵션입니다.


3

세션에 이미 연결된 다른 개체를 설명하는 지속성 저장소에서 개체를 "새로 고치는"솔루션을 찾았습니다.

public void refreshDetached(T entity, Long id)
{
    // Check for any OTHER instances already attached to the session since
    // refresh will not work if there are any.
    T attached = (T) session.load(getPersistentClass(), id);
    if (attached != entity)
    {
        session.evict(attached);
        session.lock(entity, LockMode.NONE);
    }
    session.refresh(entity);
}

2

죄송하지만 댓글을 추가 할 수 없습니다 (아직?).

최대 절전 모드 3.5.0 사용

Session#lock방법은 더 이상 사용되지 않지만 javadoc 사용을 제안 Session#buildLockRequest(LockOptions)#lock(entity)하고 연결이 있는지 확인 cascade=lock하면 지연 로딩도 문제가되지 않습니다.

그래서 내 연결 방법은 약간 비슷합니다.

MyEntity attach(MyEntity entity) {
    if(getSession().contains(entity)) return entity;
    getSession().buildLockRequest(LockOptions.NONE).lock(entity);
    return entity;

초기 테스트는 치료법이 효과가 있다고 제안합니다.


2

아마도 Eclipselink에서 약간 다르게 동작합니다. 오래된 데이터를 가져 오지 않고 분리 된 객체를 다시 연결하려면 일반적으로 다음을 수행합니다.

Object obj = em.find(obj.getClass(), id);

그리고 옵션으로 두 번째 단계로 캐시를 무효화합니다.

em.refresh(obj)

1

getHibernateTemplate (). replicate (entity, ReplicationMode.LATEST_VERSION)을 시도하십시오.


1

원래 포스트에서는 두 가지 방법이있다, update(obj)그리고 merge(obj)그 반대 인 상황에서, 일에 언급되어있다. 이것이 실제로 사실이라면, 객체가 이미 세션에 있는지 확인한 다음 호출 update(obj)하고 그렇지 않으면 호출하십시오 merge(obj).

세션에 존재하는 테스트는 session.contains(obj)입니다. 따라서 다음 의사 코드가 작동한다고 생각합니다.

if (session.contains(obj))
{
    session.update(obj);
}
else 
{
    session.merge(obj);
}

2
contains () 검사는 참조로 비교하지만 최대 절전 모드 함수는 데이터베이스 ID로 작동합니다. 코드에서 session.merge가 호출되지 않습니다.
Verena Haunschmid

1

이 객체를 다시 연결하려면 merge ()를 사용해야합니다.

이 메소드는 매개 변수로 엔티티를 분리하고 엔티티를 리턴하여 데이터베이스에서 다시로드합니다.

Example :
    Lot objAttach = em.merge(oldObjDetached);
    objAttach.setEtat(...);
    em.persist(objAttach);

0

영속 인스턴스를 업데이트하기 위해 첫 번째 merge ()를 호출 한 다음 현재 인스턴스를 첨부하기 위해 lock (LockMode.NONE)을 호출하는 경우 (use ()가 반환 한 인스턴스가 아닌) 일부 유스 케이스에서 작동하는 것으로 보입니다.


0

재산 hibernate.allow_refresh_detached_entity은 나를 위해 속임수를했다. 그러나 일반적인 규칙이므로 일부 경우에만 수행하려는 경우에는 적합하지 않습니다. 도움이 되길 바랍니다.

최대 절전 모드 5.4.9에서 테스트

SessionFactoryOptionsBuilder



당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.