热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

开发笔记:Spring中使用JDBC

篇首语:本文由编程笔记#小编为大家整理,主要介绍了Spring中使用JDBC相关的知识,希望对你有一定的参考价值。Spring中的数据库异常体系

篇首语:本文由编程笔记#小编为大家整理,主要介绍了Spring中使用JDBC相关的知识,希望对你有一定的参考价值。



Spring中的数据库异常体系

使用JDBC(不使用Spring)的时候,我们需要强制捕获SQLException,否则无法使用JDBC处理任何事情。SQLException表示尝试访问数据库的时候出现问题,但是这个异常却没有告诉我们哪里出错以及如何处理。可能出现SQLException的情况有:



  • 应用程序无法连接数据库

  • 查询的SQL有问题

  • 查询中的表,列不存在

  • 尝试插入或更新的数据违法数据库的约束

还有其他的数据库有关的异常,但是真正抛出SQLException的时候,我们没有办法准确的定位,只有靠经验与猜测去处理。而且抛出SQLException意味着出现致命性的错误,程序也没有办法继续处理。

一些持久层框架都有相对丰富的异常体系,例如Hibernate有二十几左右的异常,分别对应特定的数据访问问题。这样就可以针对特定的异常编写catch代码块。但是,这种Hibernate的异常是与对应的框架相对应的,我们如果希望特定的持久框架独立于数据访问层。如果我们将这些Hibernate的异常抛出去,那么我们对Hibernate的使用将渗透到其他层。如果不这样做,就需要将这些特定的异常捕获然后将其转换为与平台无关的异常再次处理。

一方面,JDBC的异常过于简单,而Hibernate的异常体系又是与其平台有关的。Spring 针对这个问题提供了多个数据访问异常,Spring的异常体系并没有与特定持久方法相关联,这样我们就不用关心所选择的持久化方案。这有助于我们将所选择的具体持久化技术与数据访问层隔离开。而且Spring的数据访问异常都继承于DataAccessException,这是一个非检查异常,也就是说没有必要捕获Spriing这些数据访问异常(如果想捕获也是完全可以的)。


第一步 配置数据源

Spring的模板类处理数据访问层的国定部分——事务控制,管理控制以及处理异常。同时,应用程序相关的数据访问——语句,绑定参数以及真理数据集需要我们自己处理。针对不同的持久化平台,Spring提供了可选的模板,如果使用JDBC就选择JdbcTemplate,如果使用对象关系映射框架,那么可以使用HibernateTemplcate或JpaTemplcate。

但首先要说明的是Spring所支持的持久功能都需要依赖数据源。所以不要忘记配置数据源,并将其作为第一步(建议使用数据库连接池或者JNDI的方式,如果有可能使用Spring的profile也是极好的)。


@Bean
public DataSource dataSource() {
BasicDataSource dataSource
= new BasicDataSource();
dataSource.setUrl(
"jdbc:mysql:///crud");
dataSource.setUsername(
"root");
dataSource.setPassword(
"root");
dataSource.setDriverClassName(
"com.mysql.jdbc.Driver");
return dataSource;
}


第二步 在Spring中使用JDBC

JDBC是建立在SQL之上的,而SQL本身就是数据库访问语言,此外,与其他的技术相比,直接使用JDBC可以更好对数据库进行调优,JDBC允许使用数据库的所有特性,而这是其他框架不鼓励甚至是禁止的。相对于其他的持久层框架,JDBC能够让我们在更底层上处理数据,我们完全可以控制应用程序如何读取和管理数据,这是一种细粒度的数据访问方式。


使用JDBC模板

Spring的JDBc模板承担了资源管理和异常处理的工作,从而简化了JDBC代码,将数据访问的样板代码抽象到模板类中,Spring为JDBC提供了三个JDBC模版类:



  • JdbcTemplate:最基本的Spring JDBC模板类,支持基于索引参数(?)的查询。

  • NamedParameterJdbcTemplate:使用该模板类执行查询的时候使用命名参数的方式绑定到SQL,而不是用索引参数。

  • SimpleJdbcTemplate:Spring3.1之后已弃用

只有我们需要使用命名参数的时候,才使用NamedParameterJdbcTemplate,对于的大多数JDBC任务使用JdbcTemplate就是最好的方案。为了JdbcTemplate可以正常工作,只需要为其配置DataSource:


@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}

然后,我们就可以将JdbcTemplate装配到Repository中了。


