Как обновить внутренний объект с помощью hibernate?

108
12 июня 2021, 19:00

У меня имеются два класса:

TimeTrackingDto

public class TimeTrackingDto {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @JsonIgnore
    private Integer id;
    @Column(name = "time_spent_minutes")
    private Integer timeSpentMinutes;
}

ProjectDto

public class ProjectDto {
    @Id
    @Column(name = "id")
    private Long id;
    @OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinColumn(name = "project_time_tracking")
    private TimeTrackingDto timeTracking;
}

Мне нужно обновить объект класса ProjectDto, но проблема в том, что в TimeTrackingDto я передаю id null:

TimeTrackingDto timeTracking = new TimeTracking(null, timeSpentMinutes);
ProjectDto project = new ProjectDto(id, timeTracking);
Session session = sessionFactory.getCurrentSession();
try {
  session.beginTransaction();
  session.saveOrUpdate(project);
  session.getTransaction().commit();
} catch (HibernateException e) {
  session.getTransaction().rollback();
}

Само собой когда hibernate видит, что id выставлен null, то он создает новую запись. Из-за этого когда я пытаюсь обновить ProjectDto, в базе данных каждый раз появляется новая запись TimeTrackingDto. Есть ли какой-нибудь механизм, который бы позволил обновлять внутренние объекты если у них id равен null?

Answer 1

Оптимальным решением будет создать запрос, который будет возвращать нужный объект ProjectDto (например по полю id, т.к. вы, видимо, получаете его значение заранее) и работать с ним.

В вашем случае, каждый раз, когда вы инициализируете оба объекта, hibernate думает, что это новые объекты. Т.к. вы вызываете saveOrUpdate, то он находит в таблице объектов ProjectDto, запись со значением id и перезаписывает и само значение и дочерние значения. В случае вызова метода save, скорее всего, он кинет ошибку, что запить с таким id уже есть.

P.S. Вы уверены, что у ваше TimeTrackingDto.id может быть null. Вы сделали его первичным ключом таблицы (@Id, что не дает ему быть null) и в добавок прописали генератор. Обычно использую конструкторы без id, потому что hibernate сам их создает.

P.P.S. Если вы, в конструкторе объекта TimeTracking, вместо null, укажете id существующей записи, то saveOrUpdate сработает успешно. Это дает вам возможность создавать новые записи объектов ProjectDto с уже существующими значениями записей объекта TimeTracking.

READ ALSO
Android обращение к ресурсам из адаптера

Android обращение к ресурсам из адаптера

Здравстуйте, уважаемые кодеры и программисты имеется следующий адаптер для ViewPager и Tablayout, и значения заголовков берутся из массива, но тк

87
JavaFX и векторные изображения

JavaFX и векторные изображения

Подскажите самый простой метод вывода векторного изображения (расширения SVG, допустим) в контейнер в JavaFX? Имеется ли аналог контейнера ImageView...

66
лямбда выражения в Java (часть 1) [закрыт]

лямбда выражения в Java (часть 1) [закрыт]

Хотите улучшить этот вопрос? Переформулируйте вопрос так, чтобы он был сосредоточен только на одной проблеме

85
Преобразование и приведение типов

Преобразование и приведение типов

Чем отличается преобразование типов от приведения типов? Относятся ли autoboxing/unboxing к преобразованию или приведению?

86