【问题标题】:JPA 2.0 EclipseLink Check for uniqueJPA 2.0 EclipseLink 检查唯一性
【发布时间】:2010-04-14 23:23:48
【问题描述】:

我有一个列作为 unique=true.. 在考试课.... 我发现因为事务是自动提交的,所以要强制我使用的提交 em.commit()

但是我想知道如何检查它是否是唯一的。运行查询不是解决方案,因为由于并发性,它可能是检查后的插入......

检查唯一性的最佳方法是什么?

List<Exam_Normal> exam_normals = exam.getExam_Normal();
    exam.setExam_Normal(null);

    try {
        em.persist(exam);
        em.flush();

        Long i = 0L;
        if (exam_normals != null) {
            for (Exam_Normal e_n : exam_normals) {
                i++;
                e_n.setItem(i);
                e_n.setId(exam);
                em.persist(e_n);
            }
        }
    } catch (Exception e) {
        System.out.print("sfalma--");
    }
}

d

【问题讨论】:

    标签: java jpa eclipselink jpa-2.0


    【解决方案1】:

    不幸的是,JPA 无法避免因违反唯一约束而导致事务回滚,因为规范要求此异常将事务标记为回滚。此外,因为当您使用 JPA 2.0 API 发出“锁定”调用时,该行可能不存在,所以“锁定”调用不能确保只有锁定线程才能插入对象。 “锁定”会阻止更新实体,但不会阻止插入。

    您需要像在代码中一样执行“持久化”,但尽可能将其保持在事务的开头或让操作发生在其自己的事务中。

    如果“持久化”必须是较大事务的一部分,并且持久化失败并不妨碍您的应用程序的这一部分成功,那么您应该存储该事务中的实体实例,您将能够“合并”它们一旦您的应用程序从回滚中恢复,进入任何后续事务。

    【讨论】:

    • 感谢您的回复...那么在我的情况下您会怎么做?正如您所说,锁定无济于事..考试对象具有独特的柱状人员。如何捕获错误并通知用户发生了唯一违规?
    • 啊,是的,当然,没想到行可能不存在。感谢您指出这一点。
    • 这确实取决于您的应用程序,但需要记住的一些事项是:如果您可以将行的创建隔离到单个事务或使用 JPA EntityManager.flush() API 导致行在事务开始时插入,您将保存丢失事务中的其他更改。如果您担心丢失考试实体中的信息,您可以始终保留对托管实体的引用。一旦事务回滚,让用户修复同一实例中的唯一性问题,并将同一实例合并到新 TXN 中的新 EntityManager 中。
    • 要向用户报告问题,只需捕获 PersistenceException 并检查所有“原因”,直到您到达 SQL 级别。如果是唯一约束违规,则在 UI 中向用户报告冲突,并指导他们如何解决问题并“重放”交易。
    【解决方案2】:

    但是我想知道如何检查它是否是唯一的。运行查询不是解决方案,因为它可能是检查后的插入,因为并发......

    JPA 2.0 允许悲观锁定并为此添加了三种锁定模式。这可能是您的用例的一个选项。

    一些参考资料:

    【讨论】:

    • 所以你的意思是我应该锁定,然后检查该值是否存在,然后持久化并解锁?
    • @Parhs 我想避免异常(并因此重新开始,因为事务将被标记为回滚),是的。
    【解决方案3】:

    我假设该列不是主键 (@Id),在这种情况下,您的应用程序必须保证唯一性。字段唯一性的保证可能必须来自其他地方。该字段是什么类型的值?这里有一些想法

    如果是计数器,那么您可能可以使用@Singleton stateful bean (JavaEE 6. See this.

    如果您使用的是 EE5,则使用带有 @Entity 映射到自动生成的密钥的无状态 bean。

    【讨论】:

    • 我正在使用 java ee 6 不幸的是它不是一个计数器它是一个字符串...它不是一个主键,但它必须是唯一的业务规则。
    • 那么你必须保证你的应用程序的唯一性。如果我可能好奇,String 的本质是什么。价值是如何产生的?
    • 如果像创建登录名,那你可能要查询
    • 如何做到安全?例如 2 个用户同时使用相同的字符串
    • 好吧,我认为其中一个可能会出现异常。你真的无能为力。问题是您无法锁定记录/实体,因为您的字段不是主键。您可能需要考虑添加名称字段以使其成为复合/复合主键。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-21
    • 2011-08-24
    • 2014-04-15
    • 1970-01-01
    • 2018-09-24
    相关资源
    最近更新 更多