大部分情况下JDBC已经能够满足大部分用户的需求,但是再使用JDBC时,必须自己来管理数据库资源:例如获取PreparedStatement,设置SQL语句,关闭连接等步骤。jdbcTemplate就是Spring对JDBC的封装,目的是使JDBC更加容易使用。jdbcTemplate时Spring的一部分。
jdbcTemplate处理了资源的简历和释放。它帮助我们便面一些常见的错误,比如忘记关闭连接。运行核心的JDBC工作流,如Statement的建立和执行,而我们只需要提供SQL语句和提取结果。
在jdbcTemplate中执行SQL语句的方法大致分为3类:
1.excute:可以执行所有的SQL语句,一般用于执行DDL语句。
2.update:用于执行insert、update、delete等DML语句。
3.QueryXxx:用于DQL数据查询语句。
准备数据:
假设在mydb数据库中创建一张emp表,用它记录员工的基本信息:
员工编号(id,int(11),主键,自增长)
员工姓名(name carchar(20),非空)
员工工资(salary double default 5000 )
现在需要插入一些员工的信息
id | name | salary |
---|---|---|
1 | 花花 | 5000 |
2 | 美丽 | 6000 |
3 | jack | 7000 |
4 | 翠花 | 8000 |
案例代码:
1.准备c3p0-config.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<!-- 默认配置,c3p0框架默认加载这段默认配置 -->
<default-config>
<!-- 配置JDBC 四个基本属性 -->
<property name="driverClass">com.mysql.cj.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/mydb?serverTimezone=UTC&characterEncoding=utf-8</property>
<property name="user">root</property>
<property name="password">123</property>
</default-config>
</c3p0-config>
2.准备JDBCUtils工具类
public class JDBCUtils {
private static final ComboPooledDataSource dataSource = new ComboPooledDataSource();
public static ComboPooledDataSource getDataSource() {
return dataSource;
}
//获取连接
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
public static void release(Connection conn, Statement stmt, ResultSet rs) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
rs = null; //clear to let GC do its work
}
release(conn, stmt);
}
public static void release(Connection conn, Statement stmt) {
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null; //clear to let GC do its work
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null; //clear to let GC do its work
}
}
}
实现需求
一 、void execute(sql)
此方法可以执行所有的sql语句,方法执行后没有返回值。一般用于执行DDL语句
1.创建表格:
@Test
public void test1(){
//创建核心类对象
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
//创建emp表
String sql = "create table emp(" +
"id int primary key auto_increment," +
"name varchar(20) not null," +
"salary double default 5000" +
");";
jdbcTemplate.execute(sql);
}
2.删除表格
String sql2 = "drop table emp2;";
jdbcTemplate.execute(sql2);
3.修改表表格
alter table emp change id pid int not null auto_increment;
二 、int updte(sql,Object … args)
此方法一般用来对数据库数据进行增、删、改操作,返回int类型结果,代表的是影响记录数。常用于执行DML语句。
1.增
@Test
public void test2(){
//创建核心类
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
//插入数据
String sql = "insert into emp values(?,?,?)";
int count = jdbcTemplate.update(sql, null, "花花", 5000);
count +=jdbcTemplate.update(sql, null, "美丽", 6000);
count +=jdbcTemplate.update(sql, null, "jack", 7000);
count +=jdbcTemplate.update(sql, null, "翠花", 8000);
count +=jdbcTemplate.update(sql, null, "如花", 88888);
System.out.println("count = " + count);
}
2.删
@Test
public void test3(){
//1.创建核心类
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
//2.删除数据
String sql = "delete from emp where name = '如花'";
int count = jdbcTemplate.update(sql);
System.out.println("count = " + count);
}
3.改
@Test
public void test4(){
//创建核心类
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
//2.修改数据
String sql = "update emp set salary = 88888 where pid = ?";
int count = jdbcTemplate.update(sql, 4);
System.out.println("count = " + count);
}
三 、 queryForXxx(sql,Object … args)
方法名 | 作用 | 返回值类型 | 备注 |
---|---|---|---|
queryForObject() | 单行单列查询 | Object | |
queryForMap() | 单行多列 | Map | |
queryForList() | 多行单列 | List | List存放多个Map,map中存在一个键值对 |
queryForList() | 多行多列 | LIst | List存放多个Map |
query() | 将查询数据包装成对象返回结果 | List | 将数据库的每一行当作一个对象,需要创建实体类来保存数据,实体类属性就是数据表的列名 |
1. queryForObject – 查询单行单列数据
public <T> T queryForObject(String sql, Class<T> requiredType, @Nullable Object... args)
方法的参数说明:
1:必须要有一条sql执行语句;
2:必须要指定方法的返回值类型
3:省略参数根据实际情况选择
方法的返回值说明:
返回值类型跟随参数列表中参数2指定的类型
实现代码:
@Test
public void test5(){
//创建核心类对象
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
//查找单个数据:
//pid=1的员工名字
String sql = "select name from emp where pid = 1";
String name = jdbcTemplate.queryForObject(sql, String.class);//省略参数
System.out.println("name = "+ name);
//名字为翠花的员工编号
String sql2 = "select pid from emp where name = ?";
int pid = jdbcTemplate.queryForObject(sql2, int.class,"翠花");//不省略参数
System.out.println("pid = " + pid);
}
2. queryForMap – 查询单行多列数据
public Map<String, Object> queryForMap(String sql, @Nullable Object... args)
方法的参数说明:
1:必须要有一条sql执行语句;
2:省略参数根据实际需要选择
方法的返回值说明:
方法返回一个Map映射集,其中key对应数据表的列名,value对应数据表的值。
代码实现:
@Test
public void test6(){
//创建核心类对象
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
//查找单行多个数据
String sql = "select * from emp where name = ?";
Map<String, Object> map = jdbcTemplate.queryForMap(sql, "翠花");
System.out.println("map = " + map);
}
3. queryForList – 查询多行单列、多行多列数据
public List<Map<String, Object>> queryForList(String sql, @Nullable Object... args)
方法的参数说明:
1:必须要有一条sql执行语句;
2:省略参数根据实际情况选择
方法的返回值说明:
方法返回值类型是List类型,里面保存的是map映射表,引射表中的key对应数据表的列名,value对应值;当查询多行单列的时候,list集合中可以存在多个map,但是map中只存在一个键值对数据;查询多行多列的时候,list集合中存放多个map,map中的键值对数量和列数量一致。
多行单列代码实现:
@Test
public void test7(){
//创建核心类对象
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
//查找多行单列数据
String sql = "select name from emp where salary >= 7000";
List<Map<String, Object>> list = jdbcTemplate.queryForList(sql);
//遍历集合
for(Map<String, Object> map:list){
System.out.println(map);
}
}
多行多列代码实现:
@Test
public void test8(){
//创建核心类对象
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
//查找多行多列数据
String sql = "select * from emp where salary >= ? and pid >2";
List<Map<String, Object>> list = jdbcTemplate.queryForList(sql, 7000);
//遍历集合
for(Map<String, Object> map:list){
System.out.println(map);
}
}
四 、query使用RowMapper做映射返回对象
通过上面的代码,我们发现:queryForList方法其实就是返回每一行中的某些列或者全部列的值,如果我们把每一行都当成一个对象,那么列的值就是对象的属性了。我们就可以通过查询对象来查找我们需要的数据了。
public <T> List<T> query(String sql, RowMapper<T> rowMapper, @Nullable Object... args)
方法的参数说明:
1:必须要有一条sql执行语句;
2:RowMapper 接口的实现类对象
在匿名内部类中将结果集中的一行记录转成一个Product对象
3:省略参数根据实际情况选择
方法返回值说明:
返回的是List集合,里面存储的是实体类对象。
定义实体类:
public class Employee {
private int pid;
private String name;
private double salsry;
@Override
public String toString() {
return "Employee{" +
"pid=" + pid +
", name='" + name + '\'' +
", salsry=" + salsry +
'}';
}
public Employee(int pid, String name, double salsry) {
this.pid = pid;
this.name = name;
this.salsry = salsry;
}
public Employee() {
}
public int getPid() {
return pid;
}
public void setPid(int pid) {
this.pid = pid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalsry() {
return salsry;
}
public void setSalsry(double salsry) {
this.salsry = salsry;
}
}
实例代码:
@Test
public void test9(){
//创建核心类对象
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
//查找多行多列数据
String sql = "select * from emp ";
List<Employee> list = jdbcTemplate.query(sql, new RowMapper<Employee>() {
@Override
public Employee mapRow(ResultSet rs, int i) throws SQLException {
//从结果集中取出数据
int pid = rs.getInt("pid");
String name = rs.getString("name");
double salary = rs.getDouble("salary");
//包装成对象并返回
return new Employee(pid,name,salary);
}
});
//遍历集合
for(Employee employee:list){
System.out.println(employee);
}
}
五 、query使用BeanPropertyRowMapper做映射返回对象
Sping 中提供了一个便利的RowMapper实现—–BeanPropertyRowMapper,通过这个类我们可以更加方便的将数据库的数据包装成对象:
代码实现:
@Test
public void test10(){
//创建核心类对象
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
//查找多行多列数据
String sql = "select * from emp ";
List<Employee> list = jdbcTemplate.query(sql,new BeanPropertyRowMapper(Employee.class));
//遍历集合
for(Employee employee:list){
System.out.println(employee);
}
}