Сохранение объекта с отношениями «один ко многим» с помощью spring-data-jdbc возвращает пустой список

У меня проблема с возвращаемым значением после сохранения элемента (ArticleList) с отношениями «один ко многим» (ArticleListEntry) в Spring Data JDBC. При создании объекта в первый раз после вызова repository.save(entity) моя возвращаемая сущность, включая все связанные элементы, правильно сохраняется в базе данных. Однако возвращаемое значение содержит пустой список для entries. Поля оригинального ArticleList всегда заполняются правильно.

У меня есть следующие сущности:

@Table("article_list_meta")
@Data
public class ArticleList {
    @Id
    private final Long id;
    @Version
    private long version;
    @MappedCollection(idColumn = "list_id", keyColumn = "seq")
    private List<ArticleListEntry> entries = new ArrayList<>();  
    
    @PersistenceConstructor
    public ArticleList(Long id, String publication, String name) {
        this.id = id;
        this.publication = publication;
        this.name = name;
    }
    public ArticleList(String publication, String name) {
        this(null, publication, name);
    }
    // other fields
}

а также

@Data
@Table("article_list_entry")
public class ArticleListEntry {

    @Column("article_id")
    private final long articleId;

}

С репозиторием

@Repository
public interface ArticleListRepository extends CrudRepository<ArticleList, Long> {}

Я настаиваю на этом, используя

        ArticleList entity = repository.findByPublicationAndName(publication, name)
                .orElseGet(() -> new ArticleList(publication, name));
        entity = mapper.fromDto(entity, list, fieldsToUpdate);
        ArticleList persistedEntity = repository.save(entity);

После первоначального (version == 0) сохранения все последующие обновления включают все связанные элементы. Обратите внимание, что AbstractRelationalEventListener<ArticleList> получает тот же объект-с-пустым-списком для первого вызова save(articleList) (persistedEntity). entity все еще содержит статьи.

Это наводит меня на мысль, что я наткнулся на ошибку, но поскольку это наш первый проект, в котором используется data-jdbc вместо data-jpa, в моих сущностях также может быть что-то не так.

Я использую Spring Boot 2.3.6.RELEASE с версией 2.0.5.RELEASE из spring-data-jdbc.


person P. Harkink    schedule 01.12.2020    source источник
comment
У вас есть сеттеры для полей? Решает ли проблему закрытие пакета полей (без модификатора)? Как вы устанавливаете идентификатор или ожидаете, что Spring Data JDBC установит его?   -  person Jens Schauder    schedule 02.12.2020
comment
Я вижу, что я слишком очистил свой опубликованный код, в коллекции есть аннотация @AccessType(AccessType.Type.FIELD), потому что я отключил для них геттеры / сеттеры, чтобы защитить тип данных ArticleListEntry за пределами агрегата. Они правильно заполняются при доступе через метод findBy через средство доступа к полю, но, видимо, для сохранения это не так. Добавление общедоступных сеттеров и установка для параметра accessType значения Type.PROPERTY дает тот же результат - метод find вызывает их, а save - нет. Изменение поля на защищенный пакет также ничего не меняет.   -  person P. Harkink    schedule 02.12.2020
comment
Фактически, при установке точки останова в BasicJdbcConverter#populateProperties я заметил, что она срабатывает при выполнении обновления, но не при выполнении вставки. Копнув немного глубже, я заметил, что это происходит только потому, что я делаю findBy перед save, так что разница не во вставке / обновлении как таковой.   -  person P. Harkink    schedule 02.12.2020
comment
Спасибо за ответы. Однако вы не ответили на этот вопрос: как вы устанавливаете идентификатор или ожидаете, что Spring Data JDBC установит его?   -  person Jens Schauder    schedule 02.12.2020
comment
Извините, я пропустил этот вопрос. У меня @PersistenceConstructor public ArticleList(Long id, String publication, String name) , я обновлю код в своем вопросе   -  person P. Harkink    schedule 02.12.2020
comment
Это действительно похоже на ошибку. Не могли бы вы создать выпуск в комплекте с репродуктором? jira.spring.io/projects/DATAJDBC   -  person Jens Schauder    schedule 15.12.2020
comment
Связанная проблема: jira.spring.io/browse/DATAJDBC-647   -  person Jens Schauder    schedule 21.12.2020


Ответы (1)


Это результат того, что entries не является частью конструктора постоянства.

Когда конструктор используется для создания копии экземпляра (например, потому что необходимо установить идентификатор), копируются только свойства, включенные в этот конструктор.

Итак, чтобы решить проблему, вы должны изменить конструктор ArticleList, чтобы он выглядел так:

@PersistenceConstructor
public ArticleList(Long id, String publication, String name, List<ArticleListEntry> entries) {
    this.id = id;
    this.publication = publication;
    this.name = name;
    this.entries = entries;
}
person Jens Schauder    schedule 21.12.2020