在 PersistenceException catch 子句中执行 JPQL 查询重新抛出 PersistenceException

Executing JPQL query in PersistenceException catch clause re-throws PersistenceException

我正在尝试使用 JPA 在我的 JavaEE 应用程序的 DAO 中实现一些错误处理。

我有这样的情况,有人(用户)可能会尝试在我的数据库中输入重复项。我的计划是尝试坚持我的实体,例如。用户("test@test.com"、"Test"、"password")。如果这失败并出现 PersistenceException,我想我可以检查唯一列上的重复条目,例如用户名 ("Test") 和电子邮件 ("test@test.com)。如果我找到重复项,我会喜欢检查失败的列并相应地通知用户。

我的尝试如下:

getEntityManager().persist(entity);
try {
    getEntityManager().flush();
} catch (PersistenceException ex) {
    List<T> duplicates = findDuplicate(entity);
    if (duplicates.size() > 0) {
        // Notify user
    } else {
        // Probably pass exception forwards
    }
}

实体管理器被注入到 class 中:

@PersistenceContext(unitName = "RecruitmentPU")
protected EntityManager mEM;

getEntityManager() 只是 return 这个成员。 class 它自己被注释为 @Stateless.

要找到重复项,我基本上就是这样做的:

String column = myEntity.getUniqueColumn(); // returns the name of the column
Object uniqueValue = myEntity.getUniqueValue(); // returns the value of the unique column

Query query = getEntityManager().createQuery(
        "SELECT e FROM TestEntity e WHERE " + column + " = :identifier",
        TestEntity.class
);

query.setParameter("identifier", uniqueValue);
List<T> entries = null;
try {
    entries = (List<T>) query.getResultList(); // Here the exception is re-thrown
} catch(Exception ex) {
    System.out.println("Caught something... \n" + ex.getMessage());
}

该实体还有一个带有注释的 ID 列 @GeneratedValue(strategy = GenerationType.IDENTITY)。还有一个 @ManyToOne 属性,是我简化代码时删除的。当我测试这个时,我得到以下输出:

Info:   Caught something... 
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.6.3.qualifier): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry 'Test' for key 'username_UNIQUE'
Error Code: 1062
Call: INSERT INTO test.test (email, username, role) VALUES (?, ?, ?)
        bind => [3 parameters bound]
Query: InsertObjectQuery(ID: 0 | email: test@test.com | username: Test | password: ********)

目前我让容器处理事务,但我有预感我遇到了这些问题,因为我试图在第一个事务完成之前查询数据库(或类似的东西).

是战略上的缺陷还是执行上的缺陷?我可以采取哪些步骤来开始解决这个问题?

don't want在发生异常后继续任何交易。

我建议你调换操作顺序,像这样:

  1. 在数据库中查询具有与您要保留的实体的唯一键相同的唯一键的记录,
  2. 坚持你的实体。