JDBC Template是基于JDBC的基础上产生的,所以在讲JDBC Template之前,先聊聊 JDBC ?


什么是JDBC ?

JDBC(Java DataBase Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。

简单点说,JDBC API是JAVA提供的一套统一访问数据库的接口,而这些接口的具体实现是由各个数据库厂商通过JDBC驱动(就是我们连接数据库是导入的那个jar包)这种方式提供的。


JDBC Template 简介

由于,直接基于JDBC API的编程,重复性代码量大,操作繁琐。Spring对数据库的操作在JDBC API中提供的功能上进行简单的封装,Spring IoC容器将管理数据库连接的DataSource数据源当作普通的Java Bean进行管理,然后将DataSource注入到JdbcTemplate封装类中。

<!--配置数据源-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="driverClassName" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/jdbc_template?characterEncoding=utf-8"/><property name="username" value="root"/><property name="password" value="root"/>
</bean><!--配置JDBC Template组件提供的工具类对象,并注入dataSource数据源-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource"/>
</bean>

Spring对JDBC API进行封装(JDBC Template)后,提供一些更为简洁方便的方法。所以在进行开发的时候,我们就直接使用JDBC Template中提供的工具类或工具方法来进行数据的操作,不再是直接基于JDBC API来进行操作了,从而简化我们操作,使我们的快发更加便捷。


那JDBC Template到底是什么?

  • JDBC Template 是Spring的一个组件,是Spring为简化持久化操作提供的

  • JDBC Template 是在JDBC API的基础上完成的,Template译为模板,通俗点说,JDBC Template 就是Spring对JDBC的封装的模板

  • JDBC Template 提供了统一的模板方法,在保留代码灵活性的基础上,尽量减少持久化操作中的重复性代码。

下面的两段代码,它们实现的功能是一样的,但通过JDBC Template方式明显要简便很多


谈谈JDBC Template做了什么?

从传统 JDBC 编程详解一文中,我们可以看出,JDBC每次执行操作时,都需要进行数据库连接,创建Statement对象,处理SQL语句,处理结果集,关闭数据库这些操作;甚至有时还可能出现数据库忘记关闭导致连接被占用

但在JDBC Template中,这些都无需我们考虑,Spring都已经为我们封装好了,只需在Spring配置文件中将数据源注入到JdbcTemplate封装类中,就可以通过JdbcTemplate对象调用相应的方法执行操作即可。操作数据库结束后,也无需关注数据库关闭问题



接下来,我们从功能上来了解一下JdbcTemplate提供的各类方法

数据库表结构

pom引入下面相关jar

Spring配置

  • 数据源
  • JdbcTemplate
<!--配置数据源-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="driverClassName" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/jdbc_template?characterEncoding=utf-8"/><property name="username" value="root"/><property name="password" value="root"/>
</bean><!--配置jdbc template组件提供的工具类,并注入数据源-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource"/>
</bean><!--自动扫描-->
<context:component-scan base-package="com.cd4356.jdbc_template"/>


JdbcTemplate作为一个工具类,它提供的简化持久化操作的功能是通过方法来呈现的,JdbcTemplate主要提供以下五类方法:

  • execute方法,可以用来执行任何sql语句,但在实际开发中,我们通常是使用它来执行DDL(数据定义语言)语句,比如通过create、drop、alter此类关键字来完成的操作。所以在实际应用中,该方法比较少用

  • update 和 batchUpdate方法,用来执行增删改操作

  • query 和 queryXXX方法,用来执行查询操作


execute方法

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class demo {@Autowiredprivate JdbcTemplate jdbcTemplate;@Testpublic void testExecute(){//通过jdbcTemplate的execute方法执行DDL类型语句,创建一个user表jdbcTemplate.execute("create table user(id int,name varchar(20))");}
}


预编译SQL语句,参数采用占位符?进行填充

以Object[]数组 或 不定项参数方式给预编译的SQL语句传值填充占位符

不定项参数,不管是在update方法中,还是在后面的query方法中,它一定是放在参数列表的最后一个位置

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class demo {@Autowiredprivate JdbcTemplate jdbcTemplate;@Testpublic void testUpdate1(){String sql = "insert into student(name,sex,born) values(?,?,?)";jdbcTemplate.update(sql,new Object[]{"李钦","男", "1998-12-05"});}@Testpublic void testUpdate2(){String sql = "update student set sex=?,born=? where id=?";jdbcTemplate.update(sql,"女","1998-11-02",2);}
}


批量操作方法根据传入的参数不同,又可分为非同构批量操作 和 同构批量操作

  • 非同构批量操作,传入的参数是一个String类型的数组,数组元素是不同结构的SQL语句
  • 同构批量操作,传入两个参数,第一个参数是SQL语句;第二个参数是元素为Object[]数组类型的List集合
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class demo {@Autowiredprivate JdbcTemplate jdbcTemplate;//非同构批量操作@Testpublic void testBatchUpdate1(){String[] sqls = {"insert into student(name,sex,born) values('赖红','男','1985-6-19')","insert into student(name,sex,born) values('宋晓青','女','1990-2-14')","update student set name='李青',sex='女' where id=1"};jdbcTemplate.batchUpdate(sqls);}//同构批量操作@Testpublic void testBatchUpdate2(){String sql = "insert into student(name,sex,born) values(?,?,?)";List list = new ArrayList<Object>();list.add(new Object[]{"张运生","男","1982-3-12"});list.add(new Object[]{"耿易","男","1987-12-04"});jdbcTemplate.batchUpdate(sql,list);}
}

在实际应用中,查询操作使用的频率是远远高于增删改的,并且查询操作又特别灵活,形式多种多样,所以JDBC Template对查询的设置是非常细致的。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class demo {@Autowiredprivate JdbcTemplate jdbcTemplate;//==========================获取一个简单数据项==========================@Testpublic void testQueryForObject1(){String sql = "select count(*) from student";int count = jdbcTemplate.queryForObject(sql,Integer.class);System.out.println(count);}@Testpublic void testQueryForObject2(){String sql = "select name from student where id=? and sex=?";String name = jdbcTemplate.queryForObject(sql,new Object[]{2,"男"},String.class);System.out.println(name);}@Testpublic void testQueryForObject3(){String sql = "select name from student where id=? and sex=?";String name = jdbcTemplate.queryForObject(sql,String.class,2,"男");System.out.println(name);}//==========================获取多个简单数据项==========================@Testpublic void testQueryForList1(){String sql = "select name from student";List<Object> names = (List) jdbcTemplate.queryForList(sql,Object.class);System.out.println(names);}@Testpublic void testQueryForList2(){String sql = "select name from student where sex=? and id<?";List<Object> names = (List) jdbcTemplate.queryForList(sql,new Object[]{"女",5},Object.class);System.out.println(names);}@Testpublic void testQueryForList3(){String sql = "select name from student where sex=? and id<?";List<Object> names = (List) jdbcTemplate.queryForList(sql,Object.class,"女",5);System.out.println(names);}
}

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class demo {@Autowiredprivate JdbcTemplate jdbcTemplate;//=============================获取一个对象=============================@Testpublic void testQueryForMap(){String sql = "select * from student where id=?";Map<String, Object> map = jdbcTemplate.queryForMap(sql,2);System.out.println(map);}//=============================获取多个对象=============================@Testpublic void testQueryForList(){String sql = "select * from student";List<Map<String, Object>> list = jdbcTemplate.queryForList(sql);System.out.println(list);}
}

在student数据库表中,每一条数据代表一个学生;而在java中,定义一个Student类,一个Student类型的对象代表一个学生。

在进行持久化操作的时候,从数据库的student表中查询出来的记录,每一条记录都转化成一个Student对象来供我们使用。而在转化的过程中,student表的各个字段和Student类的各个属性之间(字段名和属性名需一致),是怎么一一对应的,它们的映射关系是怎么实现的。

JDBC Template通过RowMapper接口实现字段和属性之间的映射

先定一个User实体类

package com.cd4356.jdbc_template.entity;import java.util.Date;public class Student {private int id;private String name;private String sex;private Date born;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public Date getBorn() {return born;}public void setBorn(Date born) {this.born = born;}@Overridepublic String toString() {return "Student{ id="+id+", name="+name+", sex="+sex+", born="+born+'}';}
}

定义一个私有内部类实现RowMapper接口,并重写mapRow方法。mapRow方法将ResultSet结果集暴露出来,我们可以直接进行访问ResultSet结果集。然后在mapRow方法中可以使用JDBC的那种方式,让字段和属性进行映射。接着在query或queryForObject方法中传入该实现了RowMapper接口的类对象(RowMapper类型对象)

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class demo {@Autowiredprivate JdbcTemplate jdbcTemplate;//=============================获取一个对象=============================@Testpublic void testQueryForObject(){String sql = "select*from student where id=?";Student student = jdbcTemplate.queryForObject(sql, new StudentRowMapper(),2);System.out.println(student);}//=============================获取多个对象=============================@Testpublic void testQuery(){String sql = "select*from student";/*** query方法的返回值是一个List集合,集合元素是Student对象*/List<Student> list = jdbcTemplate.query(sql, new StudentRowMapper());System.out.println(list);}//定义一个私有类实现RowMapper接口private class StudentRowMapper implements RowMapper<Student>{public Student mapRow(ResultSet resultSet, int i) throws SQLException {Student student = new Student();/*** 注意从数据库取值的时候,实体类属性名和数据库表的字段名需一一对应*/student.setId(resultSet.getInt("id"));student.setName(resultSet.getString("name"));student.setSex(resultSet.getString("sex"));student.setBorn(resultSet.getDate("born"));return student;}}
}

当然你也可以通过匿名内部类的方式,直接在query或queryForObject方法中使用该RowMapper接口对象,但这样很繁琐且不易维护

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class demo {@Autowiredprivate JdbcTemplate jdbcTemplate;//=============================获取一个对象=============================@Testpublic void testQueryForObject(){String sql = "select*from student where id=?";Student student = jdbcTemplate.queryForObject(sql, new RowMapper<Student>() {public Student mapRow(ResultSet resultSet, int i) throws SQLException {Student student = new Student();/*** 注意从数据库取值的时候,实体类属性名和数据库表的字段名需一一对应* 让属性和字段进行映射*/student.setId(resultSet.getInt("id"));student.setName(resultSet.getString("name"));student.setSex(resultSet.getString("sex"));student.setBorn(resultSet.getDate("born"));return student;}},2);System.out.println(student);}//=============================获取多个对象=============================@Testpublic void testQuery(){String sql = "select*from student";/*** query方法的返回值是一个List集合,集合元素是Student对象*/List<Student> list = jdbcTemplate.query(sql, new RowMapper<Student>() {public Student mapRow(ResultSet resultSet, int i) throws SQLException {Student student = new Student();/*** 注意从数据库取值的时候,实体类属性名和数据库表的字段名需一一对应*/student.setId(resultSet.getInt("id"));student.setName(resultSet.getString("name"));student.setSex(resultSet.getString("sex"));student.setBorn(resultSet.getDate("born"));return student;}});System.out.println(list);}
}


前面,从功能上来了解了JdbcTemplate提供的各类方法。那么在实际项目开发中,若想使用Jdbc Template来封装它的持久层,从结构上,应该怎么设置


定义实体类

package com.cd4356.jdbc_template.entity;import java.util.Date;public class Student {private int id;private String name;private String sex;private Date born;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public Date getBorn() {return born;}public void setBorn(Date born) {this.born = born;}@Overridepublic String toString() {return "Student{ id="+id+", name="+name+", sex="+sex+", born="+born+'}';}
}

定义dao接口

package com.cd4356.jdbc_template.dao;import com.cd4356.jdbc_template.entity.Student;import java.util.List;public interface StudentDao {void insert(Student student);void delete(int id);void update(Student student);Student select(int id);List<Student> selectAll();
}

实现dao接口,注入JdbcTemplate实例对象,并声明RowMapper

package com.cd4356.jdbc_template.dao;import com.cd4356.jdbc_template.entity.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;@Repository
public class StudentDaoImpl implements StudentDao{//注入JdbcTemplate@Autowiredprivate JdbcTemplate jdbcTemplate;public void insert(Student student) {String sql = "insert into student(name,sex,born) values(?,?,?)";jdbcTemplate.update(sql,student.getName(),student.getSex(),student.getBorn());}public void delete(int id) {String sql = "delete from student where id=?";jdbcTemplate.update(sql,id);}public void update(Student student) {String sql = "update student set name=?,sex=?,born=? where id=?";jdbcTemplate.update(sql,student.getName(),student.getSex(),student.getBorn(),student.getId());}public Student select(int id) {String sql = "select*from student where id=?";return jdbcTemplate.queryForObject(sql,new StudentRowMapper(),id);}public List<Student> selectAll() {String sql = "select*from student";return jdbcTemplate.query(sql,new StudentRowMapper());}//定义一个私有内部类实现RowMapper接口private class StudentRowMapper implements RowMapper<Student> {public Student mapRow(ResultSet resultSet, int i) throws SQLException {Student student = new Student();/*** 注意从数据库取值的时候,实体类属性名和数据库表的字段名需一一对应*/student.setId(resultSet.getInt("id"));student.setName(resultSet.getString("name"));student.setSex(resultSet.getString("sex"));student.setBorn(resultSet.getDate("born"));return student;}}
}

测试代码

package com.cd4356.jdbc_template;import com.cd4356.jdbc_template.dao.StudentDao;
import com.cd4356.jdbc_template.entity.Student;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class demo {@Autowiredprivate StudentDao studentDao;@Testpublic void find(){Student student = studentDao.select(3);System.out.println(student);}
}

输出结果


  • 优点:简单、灵活

    • JDBC Template对JDBC API进行封装后,提供简洁方便的方法,简化了我们开发的代码,并且保留了它的灵活性,使我们的快发更加便捷
  • 缺点

    • SQL与Java代码参杂,对开发人员要求较高,我们更提倡SQL和Java代码分离的形式,这样就可以让开发人员更加专注于自己擅长的领域

    • 功能不够强大,比如它没有提供分页(查询大量数据的时候)、没有提供对象关联(selection关联了student,那么通过selection对象就可以访问关联的student对象,而无需使用student对象的id)、. . .等功能

总结:
JDBC Template是Spring框架对JDBC操作的封装,它简单、灵活,但不够强大。它只是在JDBC API的基础上迈出了一小步,Spring没有更大程度的去改进。当然并不是说Spring做的不好,而是Spring要留出跟多的空间给其它优秀的ORM框架。

Spring内部提供了对优秀的ORM框架的直接支持,Spring可以很轻松的集成这些框架,这些完善的ORM框架,解决了SQL与Java代码参杂、功能不够强大等问题。

所以在实际开发中,一般会与其它ORM框架(mybatis,hibernate等. . .)混合使用




SQL 语句主要可以划分为以下 3 个类别。

  • DDL(Data Definition Languages,数据定义语言)语句:这些语句定义了不同的数据段、数据库、表、列、索引等数据库对象的定义。常用的语句关键字主要包括 create、drop、alter等。

  • DML(Data Manipulation Language,数据操作语言)语句:用于添加、删除、更新和查询数据库记录,并检查数据完整性,常用的语句关键字主要包括 insert、delete、udpate 和select 等。(增添改查)

  • DCL(Data Control Language,数据控制语句)语句:用于控制不同数据段直接的许可和访问级别的语句。这些语句定义了数据库、表、字段、用户的访问权限和安全级别。主要的语句关键字包括 grant、revoke 等。

总结:

  • DDL 是数据定义语言的缩写,简单来说,就是对数据库内部的对象进行创建、删除、修改的操作语言。它和 DML 语言的最大区别是 DML 只是对表内部数据的操作,而不涉及到表的定义、结构的修改,更不会涉及到其他对象。DDL 语句更多的被数据库管理员(DBA)所使用,一般的开发人员很少使用

https://blog.csdn.net/scbiaosdo/article/details/81561162


Spring组件之一 JDBC Template相关推荐

  1. Spring JDBC Template

    Spring为我们提供了JDBC的模板来连接数据库,Spring JDBC Template. 使用: 第一,导入相关的jar包 第二,要连接数据库首先要加载驱动,获得连接,然后才能进行相关的数据库操 ...

  2. jdbc Template 介绍和 spring 链接数据源的四种方式

    为什么具体讲template介绍和spring jdbc链接数据源的几种方式放在一起介绍,在于你在使用template的时候,具体配置数据源,或者在链接配置数据源的时候要是使用template,就在在 ...

  3. java day30【数据库连接池 、Spring JDBC : JDBC Template】

    第一章  数据库连接池 1. 概念:其实就是一个容器(集合),存放数据库连接的容器. 当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完之后 ...

  4. 在Spring中使用JDBC访问关系数据

    在Spring中使用JDBC访问关系数据 本指南将引导您完成使用Spring访问关系数据的过程. 你会建立什么 您将构建一个使用Spring JdbcTemplate访问存储在关系数据库中的数据的应用 ...

  5. Spring框架对JDBC的简单封装。提供了一个JDBCTemplate对象简化JDBC的开发

    Spring JDBC     * Spring框架对JDBC的简单封装.提供了一个JDBCTemplate对象简化JDBC的开发     * 步骤:         1. 导入jar包        ...

  6. Spring复习日志--spring中的jdbc

    Spring复习日志--spring中的jdbc xml的配置 Spring中操作数据库 jdbcTemplate的基本操作-执行简单的 执行预编译语句 执行查询的语句 模糊查询 xml的配置 < ...

  7. spring: 使用Spring提供的JDBC模板(使用profiles选择数据源/使用基于JDBC驱动的数据源)...

    Spring提供的JDBC框架负责管理资源和异常处理,从而可以简化开发者的JDBC代码.开发者只需要编写写入和读取数据库相关的代码即可. 正如在之前的小节中论述过的,Spring将数据库访问过程中的模 ...

  8. Spring组件扫描context:component-scan/使用详解

    1.如果不想在xml文件中配置bean,我们可以给我们的类加上spring组件注解,只需再配置下spring的扫描器就可以实现bean的自动载入. <!-- 注解注入 --> <co ...

  9. datastore_使用Spring Session和JDBC DataStore进行会话管理

    datastore 在Web应用程序中,用户会话管理对于管理用户状态至关重要. 在本文中,我们将学习在集群环境中管理用户会话所采用的方法,以及如何使用Spring Session以更简单和可扩展的方式 ...

最新文章

  1. C#读取excel文件数据丢失问题
  2. 秒懂上线必不可少的安全测试!
  3. MySQL中的子查询
  4. LeetCode之最小路径和
  5. grafana mysql插件_grafana插件动态数据
  6. C#用户进行LDAP验证并返回员工信息
  7. c语言编写自动生成密码,c语言密码生成.doc
  8. Matlab中(),[],与{}的用法认识
  9. 俄罗斯互联网提供商巨头Rostelecom遭遇DDoS攻击企图
  10. chrome中文本框样式问题
  11. 未来教育计算机二级python_计算机二级题库
  12. 软件质量保证与测试(秦航第二版)第一章软件质量和测试的背景
  13. 高速PCB设计考虑的六个方面
  14. 五笔中比较难拆解的字
  15. Swift - 视频录制教程3(设置拍摄窗口大小,录制正方形视频)
  16. JavaScript基础第06天笔记
  17. 虚拟机(VMware Workstation Pro15)及系统(Windows10)安装
  18. python中split_python中split是什么意思
  19. sketch如何做设计稿交互_设计干货 | Sketch 的交互插件强势更新,再也不用为跳转的事发愁了!...
  20. 各种项目的源代码网站

热门文章

  1. vue中在data中写入img地址 引入问题
  2. 将button变成圆形(有弧度)
  3. 小汤学编程之JavaEE学习day05——会话管理、文件上传与下载、Ajax
  4. 设计者模式详解--桥接模式
  5. 学生群体中奖励制度的马太效应
  6. Java动态代理全面分析
  7. 学习API 判断光驱是否为光盘
  8. Flutter打包安卓提示请使用 -Xlint:deprecation 重新编译、请使用 -Xlint:unchecked 重新编译
  9. JS获取登录者IP和登录城市
  10. Spring Bean的生命周期例子