@Repository
public class JdbcRepository {

@Autowired
private JdbcOperations jdbcOperations;

这里使用的是 JdbcOperations ,JdbcOperations接口定义了JdbcTemplate模板类所实现的方法,使用接口而不是具体的某一个JDBC模板类,保证松耦合。这里使用Spring的@AutoWired,其实使用@Inject作也可以,只不过后者是Java的注入规范中的注解。

使用模板类之后所有的样板代码隐藏到JDBC模板类中,并且也不用对SQLException进行处理,在内部,JdbcTemplate将会捕获说有可能抛出的SQlException,并将其转换为Spring中通用的数据访问异常,然后将其重新抛出。


使用JdbcTemplate读取数据

JdbcTemplate中有众多query...()的方法用于读取数据,但是对于需要将返回结果封装为对象的操作,需要有一些特殊处理。这个对象需要实现RowMapper接口,对于查询所返回的每一行数据,JdbcTemplate将会调用RowMapper的mapRow方法,并传入一个ResultSet和包含行号的整数。


private static final class SpitterRowMapper implements RowMapper {
public Spitter mapRow(ResultSet rs, int rowNum) throws SQLException {
//这段代码摘自书本
long id = rs.getLong("id");
String username
= rs.getString("username");
String password
= rs.getString("password");
String fullName
= rs.getString("fullname");
String email
= rs.getString("email");
boolean updateByEmail = rs.getBoolean("updateByEmail");
return new Spitter(id, username, password, fullName, email, updateByEmail);
}
}

因为RowMapper接口中只有一个mapRow方法,它完全符合函数式接口的标准。这意味着使用Java8来开发应用的化可以使用Lambda表达式,而不必使用具体的实现类了。或者使用Java8的方法引用,在单独的方法中定义映射规则:


public Dept findOne(Integer deptId) {
return jdbcOperations.queryForObject(SELECT_SQL, this::mapDept,deptId);
}

private Dept mapDept(ResultSet rs,int row)throws SQLException {
return new Dept(rs.getInt("dept_id"),rs.getString("dept_name"));
}

但是,不论使用Lambda表达式还是方法引用,都需要保证接受与mapRow相同的参数。


使用命名参数

使用索引参数的时候,需要注意参数的顺序,在将值传递给繁华的是否需要保证正确的顺序。如果在修改SQL时改变了参数的顺序,那我们还需要修改参数值的顺序。而我们使用命名参数,命名参数可以给SQL中的每一个参数一个明确的名字,在绑定值得时候通过名字来引用参数。


private static final String SQL_INSERT_SPITTER="insert into spitter(username,password,fullname)"+"values(:username,:password,:fullname)";

使用命名参数查询,绑定值得顺序就不重要了,如果SQL改变导致参数顺序与之前不一致,我们不需要修改绑定的代码。

NamedParameterJdbcTemplate是一个特殊得JDBC模板类,它使用命名参数。NamedParameterJdbcTemplate得用法与JdbcTemplate一致:


@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new NamedParameterJdbcTemplate(dataSource);
}

然后,就开始在Repository中使用吧:


public void addSpitter(Spitter spitter){
Map
map=new HashMap();
map.put(
"username",spitter.getUsername());
map.put(
"password",spitter.getPassword());
map.put(
"username",spitter.getFullName());

jdbcOperations.update(SQL_INSERT_SPITTER, map);
}

因为命名参数需要通过java.util.Map进行绑定,所以需要将参数塞进Map中。


使用事务

因为采用JavaConfig得方式配置Spring,所以对于事务得处理也需要通过Java代码的方式来声明,至于使用,还是与XML得方式一样来使用即可,先来回顾一下XML中配置事务的方式(使用事务注解,而不是AOP配置事务):



  1. 与平台相关的事务管理器

  2. 开启事务注解驱动:

  3. 在需要事务的方法上使用@Transactional

Java代码的方式也是按照这个步骤去进行的,首先,我们配置事务管理器,JDBC和MyBatis都是使用数据源的事务管理(DataSourceTransactionManager),Hibernate和JPA使用分别各自的事务管理器(HibernateTransactionManager, JpaTransactionManager)。 因为这里使用JDBC就用DataSourceTransactionManager了


//注册事务管理器在容器中
@Bean
public PlatformTransactionManager transactionManager() throws Exception{
return new DataSourceTransactionManager(dataSource());
}

需要将数据源交给事务管理器,这样管理器可以控制commit或rollback

接下来在配置类上启用 @EnableTransactionManagement 表示开启事务注解驱动


@EnableTransactionManagement
@ComponentScan(
"cn.lynu")
@Configuration
public class TxConfig {

最后在需要事务的方法上使用@Transactional注解即可,使用方法与XML的配置没有什么不同。

 


推荐阅读
  • r2dbc配置多数据源
    R2dbc配置多数据源问题根据官网配置r2dbc连接mysql多数据源所遇到的问题pom配置可以参考官网,不过我这样配置会报错我并没有这样配置将以下内容添加到pom.xml文件d ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • 解决.net项目中未注册“microsoft.ACE.oledb.12.0”提供程序的方法
    在开发.net项目中,通过microsoft.ACE.oledb读取excel文件信息时,报错“未在本地计算机上注册“microsoft.ACE.oledb.12.0”提供程序”。本文提供了解决这个问题的方法,包括错误描述和代码示例。通过注册提供程序和修改连接字符串,可以成功读取excel文件信息。 ... [详细]
  • 背景应用安全领域,各类攻击长久以来都危害着互联网上的应用,在web应用安全风险中,各类注入、跨站等攻击仍然占据着较前的位置。WAF(Web应用防火墙)正是为防御和阻断这类攻击而存在 ... [详细]
  • 本文整理了Java面试中常见的问题及相关概念的解析,包括HashMap中为什么重写equals还要重写hashcode、map的分类和常见情况、final关键字的用法、Synchronized和lock的区别、volatile的介绍、Syncronized锁的作用、构造函数和构造函数重载的概念、方法覆盖和方法重载的区别、反射获取和设置对象私有字段的值的方法、通过反射创建对象的方式以及内部类的详解。 ... [详细]
  • Whatsthedifferencebetweento_aandto_ary?to_a和to_ary有什么区别? ... [详细]
  • Week04面向对象设计与继承学习总结及作业要求
    本文总结了Week04面向对象设计与继承的重要知识点,包括对象、类、封装性、静态属性、静态方法、重载、继承和多态等。同时,还介绍了私有构造函数在类外部无法被调用、static不能访问非静态属性以及该类实例可以共享类里的static属性等内容。此外,还提到了作业要求,包括讲述一个在网上商城购物或在班级博客进行学习的故事,并使用Markdown的加粗标记和语句块标记标注关键名词和动词。最后,还提到了参考资料中关于UML类图如何绘制的范例。 ... [详细]
author-avatar
路侑华
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有