your programing

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

lovepro 2020. 10. 14. 08:16
반응형

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


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

  • 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)

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

<generator class="native"/>

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


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


위의 문제를 해결하는 한 가지 방법은 hashcode().
또한 저장 전후에 최대 절전 모드 세션을 플러시하십시오.

getHibernateTemplate().flush();

분리 된 개체를로 명시 적으로 설정하는 null것도 도움이됩니다.


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

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

@Id
private Integer id;

...에

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

이 메시지를 보았지만 C # 코드입니다. 관련성이 있는지 확실하지 않습니다 (정확히 동일한 오류 메시지).

중단 점을 사용하여 코드를 디버깅하고 디버거가 중단 점에있는 동안 개인 멤버를 통해 일부 컬렉션을 확장했습니다. 구조를 파헤 치지 않고 코드를 다시 실행하면 오류 메시지가 사라졌습니다. 개인 지연로드 컬렉션을 조사하는 행위로 인해 NHibernate가 그 당시로드되지 않았던 것들을로드하게 된 것 같습니다 (개인 멤버에 있었기 때문에).

코드 자체는 해당 트랜잭션 (가져 오기 프로세스)의 일부로 많은 레코드와 많은 종속성을 업데이트 할 수있는 상당히 복잡한 트랜잭션으로 래핑됩니다.

문제를 접한 다른 사람에게 단서가 되었기를 바랍니다.


Hibernate에서 "Cascade"속성을 찾아 삭제하십시오. "Cascade"를 사용 가능하게 설정하면 관련 클래스와 관계가있는 다른 엔티티에 대해 다른 작업 (저장, 업데이트 및 삭제)을 호출합니다. 따라서 동일한 ID 값이 발생합니다. 저와 함께 일했습니다.


며칠 동안이 오류가 발생 했으며이 오류를 수정하는 데 너무 많은 시간을 보냈습니다.

 public boolean save(OrderHeader header) {
    Session session = sessionFactory.openSession();


    Transaction transaction = session.beginTransaction();

    try {
        session.save(header);

        for (OrderDetail detail : header.getDetails()) {
            session.save(detail);
        }

        transaction.commit();
        session.close();

        return true;
    } catch (HibernateException exception) {

        exception.printStackTrace();
        transaction.rollback();
        return false;
    }
}

Before i get this error , I didn't have mentioned ID generation type on the OrderDetil Object. when without generating Orderdetails' id it keeps Id as 0 for every OrderDetail objects. this what #jbx explained. Yes it is the best answer. this one example how it happens.


Try to place the code of your query before. That fix my problem. e.g. change this:

query1 
query2 - get the error 
update

to this:

query2
query1
update

you might not be setting the identifier of the object before calling update query.


I met the problem because of the primary key generation is wrong,when I insert a row like this:

public void addTerminal(String typeOfDevice,Map<Byte,Integer> map) {
        // TODO Auto-generated method stub
        try {
            Set<Byte> keySet = map.keySet();
            for (Byte byte1 : keySet) {
                Device device=new Device();
                device.setNumDevice(DeviceCount.map.get(byte1));
                device.setTimestamp(System.currentTimeMillis());
                device.setTypeDevice(byte1);
                this.getHibernateTemplate().save(device);
            }
            System.out.println("hah");
        }catch (Exception e) {
            // TODO: handle exception
            logger.warn("wrong");
            logger.warn(e.getStackTrace()+e.getMessage());
        }
}

I change the id generator class to identity

<id name="id" type="int">
    <column name="id" />
    <generator class="identity"  />
 </id>

In my case only flush() did not work. I had to use a clear() after flush().

public Object merge(final Object detachedInstance)
    {
        this.getHibernateTemplate().flush();
        this.getHibernateTemplate().clear();
        try
        {
            this.getHibernateTemplate().evict(detachedInstance);
        }
}

if you use EntityRepository then use saveAndFlush instead of save


If left an expressions tab in my IDE open which was making a hibernate get call on the object causing this exception. I was trying to delete this same object. Also I had a breakpoint on the delete call which seems to be necessary to get this error to happen. Simply making another expressions tab to be the front tab or changing the setting so that the ide does not stop on breakpoints solved this problem.

참고URL : https://stackoverflow.com/questions/16246675/hibernate-error-a-different-object-with-the-same-identifier-value-was-already-a

반응형