[java] Hibernate Error : 동일한 식별자 값을 가진 다른 개체가 이미 세션과 연결되었습니다.

기본적으로이 구성에 몇 가지 개체가 있습니다 (실제 데이터 모델은 조금 더 복잡합니다).

  • A는 B와 다 대다 관계를 가지고 있습니다. (B는 inverse="true")
  • B는 C와 다 대일 관계를 가지고 있습니다. (로 cascade설정했습니다 "save-update")
  • C는 유형 / 카테고리 테이블의 일종입니다.

또한 기본 키는 저장시 데이터베이스에 의해 생성된다는 점을 언급해야합니다.

내 데이터로 A에 다른 B 개체 집합이 있고 이러한 B 개체가 동일한 C 개체를 참조하는 문제가 가끔 발생합니다.

을 호출 session.saveOrUpdate(myAObject)하면 다음과 같은 최대 절전 모드 오류가 발생 "a different object with the same identifier value was already associated with the session: C"합니다. 최대 절전 모드가 동일한 세션에서 동일한 객체를 두 번 삽입 / 업데이트 / 삭제할 수 없다는 것을 알고 있지만이 문제를 해결할 수있는 방법이 있습니까? 이것은 드문 상황이 아닌 것 같습니다.

이 문제를 조사하는 동안 사람들이를 사용하는 것을 제안하는 것을 보았습니다 session.merge().하지만 그렇게하면 “충돌하는”개체가 모든 값이 null로 설정된 빈 개체로 데이터베이스에 삽입됩니다. 분명히 그것은 우리가 원하는 것이 아닙니다.

[편집] 내가 언급하는 것을 잊은 또 다른 점은 (내가 통제 할 수없는 구조적인 이유로) 각 읽기 또는 쓰기는 별도의 세션에서 수행되어야한다는 것입니다.



답변

아마도 B 객체가 동일한 Java C 객체 인스턴스를 참조하지 않기 때문일 것입니다. 데이터베이스에서 동일한 행 (즉, 동일한 기본 키)을 참조하지만 다른 사본입니다.

그래서 일어나고있는 것은 엔티티를 관리하는 Hibernate 세션이 동일한 기본 키를 가진 행에 해당하는 Java 객체를 추적하는 것입니다.

한 가지 옵션은 동일한 행을 참조하는 개체 B의 엔터티가 실제로 C의 동일한 개체 인스턴스를 참조하는지 확인하는 것입니다. 또는 해당 멤버 변수에 대해 계단식 연결을 해제합니다. 이렇게하면 B가 지속될 때 C는 그렇지 않습니다. 하지만 C를 수동으로 별도로 저장해야합니다. C가 유형 / 범주 테이블 인 경우 그 방법이 이치에 맞을 것입니다.


답변

cascade를 MERGE로 설정하기 만하면됩니다.


답변

한 가지만하면됩니다. session_object.clear()새 개체를 실행 하고 저장합니다. 이렇게하면 세션 (적절한 이름)이 지워지고 세션에서 문제가되는 중복 개체가 제거됩니다.


답변

@Hemant Kumar에 동의합니다. 대단히 감사합니다. 그의 해결책에 따라 나는 내 문제를 해결했습니다.

예 :

@Test
public void testSavePerson() {
    try (Session session = sessionFactory.openSession()) {
        Transaction tx = session.beginTransaction();
        Person person1 = new Person();
        Person person2 = new Person();
        person1.setName("222");
        person2.setName("111");
        session.save(person1);
        session.save(person2);
        tx.commit();
    }
}

Person.java

public class Person {
    private int id;
    private String name;

    @Id
    @Column(name = "id")
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @Basic
    @Column(name = "name")
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

이 코드는 항상 내 응용 프로그램에서 실수를합니다.
A different object with the same identifier value was already associated with the session, 나중에 기본 키자동 으로 늘리는 것을 잊었 음을 알게되었습니다 !

내 해결책은 기본 키에이 코드를 추가하는 것입니다.

@GeneratedValue(strategy = GenerationType.AUTO)


답변

즉, 동일한 개체에 대한 참조를 사용하여 테이블에 여러 행을 저장하려고합니다.

엔티티 클래스의 id 속성을 확인하십시오.

@Id
private Integer id;

…에

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(unique = true, nullable = false)
private Integer id;


답변

다음을 사용하여 Hibernate에서 데이터베이스로 개체 ID를 할당하는 작업을 전송합니다.

<generator class="native"/>

이것은 나를 위해 문제를 해결했습니다.


답변

삽입중인 Bean에 @GeneratedValue 어노테이션을 추가하십시오.