一意制約に違反すると、javax.persistence.RollbackException
がスローされます。ただし、RollbackException
をスローする理由はいくつかあります。一意制約に違反していることをどのように確認できますか?
try {
repository.save(article);
}
catch(javax.persistence.RollbackException e) {
// how to find out the reason for the rollback exception?
}
一意制約に違反していることをどのように確認できますか?
例外はチェーン化されています。getCause()
を再帰的に呼び出してプロバイダー固有の例外を取得し(そしてSQLException
に移動して)、アプリケーションがユーザーにとって適切に処理できるものに変換する必要があります。以下は例外のチェーンを出力します:
for (t = e.getCause(); t != null; t = t.getCause()) {
logger.debug("Exception:" + t);
}
例外処理と「変換」については、Springが行うようなことを行うことができます(さまざまなJpaDialect
クラス、たとえば HibernateJpaDialect
を参照してください)。
これはいいことではありません。このコードは移植できず、違反の原因となった属性を見つけるのは簡単ではありません。これにより、JPAの制約違反を処理する のエレガントで移植可能な方法がないことが何らかの形で確認されます 。
e.getCause()
を使用して、ロールバックの原因を調べます。
コンパイラーは、一意の制約に違反しようとしたときに、例外SQLIntegrityConstraintViolationExceptionを返します。
適切な例外を処理するには、次のキャッチブロックの概念を使用します。
catch(SQLIntegrityConstraintViolationException e)
{
// Error message for integrity constraint violation
}
catch(Exception e)
{
// Other error messages
}
次のものを使用できます。
Springフレームワークを使用している場合は、次を使用できます:
org.springframework.dao.DataIntegrityViolationException
標準のJPAが使用できる場合
org.hibernate.exception.ConstraintViolationException
SQLレベルでは、以下を使用できます。
Java.sql.SQLIntegrityConstraintViolationException
これは非常に遅いかもしれませんが、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);
}
あなたはこのようにすることができます:
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.
そして、例外の情報を表示します。
スタックトレースを印刷すると、これを知るのに役立ちます。 e.printStackTrace();