级联ALL无法按预期工作

时间:2015-12-31 15:00:15

标签: java orm one-to-many cascade

我有以下实体:

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

我在这里缺少什么?

2 个答案:

答案 0 :(得分:1)

问题是两个类都没有自动生成id,所以你看到错误

  

错误:“book_id”列中的空值违反了非空约束

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不支持序列

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

  

创建序列BOOK_SEQ     从1开始     增加1     maxvalue 10000     最小值1     周期;    创建序列PAGE_SEQ     从1开始     增加1     maxvalue 10000     最小值1     周期;

答案 1 :(得分:0)

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