Я хотел бы знать, если мне не хватает аннотации или конфигурации, или мне нужно реализовать эту функциональность самостоятельно, и если да, то как. Я спрашиваю, потому что существующий код предполагает, что это должно работать "из коробки".
Для справки: у меня есть старая база кода, которая недавно была обновлена с
- Spring Boot: с 2.1.3 по 3.3.1
- Спящий режим: с 5.4.1 по 6.5.2.Окончательная версия
У меня есть следующие упрощенные объекты:И страна рождения, и адреса имели аннотацию @LazyToOne(value = LazyToOneOption.NO_PROXY).Код: Выделить всё
@Data @Entity @Audited @EqualsAndHashCode(callSuper = true) @Table(name = "PERSON") // The listener listens for PrePersist and PreUpdate, but does not touch the problematic fields. @EntityListeners(PersonListener.class) public class Person { @Id @Column(name = "id", nullable = false, insertable = false, updatable = false) private Long id; @Column(name = "name", nullable = false) private String name; @ManyToOne(targetEntity = Country.class, fetch = FetchType.LAZY) @JoinColumn(name = "birth_country_id", referencedColumnName = "id", foreignKey = @ForeignKey(name = "fk_birth_country")) @RestResource(exported = false) private Country birthCountry; @ManyToMany(targetEntity = Address.class, cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH}, fetch = FetchType.LAZY) @JoinTable(name = "person_address", joinColumns = @JoinColumn(name = "person_id"), inverseJoinColumns = @JoinColumn(name = "address_id") ) private List addresses = new ArrayList(); // Other fields omitted for brevity. }Код: Выделить всё
@Data @Entity @Audited @Table(name = "COUNTRY") @EntityListeners(AuditingEntityListener.class) public class Country implements Serializable { @Id @Column(name = "id", nullable = false, length = 19) @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "name", nullable = false) private String name; }И для человека, и для страны у меня есть простой репозиторий отдыха, как показано ниже. Адрес не имеет репозитория.Код: Выделить всё
@Data @Entity @Audited @Table(name = "ADDRESS") @EqualsAndHashCode(callSuper = true) public class Address { @Id @Column(name = "id", nullable = false) @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @ManyToOne(targetEntity = Country.class, fetch = FetchType.LAZY, optional = false) @JoinColumn(name = "country_id", referencedColumnName = "id", nullable = false, foreignKey = @ForeignKey(name = "fk_country")) private Country country; @Column(name="street", nullable = false) private String street; }Например, у меня есть следующий человек:Код: Выделить всё
@RepositoryRestResource(collectionResourceRel = "person", path = "person") public interface PersonRepository extends JpaRepository { }Я получаю следующий json от клиента через PUT, когда пользователь выбирает новую страну и изменяет адрес. Вот какой я ожидал бы получить конечный результат:Код: Выделить всё
{ "id": 1, "name": "John Smith", "birthCountry": { "id": 10, "name": "United States" }, "addresses": [{ "id": 100, "country": { "id": 10, "name": "United States" }, "name": "Wall Street" }] }Код: Выделить всё
{ "id": 1, "name": "Oliver Smith", "birthCountry": { "id": 11, "name": "Canada" }, "addresses": [{ "id": 100, "country": { "id": 12, "name": "Mexico" }, "name": "Avenida Francisco I. Madero" }] }вызывается, но объединяются только изменения примитивных значений. Это конечный результат в базе данных:Код: Выделить всё
SimpleJpaRepository.saveВ журнале отладки sql я вижу, что оператор обновления, сгенерированный Hibernate, содержит id=10 вместо того, что я получил от клиента.Код: Выделить всё
{ "id": 1, "name": "Oliver Smith", "birthCountry": { "id": 10, "name": "United States" }, "addresses": [{ "id": 100, "country": { "id": 10, "name": "United States" }, "name": "Avenida Francisco I. Madero" }] }
Как ни странно, когда я отлаживаю метод SimpleJpaRepository.save в IntelliJ и смотрю на сущность Person в представлении отладчика, я вижу новые примитивные значения в связанных сущностях с id=null. Однако если я вычисляю выражение, запрашивающее то же самое, фрагмент кода возвращает старые значения.
Подробнее здесь: https://stackoverflow.com/questions/791 ... ed-on-save