Подтвердить что ты не робот

Спящий режим пытается сохранить тот же объект дважды

У меня есть 3 класса, соответствующие 3 таблицам V, D и P. D имел FK до V (FK_V) и соединяется с использованием отношения OneToMany. Также их выходы 4-й таблицы V_D_P, которая имеет отношение этих V, D и P.

Ниже приведена модель данных для них:

@Entity
@Table(name = "V")                                                   
public class V {

     @Id
     @GeneratedValue(strategy = GenerationType.SEQUENCE)
     @Column(name = "ID")
     private Long id;

    @OneToMany(cascade=CascadeType.ALL)
    @JoinColumn(name = "FK_V", referencedColumnName="Id", nullable = false)
    private Set<D> d;

    @OneToMany(cascade=CascadeType.ALL)
    @JoinColumn(name = "FK_V", referencedColumnName="Id", nullable = false)
    private Set<V_D_P> vdp;

    //Getters Setters etc.
}


@Entity
@Table(name = "V_D_P")
public class V_D_P {

      @Id
      @GeneratedValue(strategy = GenerationType.SEQUENCE)
      @Column(name = "ID")
      private Long id;

     @ManyToOne(cascade=CascadeType.ALL)
     @JoinColumn(name = "FK_D", nullable = false)
     private D d;

     @ManyToOne(cascade=CascadeType.ALL)
     @JoinColumn(name = "FK_P", nullable = false)
     private P p;

     //Getters Setters etc.       
}

@Entity
@Table(name = "D")                                                   
public class D {
      @Id
      @GeneratedValue(strategy = GenerationType.SEQUENCE)
      @Column(name = "ID")
      private Long id;

    //Getters Setters etc.
}

@Entity
@Table(name = "P")                                                  
public class P {

      @Id
      @GeneratedValue(strategy = GenerationType.SEQUENCE)
      @Column(name = "ID")
      private Long id;

    //Getters Setters etc.
}

Теперь я хочу сохранить V, D и P вместе со своими отношениями. Я

V v = new V();

D d = new D();
Set<D> dSet = new HashSet<>();
dSet.add(d);
v.setD(dSet); // Adding d to V ....(1)

P p = new P();
V_D_P vdp = new V_D_P();

vdp.setD(d); // Adding d to V_D_P ....(2)
vdp.setP(p);

Set<V_D_P> vdpSet = new HashSet<V_D_P>();
vdpSet.add(vdp);
v.setVdp(vdpSet);

entityManager.persist(v);

Теперь вы можете увидеть, что я добавляю один и тот же объект D дважды. Один раз на P и один раз на V_D_P. Однако, поскольку это те же объекты, только один из них должен сохраняться. Однако, основываясь на журналах спящего режима, я вижу, что спящий режим пытается вставить два разных объекта.

Я также вижу следующее исключение: ORA-00001: уникальное ограничение

Есть ли способ позволить спящему, что это одни и те же объекты и персидровать их только один раз?

4b9b3361

Ответ 1

Объекты уникально идентифицируются идентификатором. Поэтому они должны иметь одинаковый идентификатор.

  • Либо укажите id раньше,
  • или сохраняйте один раз и обновляйте объект d перед сохранением другого (поэтому он имеет набор идентификаторов).

Ответ 2

Попробуйте save() вместо persist(). Как отмечено в этом сообщении, persist не обязательно обновляет идентификатор объекта немедленно. Это означает, что спящий режим может дважды встретить ваш объект "d", когда он пересекает граф объектов. Оба раза он мог бы сказать: "id имеет значение null, мне нужно вставить новый!".

По-видимому, это поведение плохо определено, поэтому во всех случаях это может не произойти.

Ответ 3

Вам действительно нужно поле VDP.d: не можете ли вы просто использовать двунаправленное (отображаемое) отношение между V и V (D) P (V (D) P будет иметь av-поле) и просто перемещаться по V (D) Pvd?