Java 在事务开始时锁定表
由于遗留代码问题,在向数据库插入新行时,我需要手动计算唯一索引,不能使用自动增量Java 在事务开始时锁定表,java,database,hibernate,locking,Java,Database,Hibernate,Locking,由于遗留代码问题,在向数据库插入新行时,我需要手动计算唯一索引,不能使用自动增量 问题是多个客户端(不同的机器)的多个插入可能同时发生。因此,我需要在当前事务处于活动状态时锁定id最高的行,以防其他事务读取该行。或者,我可以锁定整张桌子,防止任何读取。在这种情况下,时间不是问题,因为写入/读取非常罕见(问题是,使用悲观读取时,您正在阻止ID最高的行上的其他更新。如果要阻止其他人的选择,则需要使用悲观写入 我知道这看起来很奇怪,因为你不打算更新那一行……但是如果你想在执行SELECT时使用其他块,
问题是多个客户端(不同的机器)的多个插入可能同时发生。因此,我需要在当前事务处于活动状态时锁定id最高的行,以防其他事务读取该行。或者,我可以锁定整张桌子,防止任何读取。在这种情况下,时间不是问题,因为写入/读取非常罕见(问题是,使用悲观读取时,您正在阻止ID最高的行上的其他更新。如果要阻止其他人的选择,则需要使用悲观写入 我知道这看起来很奇怪,因为你不打算更新那一行……但是如果你想在执行SELECT时使用其他块,你应该碱化并说:“嗨,所有……我读了这一行并将更新它”……这样他们就不被允许读那一行,因为DB引擎认为你会在提交之前修改它
根据文档,SERIALIZABLE本身会将所有普通SELECT语句转换为SELECT…在共享模式下锁定,因此不会超过您已明确执行的操作。您是否可以选择实现服务并通过该服务公开数据库?不,遗憾的是,不可以。整个体系结构一团糟(长达15年)而且所有客户端都直接连接到数据库。当我现在实现它时,我会选择连接到DB的中央服务器和瘦客户端,它们只从服务器请求和显示数据。但遗憾的是,客户端有超过200k的LOC,完全重写它不是一个选项(每次生成一个唯一标识符如何?由基于时间的部分加上随机部分组成。或加密安全的唯一标识符。没有事务隔离或乐观锁定问题,易于实现。还有一个想法——使用序列。
public void insert(T entity) {
EntityManager em = factory.createEntityManager();
try {
EntityTransaction transaction = em.getTransaction();
try {
transaction.begin();
int id = 0;
TypedQuery<MasterDataComplete> query = em.createQuery(
"SELECT m FROM MasterDataComplete m ORDER BY m.id DESC", MasterDataComplete.class);
query.setMaxResults(1);
query.setLockMode(LockModeType.PESSIMISTIC_READ);
List<MasterDataComplete> results = query.getResultList();
if (!results.isEmpty()) {
MasterDataComplete singleResult = results.get(0);
id = singleResult.getId() + 1;
}
entity.setId(id);
em.persist(entity);
transaction.commit();
} finally {
if (transaction.isActive()) {
transaction.rollback();
}
}
} finally {
em.close();
}
}