今天主要学习JdbcTemplate,DBUtils
思维导图:
一.JdbcTemplate
1.概念:
JdbcTemplate是spring框架对JDBC进行简便操作所提供一个模板类吗,这个类core包下面进行提供的JdbcTemplate可以在JDBC的基础进行一些简单的CRUD(增删改查)操作,同时还大量的使用了预编译操作,所以在性能和安全上都可以达到一个非常优秀的地步。
2. 如何去使用JdbcTemplate:
(1)需要导入jar包(因为这是一个第三方工具)
所提供的JdbcTemplate目录下的lib下面的所有包(5个)
(2)创建JdbcTemplate对象
JdbcTemplate template = new JdbcTemplate(JdbcUtils.getDataSource());
注意:这里的构造方法需要一个DataSource()的具体对象(其实要的就是连接池,因为JdbcTemplate不具备连接功能,所以需要连接池来驱动它)
(3)调用我们的 JdbcTemplate的各种方法实现对DML和DQL的操作
int update(String sql):适用于没有修改条件的增删改(不存在预参数参与)
delete from account;
int update(String sql,Object...):适用于带有操作条件的增删改(存在预编译参数)
delete from account where id = ?;
注意:这个Object...是一个可变参数
3.查询的结果有哪些?
(1)返回的结果只有单行(查询之后只能存在一条结果的操作)
Map<String, Object> queryForMap(String var1):适用于没有预编译参数的sql
Map<String, Object> queryForMap(String var1, Object... var2):适合存在预编译参数的sql
注意:
queryForMap只适用于一条结果的查询,如果是是多条结果则会产生异常,查询后的结果列会存储到一个Map集合当中,其中Map的键用于存储列名,Map值则存储列的数据
(2)返回的结果是全部或者多行(查询全表数据或者查询结果存在多条)
List<Map<String, Object>> queryForList(String var1):适用于没有预编译参数的sql
List<Map<String, Object>> queryForList(String var1,Object... var2):适合存在预编译参数的sql
注意:queryForMap适用于多条结果的查询,如果确保是一条结果则不建议使用它,因为操作比较复杂其查询的每一行数据会先存在Map集合当中,然后在将Map集合存储在List集合当当中在正常的开发逻辑当中,我们的每一个数据应该是一个对象的属性,所有的操作应该以对象作为中心JdbcTemplate为了更加的符合面向对象思想,也给我们提供了一个将查询结果封装到对象的方法
方式一:手写转换处理
List<T> query(String var1, RowMapper<T> var2):
var1:需要操作的SQL
var2:这是一个接口,里面需要依赖重写后的mapRow方法,因为所有查询的结果全部存在这个方法的ResultSet当中。
方式二:自动转换处理
template.query(sql,new BeanPropertyRowMapper<UserVO>(UserVO.class));
(3)返回的结果是一个数据(聚合函数的SUM/AVG/COUNT)
queryForObject(String sql, Class<T> requiredType);
sql:需要查询的SQL语句
requiredType:返回结果和接收结果的数据类型,通过反射加载 一般只能是Double.class和Long.class
例子:
package com.jdbctemlate;
import com.util.JdbcUtils;
import com.vo.UserVO;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class Demo01 {
public static void main(String[] args) {
select05();
}
//一个结果的查询
public static void select05() {
JdbcTemplate template = new JdbcTemplate(JdbcUtils.getDataSource());
String sql = "select count(id) from ask_users";
Long l = template.queryForObject(sql,Long.class);
System.out.println(l);
}
//自动将查询结果转化为JavaBean
public static void select04() {
JdbcTemplate template = new JdbcTemplate(JdbcUtils.getDataSource());
String sql = "select * from ask_users";
List<UserVO> list = template.query(sql,new BeanPropertyRowMapper<UserVO>(UserVO.class));
for (UserVO userVO : list) {
System.out.println(userVO.getUsername());
System.out.println(userVO.getPassword());
System.out.println(userVO.getEmail());
System.out.println(userVO.getStatus());
System.out.println(userVO.getJob());
System.out.println(userVO.getGender());
System.out.println("--------------------");
}
}
//手动将查询结果转化为JavaBean
public static void select03() {
JdbcTemplate template = new JdbcTemplate(JdbcUtils.getDataSource());
String sql = "select * from ask_users";
//通过子类实现RowMapper,并mapRow方法
//List<UserVO> u = template.query(sql,new MyRowMapper());
//直接使用匿名内部类
// List<UserVO> u = template.query(sql, new RowMapper<UserVO>() {
// @Override
// public UserVO mapRow(ResultSet rs, int i) throws SQLException {
// //创建一个实体对象
// UserVO user = new UserVO();
// user.setUsername(rs.getString("username"));
// user.setEmail(rs.getString("email"));
// user.setGender(rs.getString("gender"));
// user.setId(rs.getInt("id"));
// user.setJob(rs.getString("job"));
// user.setStatus(rs.getInt("Status"));
// return user;
//
// }
// });
//使用Lambda表达式处理
List<UserVO> u1 = template.query(sql,(rs, i) -> {
//创建一个实体对象
UserVO user = new UserVO();
user.setUsername(rs.getString("username"));
user.setEmail(rs.getString("email"));
user.setGender(rs.getString("gender"));
user.setId(rs.getInt("id"));
user.setJob(rs.getString("job"));
user.setStatus(rs.getInt("Status"));
return user;
});
for (UserVO userVO : u1) {
System.out.println(userVO.getUsername());
System.out.println(userVO.getPassword());
System.out.println(userVO.getEmail());
System.out.println(userVO.getStatus());
System.out.println(userVO.getJob());
System.out.println(userVO.getGender());
System.out.println("--------------------");
}
}
//查询多条结果
public static void select02() {
JdbcTemplate template = new JdbcTemplate(JdbcUtils.getDataSource());
String sql = "select * from ask_users";
List<Map<String, Object>> list = template.queryForList(sql);
/*
* +--------------------------+
* | id | username | password |
* +--------------------------+
* | 1 | admin | root |
* +--------------------------+
* | 2 | toobug | admin |
* +--------------------------+
* ....
*
* 1.将每一条结果转换成了Map:
* {id = 1,username = admin,password = root}
* {id = 2,username = toobug,password = admin}
* ...
* 2.将Map继续存储到List集合当中
* [{id = 1,username = admin,password = root},{id = 2,username = toobug,password = admin}.....]
* */
// System.out.println(list);
//取出结果
//1.先取出每一行的数据(每一个map)
for (Map<String, Object> maps : list) {
//System.out.println(maps);
//2.在map当中取出每一个数据值
for (Map.Entry<String, Object> e : maps.entrySet()) {
System.out.println("列名:" + e.getKey() + "," + "值:" + e.getValue());
}
System.out.println("-------------------------");
}
}
//查询单条结果
public static void select01() {
JdbcTemplate template = new JdbcTemplate(JdbcUtils.getDataSource());
//查询ID为1的用户数据
String sql = "select * from ask_users where id = ? ";
//String sql = "select * from ask_users where id = ? or name = ?";//错误,不能反回多条结果的查询
Map<String, Object> map = template.queryForMap(sql, 1);
/*
* +--------------------------+
* | id | username | password |
* +--------------------------+
* | 1 | admin | root |
* +--------------------------+
* 转换成了Map:
* {id = 1,username = admin,password = root}
* */
System.out.println(map);
//判断账号是否存在
if (map.get("username").equals("李神仙")) {
System.out.println("账号已经存在");
} else {
System.out.println("账号不存在");
}
//对map集合遍历,取出所有数据
for (Map.Entry<String, Object> e : map.entrySet()) {
System.out.println("列名:" + e.getKey() + "," + "值:" + e.getValue());
System.out.println("-------------------------");
}
}
//修改数据
public static void update() {
JdbcTemplate template = new JdbcTemplate(JdbcUtils.getDataSource());
//修改username为HR且状态为1的数据
String sql = "update ask_users set email= ? where username = ? AND status = ?";
int rows = template.update(sql, "[email protected]", "HR", 1);
System.out.println("一共修改了" + rows + "行。");
}
//删除数据
public static void deltet() {
//1.创建一个JdbcTemplate对对象
JdbcTemplate template = new JdbcTemplate(JdbcUtils.getDataSource());
//2.调用方法
//删除id为6的数据
int rows = template.update("delete from ask_users where id = ?", 6);
System.out.println("一共删除了" + rows + "行。");
}
}
二.DBUtils
1.DBUtils的概念:
DBUtils是Apache所提供的一个java语言当中用于操作数据的工具类,小巧简单且实用;DBUtils他封装了对JDBC的大部分的操作,简化了我们操作JDBC的流程
2.DBUtils的三个核心功能:
(1)DBUtils类:主要的功能就是数据的连接进行释放、关闭、事务的开启和关闭
(2)QueryRunner:主要的功能就是的JDBC进行一些CRUD操作(最主要的核心类)
(3)ResultSetHandler:主要的功能是对结果集进行处理
3.DML如何操作(update):
(1)导包
commons-dbutils-1.6.jar
(2)创建一个QueryRunner的对象
构造方法:
public QueryRunner():无参,可以不指定数据库的连接池,一般是用来操作事务
public QueryRunner(DataSource ds):需要指定一个数据库的连接池,因为本事并不具备数据
库的连接功能,所以还是需要第三方的连接池来进行操作。
(3)准备一个sql语句
String sql = "update ask_users set username = ? where id = ?";
(4)准备填充预编译占位数据
方式一:使用可变参数
qr.update(sql,"admin","root");
方式二:使用Object[]数组
Object [] obj = {"root","admin"};
int rows = qr.update(sql,obj); / int rows = qr.update(sql,new Object[]{"root","admin"});
注意:
1)这里返回的int类型的受影响的行数
2)如果没有预编译占位的数据,则直接写上sql的数据就可以了
3)这种方式适用于增删改,不适用于查。
例子:
package com.DBUtils;
import com.util.JdbcUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.junit.Test;
import java.sql.SQLException;
public class Demo01 {
public static void main(String[] args) throws SQLException {
}
public void insert() throws SQLException {
//创建一个对象,并指定连接池进行连接
QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
//需求新增一条数据
//准备sql
String sql = "insert into ask_users(id,username,password) values(0,?,?)";
//通过可变参数对预编译的占位数据进行赋值
//int rows = qr.update(sql,"admin","root");
//通过Object的数组准备参数进行赋值(常用)
Object [] obj = {"root","admin"};
//int rows = qr.update(sql,obj);
//使用匿名数组赋值
int rows = qr.update(sql,new Object[]{"root","admin"});
System.out.println("一共影响了"+rows+"行");
}
@Test
public void update() throws SQLException {
//创建对象并且指定数据源
QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
//准备SQL语句
String sql = "update ask_users set username = ? where id = ?";
//执行操作
int rows = qr.update(sql,new Object[]{"toobug",747});
System.out.println("一共影响了"+rows+"行");
}
@Test
public void delete() throws SQLException{
//创建对象并且指定数据源
QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
//准备SQL语句
String sql = "delete from ask_users where id = ?";
//执行操作
int rows = qr.update(sql,new Object[]{747});
System.out.println("一共影响了"+rows+"行");
}
}
4.DQL如何操作(query):
所有的查询的重载一定会有一个ResultSetHandler
ResultSetHandler是对我们的查询结果进行处理,但是我们发现ResultSetHandler其实是一个接口
ResultSetHandler本身其实针对不同的查询结果的类型也提供了不同子类给我们进行直接调用
5.ResultSetHandler子类有哪些?
(1)ArrayHandler:将处理的结果的第一条记录封装在一个Object数组的集合当中(一般只处理一行数据的查询)
(2)ArrayListHandler:将处理结果的所有的数据全部封装在一个Object数组,然后将这个数组在存储到List的集合当中(一般用于处理多行或者全表的数据)
(3)(重要)BeanHandler:将查询的一条结果储存到一个JavaBean的变量当中(一般用于一行数据的查询)
(4)(重要)BeanListHandler:将处理结果的所有的数据全部全部存储在JavaBean当中,然后将这些JavaBean在存储到List的集合当中(一般用于处理多行或者全表的数据)
(5)ColumnListHandler:查询指定行的数据(不包含列名),存在一个List集合
(6)MapListHandler:会将我们结果的所有数据全部封装在一个Map集合当中,key就对应列名,value就对应了列的值,因为存在多个,所以继续封装在List集合当中
(7)(重要)ScalarHandler:将单个数据(非行)查询并且返回(只用于聚合函数)
例子:
package com.DBUtils;
import com.util.JdbcUtils;
import com.vo.UserVO;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.*;
import org.junit.Test;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
public class Demo02 {
//创建对象
QueryRunner qr = new QueryRunner();
@Test
//ArrayHandler:将处理的结果的第一条记录的数据值封装在一个Object数组的集合当中(一般只处理一行数据的查询)
public void arrayHandler() throws SQLException {
//创建对象
QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
//准备sql
String sql = "select * from ask_users";
//执行查询
Object[] obj = qr.query(sql,new ArrayHandler());
//运行查询结果
for(Object o : obj){
System.out.println(o);
}
}
@Test
//ArrayListHandler:将处理结果的所有的数据的值全部封装在一个Object数组,然后将这个数组在存储到List的集合当中(一般用于处理多行或者全表的数据)
public void arrayListHandler() throws SQLException{
String sql = "select * from ask_users";
List<Object[]> list = qr.query(sql,new ArrayListHandler());
for(Object[] objs : list){
for(Object o : objs){
System.out.println(o);
}
System.out.println("-------------------------");
}
}
@Test
//(重要)BeanHandler:将查询的第一条结果储存到一个JavaBean的对应变量当中(一般用于一行数据的查询,这里因为是自动装配
// 所以一定要保证JavaBean的字段和数据库的字段名完全一致 是原则上也应该如此)
public void beanHandler() throws SQLException{
String sql = "select * from ask_users";
UserVO userVO = qr.query(sql,new BeanHandler<UserVO>(UserVO.class));
System.out.println(userVO.getUsername());
}
@Test
//(重要)BeanListHandler:将处理结果的所有的数据全部全部存储在JavaBean当中,然后将这些JavaBean在存储到List的集合当中(一般用于处理多行或者全表的数据)
public void beanListHandler() throws SQLException{
String sql = "select * from ask_users";
List<UserVO> userVOSList = qr.query(sql,new BeanListHandler<UserVO>(UserVO.class));
userVOSList.forEach(System.out::println);
}
@Test
//ColumnListHandler(String 列名):查询指定列的数据(不包含列名),存在一个List集合
public void columnListHandler() throws SQLException{
String sql = "select * from ask_users";
List<String> list = qr.query(sql,new ColumnListHandler<String>("username"));
list.forEach(System.out::println);
}
@Test
//MapListHandler:会将我们结果的所有数据全部封装在一个Map集合当中,key就对应列名,value就对应了列的值,因为存在多个,所以继续封装在List集合当中
public void mapListHandler() throws SQLException{
String sql = "select * from ask_users";
List<Map<String,Object>> list = qr.query(sql,new MapListHandler());
list.forEach(System.out::println);
}
@Test
//ScalarHandler:将单个数据(非行)查询并且返回(只用于聚合函数)
public void scalarHandler() throws SQLException {
String sql = "select count(id) from ask_users";
Object obj = qr.query(sql,new ScalarHandler());
System.out.println(obj);
}
@Test
//query的多个参数的填充(数据源,sql语句,填充参数,实现类对象)
public void beanListHandlers() throws SQLException{
String sql = "select * from ask_users where gender = ?";
//List<UserVO> userVOSList = qr.query(sql,1,new BeanListHandler<UserVO>(UserVO.class));
List<UserVO> userVOSList = qr.query(JdbcUtils.getC3p0Pool(),sql,new Object[]{1},new BeanListHandler<UserVO>(UserVO.class));
userVOSList.forEach(System.out::println);
}
}