java - 如果在并发操作中不存在,则 JPA 插入实体
问题描述
我有一个简单的用例:
我想插入一个不存在的实体。
这是实体类,它结合了独特的列:
@Entity
@Table(uniqueConstraints = {
@UniqueConstraint(columnNames = {
"firstName", "lastName"
})
})
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String firstName;
private String lastName;
这是简单的插入逻辑:
Optional<Customer> customer = customerRepository.findByFirstNameAndLastName("John", "Doe");
if (!customer.isPresent()) {
customerRepository.save(new Customer("John", "Doe"));
}
当我通过并发线程调用它时,我得到了这个ConstraintViolationException
,这很明显
insert into customer (first_name, last_name, id) values (?, ?, ?) [23505-200]]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause
org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException: Unique index or primary key violation: "PUBLIC.UKKIYY7M3FWM4VO5NIL9IBP5846_INDEX_5 ON PUBLIC.CUSTOMER(FIRST_NAME, LAST_NAME) VALUES 8"; SQL statement:
insert into customer (first_name, last_name, id) values (?, ?, ?) [23505-200]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:459) ~[h2-1.4.200.jar:1.4.200]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:429) ~[h2-1.4.200.jar:1.4.200]
我可以捕捉到这个异常,但 ConstraintViolationException 可以在唯一索引以外的任何情况下发生。
我还尝试了 JPA 的乐观锁定,但它似乎只在更新和删除操作中有效,而在插入时无效。
我不想要本地查询(比如ON DUPLICATE KEY
在 mysql 中,ON CONFLICT
在 PostgresSQL 中),因为我想让操作在 JPA 本身中处理。
此外,我无法使其成为线程安全的,因为应用程序将在多个 JVM 上运行。
有什么办法可以处理这个问题,比如锁定插入或至少更新相同的键?
解决方案
推荐阅读
- javascript - 保存复选框选择
- java - 如何将 java.util.stream.Stream 写入 StreamingResponseBody 输出流
- java - 从字节数组到图像java
- javascript - 使用 dynmac setInterval 反应 UseEffect
- c++ - 为什么 map.find 使用 < 运算符而不是 == 运算符?
- javascript - 不占空间的置顶
- java - 具有动态方法名称的接口
- pandas - pandas 为小于 0.05 的值添加一个“*”
- html - 如何在 CSS 中调用 id 内的锚点?
- python - 列名未在熊猫数据框中引用