- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一些执行 UPSERT 的代码,也称为 Merge 。我想清理这段代码,具体来说,我想摆脱异常处理,并减少这样一个简单操作的代码的整体冗长和复杂性。要求是插入每个项目,除非它已经存在:
public void batchInsert(IncomingItem[] items) {
try(Session session = sessionFactory.openSession()) {
batchInsert(session, items);
}
catch(PersistenceException e) {
if(e.getCause() instanceof ConstraintViolationException) {
logger.warn("attempting to recover from constraint violation");
DateTimeFormatter dbFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
items = Arrays.stream(items).filter(item -> {
int n = db.queryForObject("select count(*) from rets where source = ? and systemid = ? and updtdate = ?::timestamp",
Integer.class,
item.getSource().name(), item.getSystemID(),
dbFormat.format(item.getUpdtDateObj()));
if(n != 0) {
logger.warn("REMOVED DUPLICATE: " +
item.getSource() + " " + item.getSystemID() + " " + item.getUpdtDate());
return false;
}
else {
return true; // keep
}
}).toArray(IncomingItem[]::new);
try(Session session = sessionFactory.openSession()) {
batchInsert(session, items);
}
}
}
}
对 SO 的初步搜索并不令人满意:
merge()
这在单线程时没问题在问题How to do ON DUPLICATE KEY UPDATE in Spring Data JPA?中被标记为重复项,我注意到这个有趣的评论:
这是一个死胡同,因为我真的不明白这个评论,尽管它听起来像是一个聪明的解决方案,并且提到了“实际相同的 SQL 语句”。
另一个有前途的方法是:Hibernate and Spring modify query Before Submitting to DB
冲突时不执行任何操作/重复 key 更新
两个主要的开源数据库都支持将幂等性下推到数据库的机制。下面的示例使用 PostgreSQL 语法,但可以轻松适应 MySQL。
遵循Hibernate and Spring modify query Before Submitting to DB中的想法, Hooking into Hibernate's query generation ,和How I can configure StatementInspector in Hibernate? ,我实现了:
import org.hibernate.resource.jdbc.spi.StatementInspector;
@SuppressWarnings("serial")
public class IdempotentInspector implements StatementInspector {
@Override
public String inspect(String sql) {
if(sql.startsWith("insert into rets")) {
sql += " ON CONFLICT DO NOTHING";
}
return sql;
}
}
有属性(property)
<prop key="hibernate.session_factory.statement_inspector">com.myapp.IdempotentInspector</prop>
不幸的是,当遇到重复项时,这会导致以下错误:
Caused by: org.springframework.orm.hibernate5.HibernateOptimisticLockingFailureException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1; nested exception is org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
如果您考虑一下幕后发生的事情,这是有道理的:ON CONFLICT DO NOTHING
会导致插入零行,但预计会插入一个。
有没有一种解决方案可以实现线程安全、无异常的并发幂等插入,并且不需要手动定义 Hibernate 执行的整个 SQL 插入语句?
就其值(value)而言,我认为将重复检查推送到数据库的方法是找到正确解决方案的途径。
澄清batchInsert
方法使用的 IncomingItem
对象源自记录不可变的系统。在这种特殊情况下,ON CONFLICT DO NOTHING
的行为与 UPSERT 相同,尽管可能会丢失第 N 个更新。
最佳答案
简短回答 - Hibernate 不支持开箱即用(正如 this blog post 中 Hibernate 专家所证实的那样)。也许您可以使用您已经描述的机制在某些情况下使其在某种程度上发挥作用,但直接使用 native 查询对我来说是实现此目的最直接的方法。
更长的答案是,考虑到我认为 Hibernate 的所有方面,很难支持它,例如:
@Audit
编辑的实体怎么样?它们是创建还是更新,如果更新则发生了什么变化?即使 Hibernate 以某种方式支持它,如果有太多需要注意和考虑的警告,我也不确定我是否会使用该功能。
所以,我遵循的经验法则是:
关于java - Hibernate线程安全幂等upsert无约束异常处理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56453690/
可写 CTE 被认为是 9.5 之前的 UPSERT 解决方案,如 Insert, on duplicate update in PostgreSQL? 中所述 可以使用以下可写 CTE 惯用法的信息
可写 CTE 被认为是 9.5 之前的 UPSERT 解决方案,如 Insert, on duplicate update in PostgreSQL? 中所述 可以使用以下可写 CTE 惯用法的信息
我正在通过 Python 在我的 MongoDB 上运行更新。我有这一行: self.word_counts[source].update({'date':posttime},{"$inc" : wo
我正在尝试使用 Sequelize 添加将数据创建到我的expressJs 应用程序中的 2 个表中的功能。 Controller : Campaign.upsert({ institutio
我正在尝试用现有的 ngxs 状态运算符替换或插入数组项 (upsert)。我目前正在使用以下 iif 语句。有更简单的方法吗? setState( patch({ contractLis
有没有一种方法可以在发生以下情况的 kdb 中更新插入: 如果键不存在,则插入值 如果key存在,检查当前值是否大于 A) 如果是,则不执行任何操作 B) 如果不是,更新值 类似于: job upse
我正在尝试更新测试键空间和表中的记录。当我插入一条记录时,接受一个列值更改,而另一个不接受。 (注意:尽管没有错误消息,我也无法删除记录) 观察 middle_initial 是如何不更新的,而 ti
我正在寻找一些有关如何优化sql存储过程的建议。 对于第一个查询,我正在执行插入操作,对于第二个查询,我正在进行更新(如果数据存在)。 我想要做的是将两个存储过程合并为一个,查询将检查数据是否存在而不
我有以下两个类(class) 条目 public class Entry { public Guid Id { get; set; } public IEnumerable Data
两年前有人问how to do upserts when you don't know a document's id . (未接受的)答案引用了 feature request 这导致了 _upda
今天这有点令人沮丧。我确定它很简单,我忽略了。请参阅下面的代码(为了示例而简化): def dbUpsert(sqlQuery, sqlValues): # Connect to the da
今天这有点令人沮丧。我确定它很简单,我忽略了。请参阅下面的代码(为了示例而简化): def dbUpsert(sqlQuery, sqlValues): # Connect to the da
我想更新插入(如果不存在则更新插入)我的 sqlite 表中的一些行。 我看到了这个sqlite命令: INSERT OR REPLACE INTO Employee (id, name, role)
我要从Amazon Mechanical Turk中提取一些数据并将其保存在mongodb集合中。 我有多个工作人员重复执行每个任务,因为略有冗余可以帮助我检查工作质量。 每次使用boto AWS p
我正在尝试测试新的 PostgreSQL upsert syntax使用以下测试代码,但出现语法错误: test=> CREATE TABLE test1 ( test(> key1
我正在使用 PostgreSQL v9.6.6。我正在运行以下 SQL: insert into t_vs_config_key (name, description, is_brand_depend
我在为 postgresql 编写强大的 upsert 函数方面得到了很多帮助。我正在尝试将值插入到包含 3 列的表中,其中两列是外键,一列是文本。 我有一个非常相似的函数,效果很好,只是没有像这个函
我在 MySQL 中有一个表,每晚都会通过 cron 任务更新。每一行都被更改,因为我从 XLS 文件获取数据并且必须更新所有值。 首先我的问题是是否值得更新每一行,或者另一方面删除所有行并再次插入。
更新插入在冲突时有效,但 id 的数据类型是串行的,这意味着我想让它自动生成/递增。如果我在不指定 id 的情况下执行插入,则插入工作正常。 我遇到的问题是将两者结合起来。为了让 key 自动递增,我
这个问题在这里已经有了答案: How to UPSERT (MERGE, INSERT ... ON DUPLICATE UPDATE) in PostgreSQL? (7 个答案) 关闭 4 年前
我是一名优秀的程序员,十分优秀!