保存时双向 OneToMany 和 ManyToOne returns "NULL not allowed for column"
Bidirectional OneToMany and ManyToOne returns "NULL not allowed for column" on save
这是实体的简化版本,我只显示了相关部分。
@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 语句:
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]
为什么会这样?我需要以正确的顺序存储所有内容吗?我是否需要先存储包装器和应用程序,然后在获得应用程序 ID 后才最终存储公寓?
休眠不能一次存储所有三个吗?还是自己想办法?
抱歉,我修好了。
问题是
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "application_id", insertable = false, updatable = false)
private Application application;
我删除了 insertable = false、updatable = false 并添加了 optional=false
有效
@JoinColumn(name = "application_id", optional = false)
试试这个:
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);
这是实体的简化版本,我只显示了相关部分。
@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 语句:
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]
为什么会这样?我需要以正确的顺序存储所有内容吗?我是否需要先存储包装器和应用程序,然后在获得应用程序 ID 后才最终存储公寓? 休眠不能一次存储所有三个吗?还是自己想办法?
抱歉,我修好了。
问题是
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "application_id", insertable = false, updatable = false)
private Application application;
我删除了 insertable = false、updatable = false 并添加了 optional=false
有效
@JoinColumn(name = "application_id", optional = false)
试试这个:
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);