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プロジェクト]にあります。もちろん、すべての例ではインメモリデータベースを使用しているため、何も設定せずに簡単に実行できます。