【发布时间】:2021-06-20 07:03:55
【问题描述】:
我有一个以 orgId 和 clientId 作为复合键的 Client 实体。当我必须插入一个新的客户端对象时,我必须为每个 orgId 依次生成 clientId id,为此,我通过在单独的表中维护每个 orgId 的最后一个 clientId 并选择、添加 1 和更新它。
@Entity
@Table(name = "ftb_client")
public class Client implements Serializable {
@Id
@JoinColumn(name = "ORG_ID")
protected String orgId;
@Id
@Column(name = "CLIENT_ID")
protected int clientId;
@Column(name = "CLIENT_NAME_ENG")
private String clientNameEng;
//....
}
@Entity
@Table
public class MySeq implements Serializable {
@Id
protected String orgId;
private int lastClientId;
//....
}
public Long getNewClientId(String orgId) {
MySeq mySeq = getSession()
.createQuery("from MySeq where orgId = :orgId", MySeq.class)
.setParameter("orgId", orgId)
.setLockMode(LockModeType.PESSIMISTIC_WRITE)
.uniqueResult();
mySeq.setLastClientId(mySeq.getLastClientId() + 1);
return mySeq.getLastClientId();
}
但是,如果有数千个并发请求,这会导致重复的 id 生成。因此,为了使其线程安全,我必须使用悲观锁定,以便多个请求不会生成相同的 clientId。但是现在的问题是,直到事务结束并且并发请求保持等待很长时间,锁才会被释放。
因此,如果我可以为每个 orgId 使用单独的序列,而不是使用锁,那么我也可以使 id 生成并发。我想通过执行诸如client_sequence_[orgId]之类的操作来确定运行时中的序列名称并执行它来生成id,从而手动执行序列生成器。
而且我还想让它独立于数据库,或者至少对于 Oracle、MySQL 和 Postgres。
我想知道是否有可能或有其他方法吗?
【问题讨论】:
标签: java multithreading hibernate hql