源码解析Spring 数据库异常抽象知识点总结
异常抽象
在Java应用中处理数据库操作时,经常会出现各种数据库异常,例如连接超时、SQL语法错误等。这些异常信息通常是非常繁琐和冗长的,不利于开发者理解和处理异常。Spring提供了丰富的异常抽象支持,可以有效地降低程序员处理异常的复杂度,提升开发效率。
Spring 提供了以下几种异常:
DataAccessException
所有与数据访问、SQL仓库和JDBC相关的异常都继承DataAccessException。DataAccessException可分为以下两类:
-
NonTransientDataAccessExcpetion:不可恢复的数据访问异常,例如:SQL语法错误、表不存在等。
-
TransientDataAccessException:可恢复的数据访问异常,例如:数据库连接超时、死锁等。
DataAccessResourceFailureException
该异常继承自NonTransientDataAccessException,是由于媒介资源(如数据库)无法打开或获得连接而导致的异常。该异常通常表现为一系列连接或登录失败异常,操作中断。
DataIntegrityViolationExcetion
该异常继承自DataAccessException,反映了数据访问层的完整性失败。
JdbcUpdateAffectedIncorrectNumberOfRowsException
当sql更新时,影响的行不符合预期时,抛出该异常。
Spring中的异常处理
Spring使用异常体系统一异常处理,通过编写AOP环绕通知来捕捉异常并将其转换为Spring期望的异常体系。
AOP环绕通知的代码如下:
public class ExceptionHandlerAspect {
@Around("execution(* com.example.demo.service..*.*(..))")
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
try {
return pjp.proceed();
} catch (SQLException e) {
throw new DataAccessResourceFailureException("SQLException", e);
} catch (DataAccessException e) {
throw new MyDataAccessException(e);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
在 AOP 环绕通知中,如果方法调用抛出 SQLException 或 DataAccessException,则将 SQLException 转换为 DataAccessResourceFailureException,将 DataAccessException 转换为 MyDataAccessException,并将其他异常转换为 RuntimeException。
MyDataAccessException 的实现如下:
public class MyDataAccessException extends UncategorizedDataAccessException {
public MyDataAccessException(SQLException ex) {
super(ex.getMessage(), ex);
}
}
该类继承了Spring的UncategorizedDataAccessException,可把非DataAccessException类的异常转换为Spring期望的异常类型。
示例
示例1:使用Spring JdbcTemplate访问数据库
在Spring中,JdbcTemplate是最常用的JDBC访问模板。我们可以在异常抽象中利用JdbcTemplate的异常处理来处理数据访问异常。
@Service("userService")
public class UserServiceImpl implements UserService {
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public void addUser(User user) {
String sql = "insert into user(name, age) values(?, ?)";
try {
jdbcTemplate.update(sql, user.getName(), user.getAge());
} catch (DataAccessException e) {
throw new MyDataAccessException(e);
}
}
@Override
public List<User> getUsers() {
String sql = "select * from user";
try {
return jdbcTemplate.query(sql, new UserMapper());
} catch (DataAccessException e) {
throw new MyDataAccessException(e);
}
}
}
在 addUser 和 getUsers 方法中,我们利用 try/catch 块捕获了 DataAccessException 异常。如果抛出了 DataAccessException 异常,我们使用 MyDataAccessException 将其转换为 Spring 期望的异常类型,以提供更好的异常处理和控制。
示例2:使用Hibernate访问数据库
在Hibernate中,使用JPA操作数据库是很常见的。我们同样可以利用上面提到的异常处理机制来处理Hibernate的异常。
@Transactional
@Repository
public class UserDaoImpl implements UserDao {
@Autowired
private EntityManager entityManager;
@Override
public List<User> getUsers() {
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<User> criteria = builder.createQuery(User.class);
Root<User> root = criteria.from(User.class);
criteria.select(root);
List<User> result = new ArrayList<>();
try {
result.addAll(entityManager.createQuery(criteria).getResultList());
} catch (Exception e) {
throw new MyDataAccessException(e);
}
return result;
}
@Override
public void addUser(User user) {
try {
entityManager.persist(user);
} catch (Exception e) {
throw new MyDataAccessException(e);
}
}
}
我们同样利用上面提到的 try/catch 块来捕获异常,并将异常转换为 MyDataAccessException,以提供更好的异常处理和控制。
以上就是Spring数据库异常抽象的知识点总结,希望对您有所帮助。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:源码解析Spring 数据库异常抽理知识点总结 - Python技术站