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 确实阻止了第二个查询。
我有以下实体:
@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 确实阻止了第二个查询。