Cascade ALL 未按预期工作

Cascade ALL doesn't work as expected

我有以下实体:

@Entity
@Table(name = "BOOKS")
public class Book {

   @Id
   @GeneratedValue(generator = "SEQUENCE_UID", strategy = GenerationType.SEQUENCE)
   private Long id;

   @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
   @JoinColumn(name = "BOOK_ID")
   private List<Page> pages = new ArrayList<>(); 
   ...
   ...

   public List<Page> getPages() {
     return Collections.unmodifiableList(pages);
   }

   public void add(Page page){
      this.pages.add(page);
   }
}

@Entity
@Table(name = "PAGES")
public class Page {

   @Id
   @GeneratedValue(generator = "SEQUENCE_UID", strategy = GenerationType.SEQUENCE)
   private Long id;

   @Column(name = "COLOR", nullable = false)
   private String color;

   ...
   ...
}

如您所见,我在页面列表中使用了 CascadeType.ALL,事实上,当我尝试创建一本新书时,我可以看到以下查询:

INSERT INTO PAGES (ID, COLOR) VALUES (?,?)

但后来我得到了这个例外:

Internal Exception: org.postgresql.util.PSQLException: ERROR: null value in column "book_id" violates not-null constraint

我正在使用 EclipseLink 和 Spring-Data,这就是我创建新书的方式:

Page page = new Page();
page.setColor("RED");
Book book = new Book();
book.add(page);
bookRepository.save(book);

我在这里错过了什么?

问题是 类 不会自动生成它们的 ID,所以你会看到错误

ERROR: null value in column "book_id" violates not-null constraint

JPA 实体对象不需要空 id 持续存在。您可以手动设置:

Book book = new Book();
book.setId(1L);
bookRepository.save(book);

但是使用生成的价值策略更容易:

 @Entity 
 @Table(name = "BOOKS")
 public class Book {

   @Id
   @GeneratedValue(strategy = GenerationType.SEQUENCE, generator="BOOK_SEQ")
   @SequenceGenerator(name="BOOK_SEQ", initialValue=1, allocationSize=1, sequenceName="BOOK_SEQ")
   private Long id;

   ...
   ...
 }

 @Entity 
 @Table(name = "PAGES")
 public class Page {

   @Id
   @GeneratedValue(strategy = GenerationType.SEQUENCE, generator="PAGE_SEQ")
   @SequenceGenerator(name="PAGE_SEQ", initialValue=1, allocationSize=1, sequenceName="PAGE_SEQ")
   private Long id;
   ...
   ...
 }

此外,您需要在数据库上创建 BOOK_SEQ 和 PAGE_SEQ,根据数据库的不同,sql 脚本可以更改,并非所有数据库都有序列, mysql例如不支持sequence

如果你使用 postgresql 例如你可以执行代码:

create sequence BOOK_SEQ start with 1 increment by 1 maxvalue 10000 minvalue 1 cycle; create sequence PAGE_SEQ start with 1 increment by 1 maxvalue 10000 minvalue 1 cycle;

找到 this 答案 - 实际上似乎有两个查询,所以 not-null 确实阻止了第二个查询。