java - 如何避免通过 Java 在数据库中重复插入?

标签 java oracle hibernate web-applications concurrency

我需要在 Employee 表中插入员工 我想要的是避免重复插入,即如果两个线程试图同时插入同一个员工,那么最后一个事务 应该失败。例如,如果两个员工的 first_name 和 hire_date 相同(同一员工来自两个线程),则最后一个事务失败。

方法 1:- 我能想到的第一种方法是将约束放在列级别(例如 first_name 和 hire_date 上的组合唯一约束)或在查询中检查是否 employee exist throw error(我相信可以通过 PL/SQL)

方法 2:- 是否也可以在 java 级别完成,例如创建一个首先检查员工是否存在然后抛出错误的方法。在那种情况下,我需要使方法同步(或 同步块(synchronized block)),但它会影响性能,它也会不必要地持有其他事务。有没有一种方法可以放置锁(可重入锁)或使用基于名称/雇用日期的同步方法,以便只有那些具有相同名称和雇用日期的特定交易才会被搁置

public void  save(Employee emp){
    //hibernate api to save
}

我认为应该首选方法 1,因为它简单且易于实现。正确的 ?即使是,我想知道是否可以在 Java 级别有效地处理它?<​​/p>

最佳答案

What i want is is to avoid duplicate inserts

but it will impact performance it will unnecassrily hold other transactions also

因此,您需要保证没有重复的高并发插入。

无论您是在 Java 中还是在数据库中执行此操作,唯一避免重复插入的方法是序列化(或者,Java 语言,同步)。也就是说,让一个事务等待另一个事务。

如果您在键值上创建PRIMARY KEYUNIQUE 约束,Oracle 数据库会自动为您执行此操作。不重复的同时插入不会相互干扰或等待。但是,如果两个 session 同时尝试重复插入,第二个将等待第一个完成。如果第一个 session 通过 COMMIT 完成,则第二个事务将失败并出现索引冲突重复键。如果第一个 session 通过 ROLLBACK 完成,第二个事务将成功完成。

您也可以在 Java 中做类似的事情,但问题是您需要一种所有 session 都可以访问的锁定机制。 synchronize 和类似的替代方案只有在所有 session 都在同一 JVM 中运行时才有效。

此外,在 Java 中,最大化并发性和最小化等待的关键是只等待实际的重复项。您可以通过散列传入的键值然后仅在该散列上同步来实现接近于此的效果。也就是比如把65536个对象放到一个列表中。然后当插入想要发生时,将传入的键值散列为 1 到 65536 之间的数字。然后从列表中获取该对象并对其进行同步。当然,您也可以在实际键值上进行同步,但散列通常同样好,而且更易于使用,尤其是在传入的键值难以处理或敏感的情况下。

总而言之,这绝对应该在数据库中使用表上的简单 PRIMARY KEY 约束和适当的错误处理来完成。

关于java - 如何避免通过 Java 在数据库中重复插入?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40132612/

相关文章:

sql - 每次创建索引时是否都需要运行 gather_table_stats 以便 Oracle 优化器使用它?

java - 数据处理平衡

sql - Postgres 获得单个供应商的第一个和最后一个版本

java - 如何使用 Vaadin 进行测试驱动开发?

java - 相当于 Java 中 ObjectInputStream 的 BufferedReader.readNext()

java - Tomcat服务器远程重新部署

c# - 需要以 C# 字符串数据类型 "as is"获取 Oracle RAW

SQL group by "date"问题

java - 将数据记录保存到数据库时出现 SQL 语法错误

java - 鼠标悬停后点击