JPA / EJB 코드와 함께 "오류를 지속하기 위해 전달 된 분리 된 엔티티"


81

이 기본 JPA / EJB 코드를 실행하려고합니다.

public static void main(String[] args){
         UserBean user = new UserBean();
         user.setId(1);
         user.setUserName("name1");
         user.setPassword("passwd1");
         em.persist(user);
  }

이 오류가 발생합니다.

javax.ejb.EJBException: javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: com.JPA.Database

어떤 아이디어?

인터넷에서 검색했는데 찾은 이유는 다음과 같습니다.

이것은 객체를 생성 한 방법, 즉 ID 속성을 명시 적으로 설정 한 경우에 발생합니다. ID 할당을 제거하면 문제가 해결되었습니다.

하지만 이해하지 못했습니다. 코드를 작동하려면 무엇을 수정해야합니까?

답변:


50

ERD

두 개의 엔티티 AlbumPhoto. 앨범에는 많은 사진이 포함되어 있으므로 일대 다 관계입니다.

앨범 클래스

@Entity
public class Album {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    Integer albumId;

    String albumName;

    @OneToMany(targetEntity=Photo.class,mappedBy="album",cascade={CascadeType.ALL},orphanRemoval=true)
    Set<Photo> photos = new HashSet<Photo>();
}

포토 클래스

@Entity
public class Photo{
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    Integer photo_id;

    String photoName;

    @ManyToOne(targetEntity=Album.class)
    @JoinColumn(name="album_id")
    Album album;

}

지속 또는 병합하기 전에해야 할 일은 각 사진에서 앨범 참조를 설정하는 것입니다.

        Album myAlbum = new Album();
        Photo photo1 = new Photo();
        Photo photo2 = new Photo();

        photo1.setAlbum(myAlbum);
        photo2.setAlbum(myAlbum);       

이것이 지속 또는 병합하기 전에 관련 엔터티를 연결하는 방법입니다.


2
제네릭을 사용하는 경우 "targetEntity = Photo.class"를 사용할 필요가 없습니다.
Rollerball

안녕하세요, 앨범 개체를 photo1 nad photo2로 설정 한 후 ... 사진 또는 앨범 목록을 저장해야하는 개체는 무엇입니까?
Dilanka Rathnayake

130

개체의 ID가 설정 되었기 때문에 오류가 발생합니다. Hibernate는 일시적인 개체와 분리 된 개체를 구분하며 일시적인 개체 persist에서만 작동합니다. 경우 persist(그것이 ID가 설정되어 있기 때문에하는) 객체가 분리 결론, 그것은 오류를 "분리 된 객체가 계속 전달"돌아갑니다. 여기여기에서 자세한 내용을 확인할 수 있습니다 .

그러나 이는 자동 생성 할 기본 키를 지정한 경우 에만 적용됩니다 . 필드가 항상 수동으로 설정되도록 구성되어 있으면 코드가 작동합니다.


