java 如何处理JPA唯一约束冲突?

ghg1uchk  于 2023-01-15  发布在  Java
关注(0)|答案(9)|浏览(250)

当违反了唯一约束时,会抛出javax.persistence.RollbackException。但是抛出RollbackException可能有多种原因。我如何才能发现违反了唯一约束?

try {
    repository.save(article);
}
catch(javax.persistence.RollbackException e) {
    // how to find out the reason for the rollback exception?
}
eimct9ow

eimct9ow1#

如何发现违反了唯一约束?
异常是链式的,你必须递归调用getCause()来获取提供者特定的异常(可能会下到SQLException),将其转换成你的应用程序可以为你的用户很好地处理的东西。

for (t = e.getCause(); t != null; t = t.getCause()) {
    logger.debug("Exception:" + t);
}

对于异常处理和“转换”,您可以做一些类似Spring所做的事情(参见各种JpaDialect类,例如HibernateJpaDialect来获得一个想法)。
所有这些都不太好,这些代码不能移植,而且找到导致违规的属性也不容易,这在某种程度上证实了不存在elegant and portable way to handle constraint violations in JPA

pgpifvop

pgpifvop2#

您可以使用以下方法:
如果您使用的是Spring框架,那么您可以用途:
org.springframework.dao.DataIntegrityViolationException
如果可以使用以下标准JPA
org.hibernate.exception.ConstraintViolationException
在SQL级别,可以使用以下内容:
java.sql.SQLIntegrityConstraintViolationException

nbewdwxp

nbewdwxp3#

使用e.getCause()检查导致回滚的原因。

e37o9pze

e37o9pze4#

这对你来说可能很晚了,但我是这样解决PostGres的。

catch (DataIntegrityViolationException e) {

            for (Throwable t = e.getCause(); t != null; t = t.getCause()) {

                if (PSQLException.class.equals(t.getClass())) {
                    PSQLException postgresException = (PSQLException) t;

                    // In Postgres SQLState 23505=unique_violation
                    if ("23505".equals(postgresException.getSQLState())) {
                        throw new CustomDataAlreadyExistsException("YourErrorCode", e);
                    }
                }
            }
            throw new SomeOtherException("YourErrorCode2", e);

        }
jutyujz0

jutyujz05#

编译器在尝试违反唯一约束时返回异常***SQLIntegrityConstraintViolationException***。
使用下面的catch块概念来处理适当的异常。

catch(SQLIntegrityConstraintViolationException e) 
{
  // Error message for integrity constraint violation
}
catch(Exception e)
{
 // Other error messages
}
ttp71kqs

ttp71kqs6#

我认为打印堆栈跟踪将帮助您了解这一点。e.printStackTrace();

6qqygrtg

6qqygrtg7#

你可以这样做:

StringWriter writer=new StringWriter(); //remains the message from stack trace.
e.printStackTrace(new PrintWriter(writer));
String message=writer.toString(); // gets the message of full stack trace.

然后查看异常信息。

yvfmudvl

yvfmudvl8#

您必须捕获javax. persistence. PersistenceException。抛出的异常是org. hibernate. exception. ConstraintViolationException。
异常消息:组织。休眠。异常。约束违反异常:密钥“nic_account_no”的条目“893073116 V-1234567”重复

lqfhib0f

lqfhib0f9#

找出约束冲突原因的最简单方法是首先正确定义约束的名称

定义唯一约束:

@Table中使用@UniqueConstraint,我们可以定义一列或多列约束,沿着一个自定义约束名称

@Entity
@Table(uniqueConstraints = {
        @UniqueConstraint(columnNames = { "name" }, name = "name_constraint"),
        @UniqueConstraint(columnNames = { "teamId", "orderIndex" }, name = "teamId_orderIndex_constraint")
})
public class Space {
    // .. other field omitted

    private String name;

    private Integer orderIndex;

    private Integer teamId;
}

JPA使用我们的自定义名称更改约束:

Hibernate: 
    alter table space
       add constraint name_constraint unique (name)

Hibernate: 
    alter table space
       add constraint teamId_orderIndex_constraint unique (team_id, order_index)

正确处理DataIntegrityViolationException

使用e.getMessage(),我们返回结果,其中包含我们上面定义的约束的名称:

could not execute statement; SQL [n/a]; constraint [space.name_constraint]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement

然后简单地检查结果是否包含我们定义的名称:

import org.springframework.dao.DataIntegrityViolationException;

try {
    repository.save(space);
} catch (DataIntegrityViolationException e) {

    if(e.getMessage().contains("name_constraint")) {
        System.out.println("Unique name constraint violated");
    }

    if(e.getMessage().contains("teamId_orderIndex_constraint")) {
        System.out.println("Unique teamId_orderIndex constraints violated");
    }
}

参考:在JPA中定义唯一约束

相关问题