Двунаправленные OneToMany и ManyToOne возвращают «NULL не разрешено для столбца» при сохранении - PullRequest
0 голосов
/ 01 февраля 2019

Это сокращенная версия сущностей, в которой я показываю только соответствующие части.

    @Entity
    @Data
    public class Wrapper {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Integer id

        @OneToOne(mappedBy = "wrapper", cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
        private Application application;

        public Wrapper(Application application) {
            this.application = application;
            application.setWrapper(this);
        }
    }

    @Data
    @Entity
    @EqualsAndHashCode(exclude = "wrapper")
    public class Application {
        @Id
        private Integer id;

        @JsonIgnore
        @OneToOne
        @JoinColumn(name = "id")
        @MapsId
        private Wrapper wrapper;

        @OneToMany(mappedBy = "application", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER)
        @SortNatural
        private SortedSet<Apartement> ownedApartements = new TreeSet<>();
    }

    @Entity
    @Data
    public class Apartement {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Integer id;

        @ManyToOne(fetch = FetchType.LAZY, optional = false)
        @JoinColumn(name = "application_id", insertable = false, updatable = false)
        private Application application;
    }

@Repository
public interface WrapperRepository extends JpaRepository<Wrapper, Integer> {
}   

Приведенные выше сущности генерируют следующие операторы создания таблицы:

create table Wrapper (
       id int identity not null,
        primary key (id)
    )

create table Application (
       id int not null,
        primary key (id)
    )

    create table Apartement (
       id int identity not null,
        application_id int not null,
        primary key (id)
    )

     alter table Apartement 
       add constraint FKsrweh1i1p29mdjfp03or318od 
       foreign key (application_id) 
       references Application

       alter table Application
       add constraint FKgn7j3pircupa2rbqn8yte6kyc 
       foreign key (id) 
       references Wrapper

Учитывая следующеелица и следующий код:

Apartement apartement1 = new Apartement()
Apartement apartement2 = new Apartement()

Wrapper wrapper = new Wrapper(new Application());

Application application = wrapper.getApplication();
application.getOwnedApartements().addAll(Arrays.asList(apartement1, apartement2));
apartement1.setApplication(application);
apartement2.setApplication(application);

WrapperRepository.saveAndFlush(wrapper);

Я вижу три вставки в журнале.Сначала обертка, затем приложение и, наконец, квартира.Но по какой-то причине application_id является нулевым при первом сохранении.Но я знаю, что у него двунаправленные отношения.

Я получаю ошибку:

Caused by: org.h2.jdbc.JdbcSQLException: NULL not allowed for column "APPLICATION_ID"; SQL statement:
insert into Apartement (id) values (null) [23502-197]

Почему это происходит?Нужно ли хранить все в правильном порядке?Нужно ли мне сначала сохранять упаковку и приложение, а затем, наконец, сохранить квартиру, как только у меня будет идентификатор приложения?Не можете хранить в спящем режиме все три за один раз?Или понять это самостоятельно?

Ответы [ 2 ]

0 голосов
/ 01 февраля 2019

Попробуйте это:

Apartement apartement1 = new Apartement()
Apartement apartement2 = new Apartement()

Wrapper wrapper = new Wrapper(new Application());

Application application = wrapper.getApplication();
application.getOwnedApartements().addAll(Arrays.asList(apartement1, apartement2));
apartement1.setApplicationId(application.getId());
apartement2.setApplicationId(application.getId());

WrapperRepository.saveAndFlush(wrapper);
0 голосов
/ 01 февраля 2019

Извините, я исправил это.

Проблема была

@ManyToOne(fetch = FetchType.LAZY, optional = false)
        @JoinColumn(name = "application_id", insertable = false, updatable = false)
        private Application application;

Я удалил вставляемый = false, обновляемый = false и добавил необязательный = false

Это сработало

@JoinColumn(name = "application_id", = false)
...