1概要

このクイックチュートリアルでは、最も重要な一般的な

NonTransientDataAccessException

の種類を例に挙げて説明します。


2

基本例外クラス

このメイン例外クラスのサブクラスは、非一時的または永続的と見なされるデータアクセス関連の例外を表します。

簡単に言うと、つまり、根本的な原因が修正されるまでは、例外を引き起こしたメソッドの今後の試みはすべて失敗するということです。


3

DataIntegrityViolationException


このサブタイプの

NonTransientDataAccessException

は、データを変更しようとしたときに整合性制約に違反した場合にスローされます。


Foo

クラスの例では、name列は

null

値を許可しないように定義されています。

@Column(nullable = false)
private String name;

名前に値を設定せずにインスタンスを保存しようとすると、

DataIntegrityViolationException

がスローされることが予想されます。

@Test(expected = DataIntegrityViolationException.class)
public void whenSavingNullValue__thenDataIntegrityException() {
    Foo fooEntity = new Foo();
    fooService.create(fooEntity);
}


3.1.

DuplicateKeyException



DataIntegrityViolationException

のサブクラスの1つは

DuplicateKeyException

です。これは、2つの行を挿入しようとするなど、すでに存在する主キーを持つレコード、または

unique

制約を持つ列にすでに存在する値を保存するとき

foo

テーブル内で、同じ

id

が1の場合:

@Test(expected = DuplicateKeyException.class)
public void whenSavingDuplicateKeyValues__thenDuplicateKeyException() {
    JdbcTemplate jdbcTemplate = new JdbcTemplate(restDataSource);
    jdbcTemplate.execute("insert into foo(id,name) values (1,'a')");
    jdbcTemplate.execute("insert into foo(id,name) values (1,'b')");
}


4

DataRetrievalFailureException


データベースに存在しない識別子を持つオブジェクトを検索するなど、データの取得中に問題が発生した場合、この例外がスローされます。

たとえば、この例外をスローするメソッドを持つ

JdbcTemplate

クラスを使用します。

@Test(expected = DataRetrievalFailureException.class)
public void whenRetrievingNonExistentValue__thenDataRetrievalException() {
    JdbcTemplate jdbcTemplate = new JdbcTemplate(restDataSource);

    jdbcTemplate.queryForObject("select **  from foo where id = 3", Integer.class);
}


4.1

IncorrectResultSetColumnCountException


この例外サブクラスは、適切な

RowMapper

を作成せずにテーブルから複数の列を取得しようとするとスローされます。

@Test(expected = IncorrectResultSetColumnCountException.class)
public void whenRetrievingMultipleColumns__thenIncorrectResultSetColumnCountException() {
    JdbcTemplate jdbcTemplate = new JdbcTemplate(restDataSource);

    jdbcTemplate.execute("insert into foo(id,name) values (1,'a')");
    jdbcTemplate.queryForList("select id,name from foo where id=1", Foo.class);
}


4.2

IncorrectResultSizeDataAccessException


この例外は、検索されたレコードの数が予想されたレコードの数と異なる場合、たとえば単一の

Integer

値を期待しているが、クエリに対して2行を取得している場合にスローされます。

@Test(expected = IncorrectResultSizeDataAccessException.class)
public void whenRetrievingMultipleValues__thenIncorrectResultSizeException() {
    JdbcTemplate jdbcTemplate = new JdbcTemplate(restDataSource);

    jdbcTemplate.execute("insert into foo(name) values ('a')");
    jdbcTemplate.execute("insert into foo(name) values ('a')");

    jdbcTemplate.queryForObject("select id from foo where name='a'", Integer.class);
}


5

DataSourceLookupFailureException


この例外は、指定されたデータソースが取得できないときにスローされます。例として、存在しないデータソースを探すためにクラス

JndiDataSourceLookup

を使用します。

@Test(expected = DataSourceLookupFailureException.class)
public void whenLookupNonExistentDataSource__thenDataSourceLookupFailureException() {
    JndiDataSourceLookup dsLookup = new JndiDataSourceLookup();
    dsLookup.setResourceRef(true);
    DataSource dataSource = dsLookup.getDataSource("java:comp/env/jdbc/example__db");
}


6.

InvalidDataAccessResourceUsageException


この例外は、ユーザーが

SELECT

権限を持っていない場合など、リソースが誤ってアクセスされたときにスローされます。

この例外をテストするには、ユーザーの

SELECT

権限を取り消してからSELECTクエリを実行する必要があります。

@Test(expected = InvalidDataAccessResourceUsageException.class)
public void whenRetrievingDataUserNoSelectRights__thenInvalidResourceUsageException() {
    JdbcTemplate jdbcTemplate = new JdbcTemplate(restDataSource);
    jdbcTemplate.execute("revoke select from tutorialuser");

    try {
        fooService.findAll();
    } finally {
        jdbcTemplate.execute("grant select to tutorialuser");
    }
}


finally

ブロックでユーザーの権限を復元していることに注意してください。


6.1

BadSqlGrammarException



InvalidDataAccessResourceUsageException

の非常に一般的なサブタイプは

BadSqlGrammarException

です。これは、無効なSQLでクエリを実行しようとしたときにスローされます。

@Test(expected = BadSqlGrammarException.class)
public void whenIncorrectSql__thenBadSqlGrammarException() {
    JdbcTemplate jdbcTemplate = new JdbcTemplate(restDataSource);
    jdbcTemplate.queryForObject("select **  fro foo where id=3", Integer.class);
}

もちろん

fro –

はクエリの無効な側面です。


7.

CannotGetJdbcConnectionException


この例外は、データベースのURLが正しくない場合など、

JDBC

を介した接続の試行が失敗した場合にスローされます。次のようにURLを書きます。

jdbc.url=jdbc:mysql:3306://localhost/spring__hibernate4__exceptions?createDatabaseIfNotExist=true

ステートメントを実行しようとすると、

CannotGetJdbcConnectionException

がスローされます。

@Test(expected = CannotGetJdbcConnectionException.class)
public void whenJdbcUrlIncorrect__thenCannotGetJdbcConnectionException() {
    JdbcTemplate jdbcTemplate = new JdbcTemplate(restDataSource);
    jdbcTemplate.execute("select **  from foo");
}


8結論

これまでのチュートリアルでは、

NonTransientDataAccessException

クラスの最も一般的なサブタイプについて見てきました。

すべての例の実装はhttps://github.com/eugenp/tutorials/tree/master/spring-exceptions[GitHubプロジェクト]にあります。もちろん、すべての例ではインメモリデータベースを使用しているため、何も設定せずに簡単に実行できます。