我对持久继承的实体有一个奇怪的自动生成 id 行为。我有一个带有序列生成器的人员实体,它以 4 递增,并且工作正常。我有另外两个实体 Client 和 Agent,它们继承 Person 并将人员 ID 用作 pk。我有一个包含 3 个连接实体的策略实体:2 个客户端和代理。当我坚持策略[entity manager]persist(policy)它调用
select nextval('sk_db.person_id_sequence')
对于第一个客户端,并按照假设增加 id,但是在持久化其他 2 个实体时:客户端和代理,它只调用:
select lastval()
并按预期增加 1 而不是 4。我无法理解这种行为。我在这里错过了什么?
我使用: JPA EclipseLink和 Postgresql
@Entity
@Table(name = "Person", schema = Constraints.DB_SCHEMA)
public class TPerson implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@SequenceGenerator(name = "personIdGenerator", sequenceName = "person_id_sequence", initialValue = 6, allocationSize = 4)
@GeneratedValue(strategy = GenerationType.IDENTITY, generator = "personIdGenerator")
protected long id;
...
}
客户端和代理类:
@Entity
@Table(name = "Client", schema = Constraints.DB_SCHEMA)
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorValue(value = "Client")
public class TClient extends TPerson implements Serializable {
private static final long serialVersionUID = 1L;
...
}
具有联合关系的策略类:
@Entity
@Table(name = "Policy", schema = Constraints.DB_SCHEMA)
@DiscriminatorColumn(name = "classType")
public class TPolicy implements Serializable {
private static final long serialVersionUID = 1L;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "policyOwnerId", referencedColumnName = "id", updatable = false, insertable = false)
private TPerson policyOwner;
@OneToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.DETACH, CascadeType.REFRESH })
@JoinColumn(name = "agentId", referencedColumnName = "id", updatable = false, insertable = false)
private TAgent agent;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "transportOwnerId", referencedColumnName = "id", updatable = false, insertable = false)
private TPerson transportOwner;
我的架构:
CREATE SEQUENCE sk_db.person_id_sequence INCREMENT BY 4 START 2 CYCLE;
create table if not exists SK_DB.Person
(
id bigserial PRIMARY KEY,
..
);
create table if not exists SK_DB.Client
(
id bigserial REFERENCES SK_DB.Person(id),
..
)
create table if not exists SK_DB.Agent
(
id bigserial REFERENCES SK_DB.Person(id),
..
)
坚持政策后:
em.persist(policy);
我在日志中收到:
[EL Fine]: sql: ... --select nextval('sk_db.person_id_sequence')
..
[EL Fine]: sql: ....--select lastval()
[EL Fine]: sql: ....--INSERT INTO sk_db.Person (ID,....) VALUES (...)
bind => [48, ....]
[EL Fine]: sql: ....--select lastval()
[EL Fine]: sql: ....--INSERT INTO sk_db.Person (ID,....) VALUES (...)
bind => [49, ....]
[EL Fine]: sql: ....--select lastval()
[EL Fine]: sql: ....--INSERT INTO sk_db.Person (ID,....) VALUES (...)
bind => [47, ....]
但是自动生成的 id 应该是: 50, 54, 58。
在插入之前我看到的数据库序列中:
当前值:46 下一个值:50
插入后:
当前值:50 下一个值:54
在下一个持久化中,我收到以下 ID:52、51、50。
解决方案:
将 allocationSize 更改为 1 是固定的,当设置此参数表示缓存时,下一个值将增加多少次,直到它将从数据库中获取下一个值,在 javaee api 文档中,此参数表示递增,但它的工作方式不同不知道为什么。