分离的实体传递给持久化,多对多 JPA

detached entity passed to persist, many to many JPA

您好,我正在尝试创建一个新请求,并且 link 它与 db 上的一个已经创建的人一起创建,但是我遇到了一个错误。

@Entity
@Table(name = "TG_REQUEST")
public class TgRequest {

    @Id
    @SequenceGenerator(name = "TG_REQUEST", sequenceName = "S_TG_REQUEST", allocationSize = 1)
    @GeneratedValue(generator = "TG_REQUEST")
    @Getter
    @Setter
    private Long idRequest;

  
    @OneToMany(mappedBy = "tgRequest", cascade = {CascadeType.PERSIST, CascadeType.MERGE}, orphanRemoval = true)
    @Getter
    @Setter
    private Set<TgRequestPerson> tgRequestPersons = new HashSet<>();


    public TgRequest() {

    }

    public void addTgRequestPerson(TgRequestPerson tgRequestPerson) {

        tgRequestPersons.add(tgRequestPerson);
        tgRequestPerson.setTgRequest(this);
    }

    public void removeTgRequestPerson(TgRequestPerson tgRequestPerson) {


        this.tgRequestPersons.remove(tgRequestPerson);
        tgRequestPerson.setTgRequest(null);
    }
}



@Entity
@Table(name = "TG_PERSON")
public class TgPerson {

    @Id
    @SequenceGenerator(name = "TG_PERSON", sequenceName = "S_TG_PERSON", allocationSize = 1)
    @GeneratedValue(generator = "TG_PERSON")
    @Getter
    @Setter
    private Long idPerson;

 
    @OneToMany(mappedBy = "tgPerson")
    @Getter
    @Setter
    private Set<TgRequestPerson> tgRequestPersons = new HashSet<>();

    public TgPerson() {

    }

    public void addTgRequestPerson(TgRequestPerson tgRequestPerson) {

        tgRequestPersons.add(tgRequestPerson);
        tgRequestPerson.setTgPerson(this);
    }

    public void removeTgRequestPerson(TgRequestPerson tgRequestPerson) {

        this.tgRequestPersons.remove(tgRequestPerson);
        tgRequestPerson.setTgPerson(null);
    }


}



@Entity
@Table(name = "TG_REQUEST_PERSON")
public class TgRequestPerson {


    @EmbeddedId
    @Getter
    @Setter
    private TgRequestPersonKey idRequestPerson;

    @ManyToOne(fetch = FetchType.LAZY)
    @MapsId("idRequest")
    @JoinColumn(name = "ID_REQUEST")
    @Getter
    @Setter
    private TgRequest tgRequest;

    @ManyToOne(fetch = FetchType.LAZY)
    @MapsId("idPerson")
    @JoinColumn(name = "ID_PERSON")
    @Getter
    @Setter
    private TgPerson tgPerson;


    public TgRequestPerson() {

    }

}



@Embeddable
public class TgRequestPersonKey implements Serializable {

    @Column(name = "ID_REQUEST")
    private Long idRequest;

    @Column(name = "ID_PERSON")
    private Long idPerson;

    public TgRequestPersonKey() {

    }

    public Long getIdRequest() {
        return idRequest;
    }

    public void setIdRequest(Long idRequest) {
        this.idRequest = idRequest;
    }

    public Long getIdPerson() {
        return idPerson;
    }

    public void setIdPerson(Long idPerson) {
        this.idPerson = idPerson;
    }
}

要保存的代码(新请求 link 到 db 上的现有人员):

TgRequest tgRequest = new TgRequest();

Long idPerson = 1; //Person already exists on db, with id = 1

TgPerson tgPerson = new TgPerson();
tgPerson.setIdPerson(idPerson)

TgRequestPerson tgRequestPerson = new TgRequestPerson();
TgRequestPersonKey tgRequestPersonKey = new TgRequestPersonKey();
tgRequestPersonKey.setIdRequest(tgRequest.getIdRequest());
tgRequestPersonKey.setIdPerson(idPerson);
tgRequest.addTgRequestPerson(tgRequestPerson);
tgPerson.addTgRequestPerson(tgRequestPerson);
tgRequestPerson.setIdRequestPerson(tgRequestPersonKey);


requestRepository.save(tgRequest);

我在看什么

插入tgRequest; --> 生成一个新的 id

插入 tgRequestPerson(idRequest = 新创建,idPerson = 1) (link 数据库上已经有人的新创建请求)

失败了。

错误

org.hibernate.PersistentObjectException: detached entity passed to persist: TgPerson

要更新的代码(link 一个创建的请求和一个创建的人)

TgRequest tgRequest = requestRepository.findByIdRequest(1); //Request already exists
Long idPerson = 1; //Person already exists on db, with id = 1,

TgPerson tgPerson = new TgPerson();
tgPerson.setIdPerson(idPerson)

TgRequestPerson tgRequestPerson = new TgRequestPerson();
TgRequestPersonKey tgRequestPersonKey = new TgRequestPersonKey();
tgRequestPersonKey.setIdRequest(tgRequest.getIdRequest());
tgRequestPersonKey.setIdPerson(idPerson);
tgRequest.addTgRequestPerson(tgRequestPerson);
tgPerson.addTgRequestPerson(tgRequestPerson);
tgRequestPerson.setIdRequestPerson(tgRequestPersonKey);


requestRepository.save(tgRequest);

期待中

插入 tgRequestPerson(idRequest = 1,idPerson = 1)有效!

那么,我怎样才能使保存代码生效?

错误发生是因为设置了对象的(tgPerson)ID。 Hibernate 区分瞬态对象和分离对象,save 仅适用于瞬态对象。如果 save 断定对象已分离(因为设置了 ID,它会分离),它将 return 出现“已分离的对象传递给持久化”错误。您可以找到更多详细信息 here and here.

但是,这仅适用于您已指定要自动生成主键的情况:如果该字段配置为始终手动设置,则您的代码有效。

所以你需要删除那些注释

@SequenceGenerator(name = "TG_PERSON", sequenceName = "S_TG_PERSON", allocationSize = 1)
@GeneratedValue(generator = "TG_PERSON")

或者调用saveOrUpdate方法

您将不得不使用 getOne,它在幕后使用 entityManager.getReference 来引用现有对象。

TgRequest tgRequest = requestRepository.findByIdRequest(1); //Request already exists
Long idPerson = 1; //Person already exists on db, with id = 1,

TgPerson tgPerson = personRepository.getOne(idPerson);

TgRequestPerson tgRequestPerson = new TgRequestPerson();
TgRequestPersonKey tgRequestPersonKey = new TgRequestPersonKey();
tgRequestPersonKey.setIdRequest(tgRequest.getIdRequest());
tgRequestPersonKey.setIdPerson(idPerson);
tgRequest.addTgRequestPerson(tgRequestPerson);
tgPerson.addTgRequestPerson(tgRequestPerson);
tgRequestPerson.setIdRequestPerson(tgRequestPersonKey);


requestRepository.save(tgRequest);