如何将我的用户创建方法限制为一次交易? (容器与事务管理并发)

How to limit my user creation method to one transaction at the time? (Container vs Transaction managed Concurrency)

我正在使用 ContainerRequestFilter 检查用户是否已存在于我的数据库中。 如果没有,它调用一个服务来创建它:

@Provider
@Priority(Priorities.AUTHENTICATION)
public class AuthenticationRequestFilter implements ContainerRequestFilter {
    // [...]
    @Inject
    JsonWebToken jwt;

    @Override
    public void filter(ContainerRequestContext containerRequestContext) {
            UserAccount userAccount = userAccountService.createIfNotExistsBySubjectId(jwt.getSubject());
        }
    }
}

服务 bean:

@RequestScoped
public class UserAccountService {
    // [...]
    @Transactional
    public UserAccount createIfNotExistsBySubjectId(String subjectId) {       
        UserAccount userAccount = UserAccount.find("subjectId", subjectId).withLock(LockModeType.PESSIMISTIC_WRITE).firstResult();
        if (userAccount == null) {
            log.info(MessageFormat.format("Creating new user account for subjectId {0}.", subjectId));
            UserAccount userAccount = new UserAccount(subjectId)
            userAccount.persistAndFlush();
        } 
        return userAccount;
    }
}

因此,我在同时发送多个请求时遇到了竞争条件。两个线程正在调用我的方法:

...导致明显的 SQL 错误:

为了解决这个问题,我尝试了两种方法:

我做错了什么? 我想确保以阻塞方式调用用户创建方法。

任何时候你对远程系统进行 read/check/update 操作,你都会遇到这样的问题。

您需要做的是利用数据库的“upsert”功能。请参阅 了解如何在 PostgreSQL

中创建正确的查询