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

이 기본 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 할당을 제거하면 문제가 해결되었습니다.

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



답변

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

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


답변

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

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


답변

풀다

user.setId(1);

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


답변

나는 대답을 얻었다.

em.persist(user);

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

em.merge(user);

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


답변

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

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


답변

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

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

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

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


답변

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