目录
写在前面
一、什么是JdbcTemplate?
二、JdbcTemplate框架搭建
1、导入所需jar包
2、配置JDBC数据源
(1)、直接在中配置数据源
(2)、引入外部配置文件
3、配置JdbcTemplate对象
三、持久化层操作详解
1、增删改操作
2、批量增删改操作
3、查询单行数据
4、查询多行数据
5、查询单一指定数值
四、使用具名参数的JdbcTemplate
1、声明具名参数类
2、具名参数的普通使用
3、通过SqlParameterSource对象传入数值
五、自动装配JdbcTemplate并实现Dao
六、写在最后
写在前面
Hello,你好呀,我是灰小猿,一个超会写bug的程序猿!
用坚持缔造技术、用指尖敲动未来!愿我们每一次敲动键盘,都能让生活变得更智能、世界变得更有趣!
在使用Spring进行业务逻辑层处理时,你是否有想过,如此强大的Spring框架在对数据库相关的业务处理时,是否有更加便捷的操作呢?Spring框架又能将传统JDBC数据库的操作优化到什么样的程度呢?
今天我就来和大家一起探究一下针对JDBC数据库操作的一个轻量级框架—JdbcTemplate。教你一篇文掌握Spring JDBC框架的核心。
一、什么是JdbcTemplate?
Spring的JdbcTemplate可以被看作是一个小型的轻量级持久化层框架,为了使JDBC操作更加便捷,Spring在JDBC API上定义了一个抽象层,以此来建立了一个JDBC存取框架。
它作为Spring JDBC框架的核心,设计目的是为不同类型的JDBC操作提供模版方法,以至于通过这种方式,在尽可能保留灵活性的前提下,将数据库存取的工作量降低到最低。
现在对于什么是jdbcTemplate你应该比较了解了吧?那么接下来我就来和大家详细的聊一聊这个轻量级的框架是如何使用的。
二、JdbcTemplate框架搭建
使用JdbcTemplate进行数据库的相关操作是需要提前搭建好相关环境配置的。那么我们就先来讲一下如何在spring中配置JdbcTemplate。
1、导入所需jar包
我们知道平常在进行框架的搭建的时候都是需要依赖相关的Jar包来实现的。那么JdbcTemplate又需要哪些jar包呢?我给大家按照作用罗列并整理了出来,
①IOC容器所需要的JAR包
- commons-logging-1.1.1.jar
- spring-beans-4.0.0.RELEASE.jar
- spring-context-4.0.0.RELEASE.jar
- spring-core-4.0.0.RELEASE.jar
- spring-expression-4.0.0.RELEASE.jar
②JdbcTemplate所需要的JAR包
- spring-jdbc-4.0.0.RELEASE.jar
- spring-orm-4.0.0.RELEASE.jar
- spring-tx-4.0.0.RELEASE.jar
③数据库驱动和数据源
- c3p0-0.9.1.2.jar
- mysql-connector-java-5.1.7-bin.jar
以上这些jar包,包括SSM开发所需的所有jar包我给大家整理了出来,下载就能使用。
SSM框架Jar包下载
现在导入了所有所依赖的jar包,接下来就是利用这些资源搭建接下来的JdbcTemplate框架了,
2、配置JDBC数据源
既然是对数据库的操作,那么就一定是需要数据源的,我们以MySQL数据库为例进行数据源的配置操作,关于在IOC中对bean的赋值我之前也和大家讲过,所以我们可以直接在IOC容器中配置出数据源,连接到指定的数据库,这里需要借助CombopooledDataSource类,并在其中给user、password、jdbcurl、driverclass等这几个属性赋值。同时我们配置上连接池中的最大连接数量和最小连接数量(当然这两个属性也是可以不用配置的)。
在这里配置数据源对属性的赋值其实也有两种方式:
一种是直接将连接信息在<bean></bean>标签中写死。
第二种是将数据源的连接信息写在单独的一个文件中,然后引入外部配置文件,这里我将两种方法都介绍给大家:
(1)、直接在<bean></bean>中配置数据源
使用这种方法只需要直接在value中将属性的值写死就可以了,同时写入数据源的id,代码如下:
代码语言:javascript复制<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="root"/>
<property name="password" value="admin"/>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/jdbc_template"/>
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<property name="minPoolSize" value="5"/>
<property name="maxPoolSize" value="20"/>
</bean>
(2)、引入外部配置文件
第二种方式是引入外部带有数据源连接信息的配置文件,然后利用引入外部配置文件的标签将数据源信息引入进来,再利用${}表达式将数据值赋值给属性,使用这种方法的好处就是在数据源变更的时候方便更改变更信息,直接在数据源的文件中更新即可,不需要在IOC容器中更改代码。
这种方法需要我们首先建立数据源信息的配置文件,如jdbcconfig.properties,当然你还可以定义成其他名字,如“xxx.properties”。但是一般都要以“.properties”为文件后缀。文件中写入数据源信息:
代码语言:javascript复制jdbc.user=root
jdbc.password=ADMIN
jdbc.jdbcurl=jdbc:mysql://localhost:3306/jdbc_template
jdbc.driverClass=com.mysql.jdbc.Driver
在IOC容器中使用标签context:property-placeholder引入外部配置文件“jdbcconfig.properties”。
代码语言:javascript复制<!-- 添加外部配置文件 -->
<context:property-placeholder location="classpath:jdbcconfig.properties"/>
注意:这里的class表示类路径下的文件。
之后按照同样的方式在容器中<bean></bean>标签下配置数据源,但是现在赋值是使用“${}”获取到的jdbcconfig.properties中的配置数据。代码如下:
代码语言:javascript复制<!-- 设置数据库配置
在这里要注意:
$是用于读取配置文件中的信息
#是用于spring应用
-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="${jdbc.user}"></property>
<property name="password" value="${jdbc.password}"></property>
<property name="jdbcUrl" value="${jdbc.jdbcurl}"></property>
<property name="driverClass" value="${jdbc.driverClass}"></property>
</bean>
3、配置JdbcTemplate对象
在我们配置好数据源之后,就是配置JdbcTemplate对象了,由于JdbcTemplate对象只是一个JDBC的操作模版,因此它需要引入外部要操作的数据源。具体操作是在IOC中为JdbcTemplate类的dataSource属性赋予数据源。
代码如下:
代码语言:javascript复制<!-- 建立一个jdbcTemplate连接 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg name="dataSource" ref="dataSource"></constructor-arg>
</bean>
直到这里,JdbcTemplate这个“轻量级”框架才算搭建配置完成了,接下来就能正常使用JdbcTemplate进行数据库中的相关操作了,我们先来写一个测试语句分别测试一下在普通连接和使用JdbcTemplate连接的情况下,数据库连接是否正常:
代码语言:javascript复制public class JdbcTest {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
JdbcTemplate jdbcTemplate = context.getBean(JdbcTemplate.class);
// 通过普通方法来获取数据库连接
@Test
public void test() throws SQLException {
System.out.println("jdbc_template执行");
DataSource bean = context.getBean(DataSource.class);
Connection connection = bean.getConnection();
System.out.println("普通方法来获取数据库连接:" connection);
}
/**
* 通过jdbcTemplate来获取数据库连接
* 实验:测试数据源
* */
@Test
public void test01() {
System.out.println("jdbcTemplate来获取数据库连接:" jdbcTemplate);
}
}
运行出现如下信息,表示连接正常:
确认数据库连接正常之后,现在才是到了JdbcTemplate使用的核心部分,敲黑板!到重点咯!!!
三、持久化层操作详解
JdbcTemplate有专门的操作函数来实现不同的增删改查操作,接下来我将通过如下数据表“员工表employee”来给大家介绍一下他们的具体使用:
1、增删改操作
非常神奇的是,JdbcTemplate的增删改操作是使用同一个方法来完成的,即:
JdbcTemplate.update(String, Object...)
该方法最常用的有两个参数:
第一个参数String传入需要执行的SQL语句,
第二个参数Object...传入sql语句中需要带的参数,使用object...的意思就是后面可能不止一个参数。该方法会有一个int类型的返回值,表示有多少行数据被修改了,下面我通过一个实例来给大家演示一下;
例:将emp_id=5的记录的salary字段更新为1300.00 首先我们需要写出相应的sql语句,语句中需要传入参数的位置使用“?”表示,之后调用update方法来实现修改操作,并返回被修改的行数: /** 修改数据库的数据表中的数据 * 将emp_id=5的记录的salary字段更新为1300.00*/ // @Test public void test02() { String sql = "UPDATE employee SET salary=? WHERE emp_id=?"; int update = jdbcTemplate.update(sql, 1300.00, 5); System.out.println("更新成功!" update); }
以上是一个修改操作,对于删除和添加操作使用同样的方式即可。
2、批量增删改操作
上面是对于普通的单条数据的增删改操作,但是如果有大量的数据需要执行同一个操作呢?一个一个的来岂不是太麻烦了嘛?所以针对这一情况JdbcTemplate还特意提供了批量的增删改方法,方便我们对大量数据的操作。具体使用是这样的。
通过调用以下函数来实现:
JdbcTemplate.batchUpdate(String, List<Object[]>)
该方法会返回一个int类型的数组,数组中存放着每次执行sql语句所修改的行数。
其中的String仍然表示要执行的sql语句,
但是Object[]封装了SQL语句每一次执行时所需要的参数,而在List集合封装了SQL语句多次执行时的所有参数。
我们通过下面这个实例来验证这一方法的操作:
例:向employee表中批量插入数据 首先需要将sql语句写好,然后将需要传递的参数写入到list集合中,之后再将sql语句和list集合传入batchUpdate()方法即可。 /** * 批量插入数据 * */ @Test public void test03() { String sql = "INSERT INTO employee(emp_name,salary) VALUES(?,?)"; List<Object[]> batchArgs = new ArrayList<Object[]>(); batchArgs.add(new Object[]{"张三","999"}); batchArgs.add(new Object[]{"李四","1999"}); batchArgs.add(new Object[]{"王五","2999"}); int[] batchUpdate = jdbcTemplate.batchUpdate(sql, batchArgs); for (int i : batchUpdate) { System.out.println(i); } }
3、查询单行数据
上面我们了解了在jdbcTemplate中如何进行增删改操作,那么CRUD四兄弟怎么能少看查找这么重要的操作呢?这不它来了!!!
在jdbcTemplate中查询数据其实是十分简单的,但是他为什么不与其他三个操作共同使用同一个操作方法呢?
原因其实很简单,还不就是增删改操作会对数据表进行修改而返回int型的修改行数,而查询操作不会对数据表修改,同时返回其他类型的查询结果!
首先我们来看一下如何查询单行数据。在jdbcTemplate中查询单行数据所使用的函数是:
JdbcTemplate.queryForObject(String, RowMapper<Department>, Object...)
该方法的参数中String同样的表示要执行查找的sql语句,
但是这里有一个坑要注意:中间传递的参数 RowMapper<Department>这个是什么呢?其实这里值的是要传递需要返回的bean对象的类型,但是在进行真正的使用的时候我们并不是通过RowMapper<Department>来映射要返回的bean对象的,而是通过它的子类BeanPropertyRowMapper,他们的继承关心是这样的:
在使用BeanPropertyRowMapper映射所返回的bean对象时,能够找到该对象并映射成功则返回,如果找不到就报错。
第三个参数object...还是表示传入的查询参数。
下面看这样一个实例你就明白了。
例:查询emp_id=5的数据库记录,封装为一个Java对象返回。 /** * 查询数据库中的单条数据 * 实验4:查询emp_id=5的数据库记录,封装为一个Java对象返回 * 创建的javabean中的字段要和数据表中的字段名一样,否则就需要进行映射 * 查询单条数据使用 queryForObject,但是中间需要使用BeanPropertyRowMapper映射需要生成的bean对象 * 在查找不到的时候会报错 * * */ @Test public void test04() { String sql = "SELECT * FROM employee WHERE emp_id=?"; Employee employee = null; try { employee = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<Employee>(Employee.class),5); } catch (Exception e) { // TODO: handle exception } System.out.println(employee); }
4、查询多行数据
与查询单行数据不同,查询多行数据需要使用的方法是:
JdbcTemplate.query(String, RowMapper<Department>, Object...)
但是其中所传递的参数是一样的,唯一不同是该方法返回的是一个数组列表,其中包含了查询到的每一条数据。
如下面这个实例:
例:查询salary>4000的数据库记录,封装为List集合返回。 /** * 查询数据库中的多条数据 * 实验5:查询salary>4000的数据库记录,封装为List集合返回 * */ @Test public void test05() { String sql = "SELECT * FROM employee WHERE salary>?"; List<Employee> employees = jdbcTemplate.query(sql, new BeanPropertyRowMapper<Employee>(Employee.class),4000); for (Employee employee : employees) { System.out.println(employee); } }
5、查询单一指定数值
现在我们知道了如何查询单条数据,也知道了如何查询多条数据,但是这些数据返回的都是成行的数据,假如说我们只想得到某一行的数据呢?
那也好办。jdbcTemplate有一个专门的方法用来返回需要查询单一数值。
JdbcTemplate.queryForObject(String, Class, Object...)
该方法中有一个返回值是class,它表示要返回的数据的类型,比如是int类型还是double类型。同时方法返回查询到的该数值。
如下面这里实例:
例:查询employee表中最大的salary。 该方法很显然是返回一个具体的数值,而且还是没有参数的,那么我们在进行参数的传递的时候就不需要传递后面的object...类型参数。 /** * 查询数据表中的数据,但是只返回一个数值 * 实验6:查询最大salary * */ @Test public void test06() { String sql = "SELECT MAX(salary) FROM employee"; Double quDouble = jdbcTemplate.queryForObject(sql, Double.class); System.out.println(quDouble); }
以上就是使用jdbcTemplate实现不同增删改查操作的全部方法了,但是操作jdbcTemplate还有一种方式,就是将sql语句中的“?”用具体的参数来表示。接下来我们来介绍一下这种方式执行sql语句。
四、使用具名参数的JdbcTemplate
接下来要介绍的这个JdbcTemplate的操作方式与上面的有一点不太一样,这里使用了一个具名参数来表示sql语句中需要传入的参数,那么什么是具名参数呢?
具名参数:指具有名字的参数,参数不再是占位符,而是一个变量名 语法格式:“:参数名”
使用该具名参数之后,spring会自动的从传入的参数中查找具有相应名称的参数,并将它的值赋值给sql语句。
而Spring有一个支持具名参数功能的jdbcTemplate,即NamedParameterJdbcTemplate类,在在Spring中可以通过NamedParameterJdbcTemplate类的对象使用带有具名参数的SQL语句。
1、声明具名参数类
使用NamedParameterJdbcTemplate类的方式与普通的JdbcTemplate类似,都需要在ioc中声明,如下所示:
代码语言:javascript复制<!-- 建立一个带有具名参数支持的jdbcTemplate -->
<bean id="namedParameterJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
<constructor-arg name="dataSource" ref="dataSource"></constructor-arg>
</bean>
2、具名参数的普通使用
我们以插入语句为例,来演示一下具名参数的使用,
传统的sql语句是这样的:
代码语言:javascript复制INSERT INTO employee(emp_name,salary) values(?,?)
使用具名参数的sql语句是这样的;
代码语言:javascript复制INSERT INTO employee(emp_name,salary) values(:emp_name,:salary)
如下面这个实例:
例:使用带有具名参数的SQL语句插入一条员工记录,并以Map形式传入参数值。 /** * 实验7:使用带有具名参数的SQL语句插入一条员工记录,并以Map形式传入参数值 * 占位符查参数:?的顺序千万不能错,传参的时候一定要注意 * */ @Test public void test07() { String sql = "INSERT INTO employee(emp_name,salary) values(:emp_name,:salary)"; Map<String, Object> paramMap = new HashMap<String, Object>(); paramMap.put("emp_name", "赵六"); paramMap.put("salary", 998.12); int updateNum = jdbcTemplate2.update(sql, paramMap); System.out.println(updateNum); }
这里有一点需要注意的是:无论是使用普通的sql语句、还是使用带具名参数的sql语句。传入的参数的顺序都需要和sql语句中参数的顺序一致,否则就会出现参数调用错误,这一点一定需要注意!
3、通过SqlParameterSource对象传入数值
通过SqlParameterSource对象传入数值其实也就是需要将参数以javabean的形式传入,但是又有了需要注意的地方。
注意:在使用sqlParmeterSource进行数据库中数据装填的时候,一定要注意values后面的参数名称和bean中的参数名称对应 否则就会报如下错误: No value supplied for the SQL parameter 'emp_Name': Invalid property 'emp_Name' of bean class [com.spring.beans.Employee]: Bean property 'emp_Name' is not readable or has an invalid getter method:
下面以一个实例来说明通过SqlParameterSource对象传入参数。
例:使用带有具名参数的SQL语句插入一条员工记录,通过SqlParameterSource对象传入参数。 /** * 实验8:重复实验7,以SqlParameterSource形式传入参数值 * */ @Test public void test08() { String sql = "INSERT INTO employee(emp_name,salary) values(:emp_name,:salary)"; Employee employee = new Employee(); employee.setEmp_name("吴九"); employee.setSalary(997.7); int updateNum = jdbcTemplate2.update(sql, new BeanPropertySqlParameterSource(employee)); System.out.println(updateNum); }
五、自动装配JdbcTemplate并实现Dao
由于JdbcTemplate类是线程安全的,所以可以在IOC容器中声明它的单个实例,并将这个实例注入到所有的Dao实例中,在Dao类中将JdbcTemplate实现自动装配。并在其中实现增删改查方法,通过自动装配的jdbcTemplate可以在Dao中减少代码的操作,更加轻松的实现增删改查操作。
通过该方法自动装配JdbcTemplate并实现Dao的步骤我给大家总结了出来:
- 建立dao类
- 书写其中的方法
- 利用包扫描将其自动装配
- 从IOC容器中获取dao类
- 实现其中响应的数据库操作的方法
下面通过实例进行验证。
例:创建BookDao,自动装配JdbcTemplate对象,并实现一个添加添加操作。 在Dao类中,我们使用@Autowired注解自动装配jdbcTemplate,并实现一个数据添加的方法: @Repository public class EmployeeDao { // 将jdbcTemplate自动注入 @Autowired JdbcTemplate jdbcTemplate; /** * 保存数据到数据表 * */ public int saveEmployee(Employee employee) { String sql = "insert into employee(emp_name,salary) values(?,?)"; return jdbcTemplate.update(sql, employee.getEmp_name(),employee.getSalary()); } }
使用测试方法进行测试:
代码语言:javascript复制 /**
* 实验9:创建BookDao,自动装配JdbcTemplate对象
* */
@Test
public void test09() {
Employee employee = new Employee();
employee.setEmp_name("王八");
employee.setSalary(888.7);
int saveEmployeeNum = employeeDao.saveEmployee(employee);
System.out.println(saveEmployeeNum);
}
这样通过自动装配JdbcTemplate并实现Dao的工作就完成了,这种方式避免了重复的创建jdbcTemplate,而且减少了代码量。
六、写在最后
叮叮!到这里,Spring的JdbcTemplate框架全部的操作使用就跟大家讲解完毕了,
其中包括从普通的JdbcTemplate搭建,到实现简单的CURD、再到复杂的具名参数。希望小伙伴们通过这一篇文章就能掌握JdbcTemplate的使用教程。同时在学习过程中有遇到不理解或者不会的地方,欢迎留言提出,我们一起学习!
再先进的技术都需要一键一键的敲出来,奋斗吧!致奔波在Java道路上的每一位“创造者”!
我是灰小猿,我们下期见!