1. Overview
1.概述
In this quick tutorial, we will go through the most important types of the common NonTransientDataAccessException and illustrate them with examples.
在这个快速教程中,我们将了解常见的NonTransientDataAccessException的最重要类型,并通过实例进行说明。
2. The Base Exception Class
2.基础异常类
Subclasses of this main exception class represent data access related exceptions which are considered non-transient or permanent.
这个主异常类的子类代表了与数据访问相关的异常,这些异常被认为是非暂时性的或永久性的。
Simply put, that means that – until the root cause is fixed – all future attempts of a method that caused an exception, will fail.
简单地说,这意味着–在根本原因得到解决之前–所有未来对引起异常的方法的尝试都会失败。
3. DataIntegrityViolationException
3、DataIntegrityViolationException
This subtype of NonTransientDataAccessException is thrown when an attempt to modify data causes a violation of an integrity constraint.
当试图修改数据导致违反完整性约束时,会抛出NonTransientDataAccessException的这个子类型。
In our example of the Foo class, the name column is defined as not allowing the null value:
在我们的Foo类的例子中,name列被定义为不允许出现null值。
@Column(nullable = false)
private String name;
If we attempt to save an instance without setting a value for the name, we can expect a DataIntegrityViolationException to be thrown:
如果我们试图保存一个实例而不为名字设置一个值,我们可以期待一个DataIntegrityViolationException的抛出。
@Test(expected = DataIntegrityViolationException.class)
public void whenSavingNullValue_thenDataIntegrityException() {
Foo fooEntity = new Foo();
fooService.create(fooEntity);
}
3.1. DuplicateKeyException
3.1.DuplicateKeyException
One of subclasses of the DataIntegrityViolationException is DuplicateKeyException, which is thrown when there is an attempt to save a record with a primary key that already exists or a value that is already present in a column with a unique constraint, such as attempting to insert two rows in the foo table with the same id of 1:
DataIntegrityViolationException的一个子类是DuplicateKeyException,当试图保存一个主键已经存在的记录,或者一个值已经存在于具有unique约束的列中,例如试图在foo表中插入两条具有相同id的记录,就会抛出这个问题。
@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
4、DataRetrievalFailureException
This exception is thrown when a problem during retrieving data appears, such as looking up an object with an identifier which doesn’t exist in a database.
当在检索数据的过程中出现问题时,例如用数据库中不存在的标识符查找一个对象时,就会抛出这个异常。
For example, we’re going to use the JdbcTemplate class which has a method that throws this exception:
例如,我们要使用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
4.1.IncorrectResultSetColumnCountException
This exception subclass is thrown when attempting to retrieve multiple columns from a table without creating the proper RowMapper:
当试图从一个表中检索多列而不创建适当的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
4.2.IncorrectResultSizeDataAccessException
This exception is thrown when a number of retrieved records differs from expected one, for example when expecting a single Integer value, but retrieving two rows for the query:
当检索到的记录数量与预期的不同时,就会抛出这个异常,例如,当预期是一个单一的Integer值,但为查询检索了两行时。
@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
5.DataSourceLookupFailureException
This exception is thrown when a specified data source cannot be obtained. For the example, we will use the class JndiDataSourceLookup, to look for a nonexistent data source:
当指定的数据源不能被获取时,就会抛出这个异常。在这个例子中,我们将使用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
6.InvalidDataAccessResourceUsageException
This exception is thrown when a resource is accessed incorrectly, for example when a user lacks SELECT rights.
当一个资源被错误地访问时,例如当一个用户缺乏SELECT权限时,就会抛出这个异常。
In order to test this exception, we’ll need to revoke the SELECT right for the user, then run a SELECT query:
为了测试这个异常,我们需要撤销用户的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");
}
}
Notice that we are restoring the permission on the user in the finally block.
注意,我们在finally块中恢复了用户的权限。
6.1. BadSqlGrammarException
6.1.BadSqlGrammarException
A very common subtype of InvalidDataAccessResourceUsageException is BadSqlGrammarException, which is thrown when attempting to run a query with invalid SQL:
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);
}
Notice of course the fro – which is the invalid aspect of the query.
当然,请注意fro – ,这是查询中无效的方面。
7. CannotGetJdbcConnectionException
7、CannotGetJdbcConnectionException
This exception is thrown when a connection attempt through JDBC fails, for example when the database url is incorrect. If we write the url like the following:
当通过JDBC的连接尝试失败时,例如当数据库网址不正确时,就会抛出这个异常。如果我们把网址写成下面这样。
jdbc.url=jdbc:mysql:3306://localhost/spring_hibernate4_exceptions?createDatabaseIfNotExist=true
Then the CannotGetJdbcConnectionException will be thrown when attempting to execute a statement:
那么在试图执行一个语句时,将抛出CannotGetJdbcConnectionException。
@Test(expected = CannotGetJdbcConnectionException.class)
public void whenJdbcUrlIncorrect_thenCannotGetJdbcConnectionException() {
JdbcTemplate jdbcTemplate = new JdbcTemplate(restDataSource);
jdbcTemplate.execute("select * from foo");
}
8. Conclusion
8.结论
In this very to the point tutorial we had a look at some of the most common subtypes of the NonTransientDataAccessException class.
在这个非常有意义的教程中,我们看了NonTransientDataAccessException类的一些最常见的子类型。
The implementation of all examples can be found in the GitHub project. And of course all examples are using an in-memory database so you can easily run them without setting anything up.
所有例子的实现都可以在GitHub项目中找到。当然,所有的例子都是使用内存数据库,所以你可以轻松地运行它们,而无需设置任何东西。