只有在不存在的情况下,才使用hibernate将对象插入数据库

时间:2009-02-25 20:11:41

标签: database hibernate insert exists ignore

假设我有一个映射的User对象,其中user_id作为主键,而邮件列具有唯一约束。 我希望我的程序只有在不存在的情况下才能将User对象保存到users表。

我可以在插入功能中执行以下操作:

  1. 开始交易
  2. 查询具有给定邮件的用户
  3. 如果不存在,请创建一个新用户并使用会话保存
  4. 如果失败则提交或回滚
  5. 有两个问题:

    1. 执行两个查询很昂贵。如果我使用普通的SQL,我可能会使用“INSERT IGNORE”语法,但在我的情况下,我想使用hibernate save方法,而且我想最终保留User对象。有解决方案吗?
    2. 并发。我的应用程序的两个实例是否可能同时运行。两者都将使用“addUser”函​​数和相同的“mail”参数。第一个将通过第2阶段,并且找不到具有该邮件的用户。第二个也将在没有找到用户的情况下经历第2阶段,因为第一个实例仍然没有保存他的用户并且已经提交。然后第一个实例将保存并提交用户,然后第二个实例将保存并提交用户,该用户具有与第一个实例的邮件相同的邮件。因为约束,它当然会失败。 我错过了什么吗?
    3. 如果我是对的,我应该怎么做:

      1. 希望不会发生。
      2. 在事务开始时锁定users表以进行读写。
      3. 添加try ...除了函数之外,除了唯一约束异常外,如果抛出异常,只会根据邮件从db中选择用户。
      4. 其他解决方案......

3 个答案:

答案 0 :(得分:1)

除非你引入如此多的锁定系统变得无法使用,否则你几乎总是有这样的情况。除非您知道这是一个问题,否则您应该专注于优雅地处理唯一约束违规。

答案 1 :(得分:0)

  

你应该专注于优雅地处理唯一约束违规。

您可以通过捕获将抛出的ConstraintViolationException来执行此操作。如果你想要更具粒度,如果可能发生多个禁忌viilation,你可以这样做:

...
} catch (ConstraintViolationException e) {
    if (e.getConstraintName() != null && e.getConstraintName().toLowerCase().equals("the_name_of_your_contraint")) {
        // do something, like add an error to be displayed on the UI
    }
}

答案 2 :(得分:0)

现在我能做到的独特方式有效:

<sql-insert check="none" callable="true">
            {call saveOrUpdate (?, ?, ?, ?, ?)}
 </sql-insert>

http://forum.springsource.org/showthread.php?65265-Hibernate-insert-problem

其他选项我无法使其有效:

也许你可以用@SQLInsert Hibernate注释

制作一个“不存在的插入”

下一个选项仅适用于编辑实例:

其他选项是使用“使用版本列进行乐观锁定”并在出现并发异常时处理异常。

link:http://docs.jboss.org/hibernate/core/3.3/reference/en/html/transactions.html#transactions-optimistic

相关问题