Java 如何在Spring/OpenJPA 1中重新创建用于更新行锁定的选择

Java 如何在Spring/OpenJPA 1中重新创建用于更新行锁定的选择,java,spring,multithreading,openjpa,Java,Spring,Multithreading,Openjpa,我需要在Spring/OpenJPA1应用程序中不允许同时使用相同的确认代码。我们决定使用select for update策略,因此我们创建了表AdmissionLock(id、确认码、终端)。 单独的示例JDBC应用程序可以很好地使用这种策略。它允许同时处理不同的确认代码,不允许同时处理相同的确认代码。请参见下面的示例代码: 线程代码: conn.setAutoCommit(false); long retId = Util.lockBySelectUpdate(conn, threadNa

我需要在Spring/OpenJPA1应用程序中不允许同时使用相同的确认代码。我们决定使用select for update策略,因此我们创建了表AdmissionLock(id、确认码、终端)。
单独的示例JDBC应用程序可以很好地使用这种策略。它允许同时处理不同的确认代码,不允许同时处理相同的确认代码。请参见下面的示例代码:

线程代码:

conn.setAutoCommit(false);
long retId = Util.lockBySelectUpdate(conn, threadName, terminalCode, confNumber);
Util.updateConfCode(conn, threadName, terminalCode, confNumber);
conn.commit();
主程序代码:

String confCode1 = "21";
String confCode2 = "22";
String terminalCode1 = "10";
String terminalCode2 = "11";
Connection conn1 = Util.getNewConnection();
Connection conn2 = Util.getNewConnection();
AdmissionThread admissionThread1=new AdmissionThread(terminalCode1, conn1, confCode1, "Thread1", 10);
AdmissionThread admissionThread2=new AdmissionThread(terminalCode2, conn2, confCode2, "Thread2", 0);
    admissionThread1.start();
    Thread.sleep(2000);
    admissionThread2.start();
SQL:

因为我们的应用程序是Spring/openjpa1,所以我需要在Spring/openjpa1代码中包含这个想法。因此,我使用以下简化代码创建了服务:

@Transactional
public void processAdmissionLock (String terminalSerialNumber, String confirmationCode){

AdmissionLock admissionLock = new AdmissionLock(terminalSerialNumber, confirmationCode);
        query = entityManager.createNativeQuery(SQL_LOCK_STRING);
        entityManager.lock(admissionLock, LockModeType.READ);
        query.setParameter(1, confirmationCode).getResultList();

        if(isEntityPersistent(admissionLock)) {
            admissionLock = entityManager.merge(admissionLock);
        } else {
            entityManager.persist(admissionLock);
        }
}
许可证实体:

@Entity
@Table (name = SdiAdmissionLock.TABLE_NAME)
public class SdiAdmissionLock extends AbstractEntityImpl {

    private static final long serialVersionUID = 1L;
    private long uidpk;
    private String terminalSerialNumber;
    private String confirmationCode;
    private Date createdDate;

    public static final String TABLE_NAME = "SDIADMISSIONLOCK";
...
}

我的问题是这个代码没有锁定任何东西。具有相同确认代码的两个同步线程都通过了

我最终使用了与JDBC应用程序中相同的本机查询。一个重要的区别是,启动事务(“启动事务”)和提交(“提交”)被转移到MYSQL本身,并由JDBC executeUpdate()方法调用。

我最终使用了与JDBC应用程序相同的本机查询。一个重要的区别是启动事务(“启动事务”)和提交(“提交”)被转移到MYSQL本身,并由JDBC executeUpdate()方法调用

@Entity
@Table (name = SdiAdmissionLock.TABLE_NAME)
public class SdiAdmissionLock extends AbstractEntityImpl {

    private static final long serialVersionUID = 1L;
    private long uidpk;
    private String terminalSerialNumber;
    private String confirmationCode;
    private Date createdDate;

    public static final String TABLE_NAME = "SDIADMISSIONLOCK";
...
}