내가 Hibernate가 아닌 JPA를 사용하고 있으므로 위의 설명이 올바르게 적용되지 않아야한다고 말할 때 기술적으로 옳습니까? 나는 JPA의 초보자입니다 (정확히 3
ays

Sun의 JPA Javadoc ( java.sun.com/javaee/5/docs/api/javax/persistence/… )과 Toplink 의 JPA 는 정확히 동일하며 기술적으로 옳다고 제안합니다. 그러나 이것은 사양이 persist ()가 어떻게 작동해야한다고 말하는지로 귀결되며 슬프게도 그게 뭔지 모르겠습니다.
Tomislav Nakic-Alfirevic

이 솔루션은 저에게 효과적이었습니다. 나는 객체를 유지하고 ID를 어딘가에 저장했습니다. 그런 다음 기존 개체를 새 값으로 덮어 쓰고 싶기 때문에 개체를 만들고 ID를 다시 복사 한 다음 저장하려고 할 때 폭발했습니다. 결국 DB (findById)를 다시 쿼리하고 변경 한 다음 해당 개체 를 유지 해야했습니다 .
cs94njw

24

풀다

user.setId(1);

DB에서 자동 생성되므로 persist 명령을 계속하십시오.


12

나는 대답을 얻었다.

em.persist(user);

지속 대신 병합을 사용했습니다.

em.merge(user);

그러나 왜 지속이 작동하지 않았는지 모르겠습니다. :(


11
이것은 해결책이 아닙니다!
Ammar Bozorgvar 2011

1
알아,하지만 이것은 나를 위해 일했다. 여기에 당신에게 도움이 된 다른 대답이 있습니까? 그렇다면 나는 그것을 선택하는 것보다 기꺼이 할 것입니다.
zengr 2011

4
개체가 최대 절전 세션에서 분리되었거나 개체가 일시적이지만 최대 절전 모드에서 기본 키를 선언했기 때문에 분리 된 것으로 간주되기 때문에 작동했습니다. 병합을 사용하면 개체를 세션에 다시 연결하여 데이터베이스의 개체를 업데이트 할 수 있습니다. ; 참조 : docs.jboss.org/hibernate/core/3.3/reference/en/html/…
Ben

10

id = GenerationType.AUTO엔티티 에서 전략 을 생성하는 데 사용하는 경우 .

로 대체 user.setId (1)되고 user.setId (null)문제가 해결됩니다.


5

나는 그것이 너무 늦었다는 것을 알고 있으며 모든 사람들이 답을 얻었습니다. 그러나 이것에 조금 더 추가해야합니다. GenerateType이 설정되면 객체의 persist ()가 생성 된 ID를 얻을 것으로 예상됩니다.

이미 사용자가 Id로 설정 한 값이있는 경우 hibernate는이를 저장된 레코드로 취급하여 분리 된 것으로 취급합니다.

id가 null 인 경우-이 상황에서 id가 테이블 또는 sequece 등에서 생성되지 않는 한 유형이 AUTO 또는 IDENTITY 등이면 null 포인터 예외가 발생합니다.

디자인 : 이것은 테이블이 기본 키로 빈 속성을 가질 때 발생합니다. GenerateType은 ID가 자동 생성되는 경우에만 설정해야합니다. 이것을 제거하고 삽입은 사용자가 지정한 ID로 작동해야합니다. (속성을 기본 키 필드에 매핑하는 것은 잘못된 설계입니다)


5

여기서 .persist ()레코드 를 삽입합니다. .merge ()를 사용 하면 현재 ID를 가진 레코드가 있는지 확인하고, 존재하는 경우 업데이트하지 않으면 새 레코드를 삽입합니다.


답변을받을 때까지 많은 시간이 소요되었습니다. 대단히 감사합니다!
Thach Van

3

데이터베이스의 id를 기본 키 및 자동 증가로 설정하면 다음 코드 줄이 잘못되었습니다.

user.setId(1);

이것을 시도하십시오 :

public static void main(String[] args){
         UserBean user = new UserBean();
         user.setUserName("name1");
         user.setPassword("passwd1");
         em.persist(user);
  }

나는 그것을 시도하고 나는이 오류가 발생하는 것을 알고 있습니다 :detached entity passed to persist
s1ddok

2

이 문제가 있었고 두 번째 수준 캐시로 인해 발생했습니다.

  1. 최대 절전 모드를 사용하여 엔티티를 유지했습니다.
  2. 그런 다음 두 번째 수준 캐시와 상호 작용하지 않는 별도의 프로세스에서 생성 된 행을 삭제했습니다.
  3. 동일한 식별자로 다른 엔터티를 유지했습니다 (내 식별자 값이 자동 생성되지 않음).

따라서 캐시가 무효화되지 않았기 때문에 hibernate는 동일한 엔티티의 분리 된 인스턴스를 처리한다고 가정했습니다.

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