Гибернация: дважды сохраняет объект в таблицу при подключении к загруженному OneToMany

#hibernate #spring #jakarta-ee #mapping

#переход в спящий режим #spring #джакарта-ee #сопоставление

Вопрос:

класс rideSingle всегда сохраняется несколько раз в БД, если для отношения OneToMany установлено значение eagle:

Класс, который сохраняется

 @Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class RideSingle  extends HibernateBasicClass{
    @OneToMany(mappedBy = "rideSingle", fetch = FetchType.EAGER)
    @Cascade(CascadeType.ALL)
    protected List<TimedRouteLocation> route;
}
  

Указанный класс:

 @Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class TimedRouteLocation  extends HibernateBasicClass {

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(nullable = false)
    protected RideSingle rideSingle;
}
  

базовый класс hibernate

 @Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class HibernateBasicClass implements Serializable {
    private static final long serialVersionUID = -2253382207065396453L;

    @Id
    @SequenceGenerator(name = "generator", allocationSize = 1, initialValue = 1)
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "generator")
    @JsonProperty
    private Long id;

    @Column(nullable = false)
    @Temporal(TemporalType.TIMESTAMP)
    private Date createdOn = new Date();

    @Version
    private Date lastModified;

    public HibernateBasicClass() {
        super();
    }

    public Long getId() {
        return id;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        final HibernateBasicClass objWId = (HibernateBasicClass) obj;
        // same id instance
        if (getId() == objWId.getId())
            ;
        // same id content
        if (getId() != null) {
            return getId().equals(objWId.getId());
        } else {
            return false;
        }
    }

}
  

Существует только одна переменная, которая затем сохраняется с помощью

     int i = rideSingleDaox.findAll().size(); // i is 0
    rideSingleDao.saveOrUpdate(this);
    i = rideSingleDaox.findAll().size(); // i is 2
  

Dao выглядит следующим образом:

 public T saveOrUpdate(T object) {
    getSession().saveOrUpdate(object);
            return object;
}
  

Если rideSingle.route содержит 2 элемента -> rideSingle дважды помещается в базу данных. Если маршрут содержит 3 элемента, в базу данных помещаются 3 копии rideSingle…

Если rideSingle загружает маршрут с задержкой, эта проблема не возникает.

 @Entity
public class RideSingle {
    @OneToMany(mappedBy = "rideSingle", fetch = FetchType.EAGER)
    @Cascade(CascadeType.ALL)
    protected List<TimedRouteLocation> route;
}
  

Кто-нибудь знает, почему это так и как я мог бы это решить?

Большое спасибо!

Комментарии:

1. Пожалуйста, дополните ваши примеры @Id определениями и фрагментом кода, который приводит к сохранению нескольких записей.

2. В примере, где объект сохраняется дважды: home, много экземпляров RideSingle и TimedRouteLocation существует в конкретной организации и сколько всего?

3. @Mada Я добавил выдержки. Полезно ли это?

4. @Ralph В этой взаимосвязи существует один rideSingle и два временных маршрута. Нет другого отдельного параметра, кроме timedroutelocation (сбрасывается для теста)

Ответ №1:

У меня была такая же проблема при вызове списка после сохранения. Он вернул один и тот же объект более одного раза.

Я добавил

.setResultTransformer(Критерии.DISTINCT_ROOT_ENTITY)

чтобы решить эту проблему.

Код выглядит следующим образом:

 session.createCriteria(clazz)
.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
.list()
  

Ответ №2:

Это только предположение:

Попробуйте реализовать метод equals для обоих классов.

Комментарии:

1. @Steve Ты ведь помнил об этом, не так ли?

2. @MaDa: о чем ты говоришь?

3. @Ralph Это может быть хорошей идеей! У меня только что был метод equal (RideSingle rideSingle). Теперь я добавил его в HibernateBasicClass. Однако это не помогает решить проблему. У вас есть еще подсказка?

4. Похоже, что метод equal не вызывается hibernate (пробовал это в HibernateBasicClass, а также в RideSingle). При работе со списками эта функция работает просто отлично. Вы знаете, какую функцию hibernates использует при сохранении каскада?