代码之家  ›  专栏  ›  技术社区  ›  Shervin Asgari

双向onetomany和manytoone在保存时返回“列不允许为空”

  •  1
  • Shervin Asgari  · 技术社区  · 6 年前

    这是实体的简短版本,我只显示相关部分。

        @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);
    

    我在原木上看到三个插页。 首先是包装器,然后是应用程序,最后是应用程序。但由于某些原因,第一次保存时应用程序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后再存储该应用程序? 不能一次存储所有三个文件吗?还是自己想出来?

    2 回复  |  直到 6 年前
        1
  •  0
  •   Thomas Mwania    6 年前

    试试这个:

    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);
    
        2
  •  0
  •   Shervin Asgari    5 年前

    对不起,我修好了。

    问题是

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

    我删除了insertable=false,updateable=false,并添加了optional=false

    有效的

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