在 JPA 中为链接 Table 的多对多实体自动生成 ID
Auto-Generating ID For Many-To-Many Entities for Linking Table in JPA
我的问题是,当我在多对多关系中插入实体时,无法在链接中自动生成 ID table。
我在实体 Foo 和 Bar 之间存在双向多对多关系。名为 FOO_BAR 的链接 table 具有 FOO_BAR_ID、FOO_ID 和 BAR_ID,第一个是 table 上的 PK。它链接 FOO 和 BAR table,它们也有自己的 PK,FOO_ID 和 BAR_ID。这两个扩展自一个公共基础 class,该基础具有带有序列生成器的 @Id。
public abstract class ParentEntity {
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "generator")
@SequenceGenerator(name = "generator", sequenceName = "some_sequence")
protected Long id;
//...getters/setters
}
实体 Foo 在 FOO table 中,其 PK 名为 FOO_ID。
@Entity
@Table(name = "FOO")
@AttributeOverride(name = "id", column = @Column(name = "FOO_ID"))
public class Foo extends ParentEntity {
@Column(name = "name")
protected String name;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "FOO_BAR",
joinColumns = @JoinColumn(name = "FOO_ID"),
inverseJoinColumns = @JoinColumn(name = "BAR_ID"))
protected Set<Bar> bars;
//...getters/setters
}
此实体 Bar 是 BAR table,其 PK 为 BAR_ID。
@Entity
@Table(name = "BAR")
@AttributeOverride(name = "id", column = @Column(name = "BAR_ID"))
public class Bar extends ParentEntity {
@Column(name = "name")
protected String name;
@ManyToMany(mappedBy = "bars", cascade=CascadeType.ALL)
protected Set<Foo> foos;
//...getters/setters
}
链接 table 有 FOO_ID、BAR_ID,它自己的 PK 称为 FOO_BAR_ID。
问题是,当我尝试插入新的 Foo 时,没有为 FOO_BAR 链接 table 中的 PK 插入 ID。其他两个 ID 看起来可以正常插入。
当我坚持使用以下内容时:
@Transactional
public void baz() {
Foo foo = new Foo();
Bar bar = entityManager.find(barId);
foo.setBars(new HashSet<Bar>());
foo.getBars().add(bar);
entityManager.persist(foo);
//also tried .merge just for giggles
}
On persist 是错误发生的地方。查看 SQL 日志,这是输出的内容:
DEBUG: org.hibernate.SQL - select some_sequence.nextval from dual
DEBUG: org.hibernate.SQL - insert into FOO (FOO_ID, NAME) values (?, ?)
DEBUG: org.hibernate.SQL - insert into FOO_BAR (FOO_ID, BAR_ID) values (?, ?)
WARN : org.hibernate.engine.jdbc.spi.SqlExceptionHelper - SQL Error: 1400, SQLState: 23000
ERROR: org.hibernate.engine.jdbc.spi.SqlExceptionHelper - ORA-01400: cannot insert NULL into ("MY_SCHEMA"."FOO_BAR"."FOO_BAR_ID")
根据 SQL 的执行,这是有道理的,但我不确定如何生成链接 table 的 PK。
我相信你们中的许多人都会理解,由于客户端限制,这只是必须的方式,但我不知道这是不可能的,还是我做错了什么。
您的两个主要选择是:
1) 更改连接 table 使其只有一个 FOO_ID
和一个 BAR_ID
并且主键是这两个字段的组合,
或
2) 如果希望连接 table 包含的不仅仅是 FOO_ID
和 BAR_ID
,则需要将连接 table 定义为单独的实体 class (FooBar
)。那么 Foo
和 Bar
都会与 FooBar
.
有一对多的关联
我的问题是,当我在多对多关系中插入实体时,无法在链接中自动生成 ID table。
我在实体 Foo 和 Bar 之间存在双向多对多关系。名为 FOO_BAR 的链接 table 具有 FOO_BAR_ID、FOO_ID 和 BAR_ID,第一个是 table 上的 PK。它链接 FOO 和 BAR table,它们也有自己的 PK,FOO_ID 和 BAR_ID。这两个扩展自一个公共基础 class,该基础具有带有序列生成器的 @Id。
public abstract class ParentEntity {
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "generator")
@SequenceGenerator(name = "generator", sequenceName = "some_sequence")
protected Long id;
//...getters/setters
}
实体 Foo 在 FOO table 中,其 PK 名为 FOO_ID。
@Entity
@Table(name = "FOO")
@AttributeOverride(name = "id", column = @Column(name = "FOO_ID"))
public class Foo extends ParentEntity {
@Column(name = "name")
protected String name;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "FOO_BAR",
joinColumns = @JoinColumn(name = "FOO_ID"),
inverseJoinColumns = @JoinColumn(name = "BAR_ID"))
protected Set<Bar> bars;
//...getters/setters
}
此实体 Bar 是 BAR table,其 PK 为 BAR_ID。
@Entity
@Table(name = "BAR")
@AttributeOverride(name = "id", column = @Column(name = "BAR_ID"))
public class Bar extends ParentEntity {
@Column(name = "name")
protected String name;
@ManyToMany(mappedBy = "bars", cascade=CascadeType.ALL)
protected Set<Foo> foos;
//...getters/setters
}
链接 table 有 FOO_ID、BAR_ID,它自己的 PK 称为 FOO_BAR_ID。
问题是,当我尝试插入新的 Foo 时,没有为 FOO_BAR 链接 table 中的 PK 插入 ID。其他两个 ID 看起来可以正常插入。
当我坚持使用以下内容时:
@Transactional
public void baz() {
Foo foo = new Foo();
Bar bar = entityManager.find(barId);
foo.setBars(new HashSet<Bar>());
foo.getBars().add(bar);
entityManager.persist(foo);
//also tried .merge just for giggles
}
On persist 是错误发生的地方。查看 SQL 日志,这是输出的内容:
DEBUG: org.hibernate.SQL - select some_sequence.nextval from dual
DEBUG: org.hibernate.SQL - insert into FOO (FOO_ID, NAME) values (?, ?)
DEBUG: org.hibernate.SQL - insert into FOO_BAR (FOO_ID, BAR_ID) values (?, ?)
WARN : org.hibernate.engine.jdbc.spi.SqlExceptionHelper - SQL Error: 1400, SQLState: 23000
ERROR: org.hibernate.engine.jdbc.spi.SqlExceptionHelper - ORA-01400: cannot insert NULL into ("MY_SCHEMA"."FOO_BAR"."FOO_BAR_ID")
根据 SQL 的执行,这是有道理的,但我不确定如何生成链接 table 的 PK。
我相信你们中的许多人都会理解,由于客户端限制,这只是必须的方式,但我不知道这是不可能的,还是我做错了什么。
您的两个主要选择是:
1) 更改连接 table 使其只有一个 FOO_ID
和一个 BAR_ID
并且主键是这两个字段的组合,
或
2) 如果希望连接 table 包含的不仅仅是 FOO_ID
和 BAR_ID
,则需要将连接 table 定义为单独的实体 class (FooBar
)。那么 Foo
和 Bar
都会与 FooBar
.