DBUtils和Spring Jdbc Template
Dbutils
DBUtils简介
-
commons-dbutils 是 Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化jdbc编码的工作量,创建连接、结果集封装、释放资源,同时也不会影响程序的性能。创建连接、结果集封装、释放资源因此dbutils成为很多不喜欢hibernate的公司的首选。
-
API介绍:
-
org.apache.commons.dbutils.QueryRunner — 核心类。执行SQL查询以处理结果集。这个类是线程安全的。
-
org.apache.commons.dbutils.ResultSetHandler — 结果集封装器
-
org.apache.commons.dbutils.DbUtils — 工具类
-
-
学习地址及jar包下载:http://commons.apache.org/proper/commons-dbutils/download_dbutils.cgi
连接数据库jar包mysql-connector-java-5.1.47:https://dev.mysql.com/downloads/connector/j/
-
本文是使用的数据库连接池是上一篇使用的C3P0文章链接:https://blog.csdn.net/SYJ_1835_NGE/article/details/88694434
DbUtils类
DbUtils:提供如加载驱动、关闭连接、事务提交、回滚等常规工作的工具类,里面的所有方法都是静态的。主要方法如下:
-
DbUtils类提供了三个重载的关闭方法close() 。这些方法检查所提供的参数是不是NULL,如果不是的话,它们就关闭Connection、Statement和ResultSet。
public static void close(Connection conn) throws SQLException public static void close(ResultSet rs) throws SQLException public static void close(Statement stmt) throws SQLException
-
这一类"quietly"方法不仅能在Connection、Statement和ResultSet为NULL情况下避免关闭,还能隐藏一些在程序中抛出的SQLException。
public static void closeQuietly(Connection conn,Statement stmt, ResultSet rs) public static void closeQuietly(Connection conn) public static void closeQuietly(ResultSet rs) public static void closeQuietly(Statement stmt)
-
用来提交连接,然后关闭连接,并且在关闭连接时不抛出SQL异常。
static void commitAndClose(Connection conn) static void commitAndCloseQuietly(Connection conn)
-
装载并注册JDBC驱动程序,如果成功就返回true。使用该方法,你不需要捕捉这个异常ClassNotFoundException。
static boolean loadDriver(ClassLoader classLoader, String driverClassName) static boolean loadDriver(String driverClassName)
-
用于事务的回滚并且在资源使用完后将连接关闭
static void rollback(Connection conn) static void rollbackAndClose(Connection conn) static void rollbackAndCloseQuietly(Connection conn)
QueryRunner类
注意:
1、如果使用 QueryRunner(DataSource ds) 构造器创建QueryRunner对象,需要使用连接池,如DBCP、C3P0等等,数据库事务交给DBUtils框架进行管理 ---- 默认情况下每条SQL语句单独一个事务。
2、如果使用 QueryRunner() 构造器创建QueryRunner对象 ,需要自己管理事务,因为框架没有连接池无法获得数据库连接。
-
该类简单化了SQL查询,它与ResultSetHandler组合在一起使用可以完成大部分的数据库操作,能够大大减少编码量。
-
QueryRunner类提供了两个比较常使用的构造方法:
-
默认的构造方法(无参的构造函数):在执行查询操作的时候需要手动传入Connection对象
public QueryRunner()
-
需要一个 javax.sql.DataSource 来作参数的构造方法:
public QueryRunner(DataSource ds)
-
使用数据库连接池来获取数据源,C3P0、DBCP或者Durid
public static DataSource getDataSource() { return ds; }
-
-
常用方法:
-
批处理
batch(Connection conn, String sql, Object[][] params) // 传递连接批处理 batch(String sql, Object[][] params) // 不传递连接批处理
-
更新操作
//无参构造函数需要手动传入连接对象 int update(Connection conn, String sql) int update(Connection conn, String sql, Object... params) int update(Connection conn, String sql, Object param) //有参的构造函数(传入数据源的)Object... params和参数注入的 ?一 一对应 int update(String sql) int update(String sql, Object... params) int update(String sql, Object param)
-
查询操作
<T> T query(Connection conn, String sql, ResultSetHandler<T> rsh) <T> T query(Connection conn, String sql, ResultSetHandler<T> rsh, Object... params) <T> T query(String sql, ResultSetHandler<T> rsh) <T> T query(String sql, ResultSetHandler<T> rsh, Object... params)
-
ResultSetHandler接口
-
该接口用于处理 java.sql.ResultSet,将数据库的记录按要求转换为另一种形式。(List、Map、Bean等)
-
ResultSetHandler 接口提供了一个单独的方法:
//将参数中的结果集ResultSet rs转化为另外一种形式 T handle(ResultSet rs) throws SQLException
-
ResultSetHandler 接口的实现类(构造方法不唯一,在这里只用最常见的构造方法):
-
**BeanHandler(Class<? extends T> type):**将结果集中的第一行数据封装到一个对应的JavaBean实例中。也可以指定参数返回指定参数所在行的数据,下面有例子进行展示
-
**BeanListHandler(Class type):**将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里。
-
**ArrayHandler():**把结果集中的第一行数据转成对象数组(存入Object[])。
-
**ArrayListHandler():**把结果集中的每一行数据都转成一个对象数组,再存放到List中
-
**ScalarHandler(int columnIndex) || ScalarHandler(String columnIndex):**通常用来保存只有一行一列的结果集。通常用来执行聚合函数
-
**MapHandler():**将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值。
-
**MapListHandler():**将结果集中的每一行数据都封装到一个Map里,然后再将所有的Map存放到List中。
-
**BeanMapHandler(Class<V> type):**将结果集每一条数据,转为JavaBean对象,再保存到map集合中
BeanMapHandler(Class<V> type) BeanMapHandler(Class<V> type, int columnIndex) BeanMapHandler(Class<V> type, RowProcessor convert) BeanMapHandler(Class<V> type, String columnName)
-
**KeyedHandler(String columnName):**将结果集每一行数据保存到一个“小”map中,key为列名,value该列的值,再将所有“小”map对象保存到一个“大”map中 , “大”map中的key为指定列,value为“小”map对象
KeyedHandler( KeyedHandler(int columnIndex) KeyedHandler(RowProcessor convert) KeyedHandler(String columnName)
-
开发步骤
-
创建mydb数据库和employee表
CREATE TABLE `employee` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(20) DEFAULT NULL, `salary` int(12) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8 --------------------- 作者:SYJ_追梦逐星 来源:CSDN 原文:https://blog.csdn.net/SYJ_1835_NGE/article/details/88694434 版权声明:本文为博主原创文章,转载请附上博文链接!
-
导入相关jar包 commons-dbutils-1.7.jar
-
创建QueryRunner对象。依赖于数据源DataSource
//数据源可以通过C3P0、DBCP或者Druid获取 QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
-
调用QueryRunner的方法来完成CRUD的操作
- update(String sql, Object… params):执行DML语句。增、删、改语句。
- query(String sql, ResultSetHandler rsh, Object… params):执行查询语句,将其封装成不同的数据方式。
-
对于CUD,执行DML语句。增、删、改语句。
public class Demo1 { //如果使用 QueryRunner(DataSource ds) 构造器创建QueryRunner对象,需要使用连接池, // 如DBCP、C3P0等等,数据库事务交给DBUtils框架进行管理 ---- 默认情况下每条SQL语句单独一个事务。 //如果使用 QueryRunner() 构造器创建QueryRunner对象 ,需要自己管理事务,因为框架没有连接池无法获得数据库连接。 @Test //快速感受DBUtils之插入操作 public void test1() { String sql = "insert into employee (username,salary) values (?,?)"; QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource()); try { int count = queryRunner.update(sql, "蜘蛛精", "1000"); if (count > 0) { System.out.println("插入成功"); } else { System.out.println("插入失败"); } } catch (SQLException e) { e.printStackTrace(); } } @Test //快速感受DBUtils之更新操作 public void test2() { String sql = "update employee set username=? where id=?"; QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource()); try { int count = queryRunner.update(sql, "蛇精", 12); if (count > 0) { System.out.println("更新成功"); } else { System.out.println("更新失败"); } } catch (SQLException e) { e.printStackTrace(); } } @Test //快速感受DBUtils之删除操作 public void test3() { String sql = "delete from employee where username=?"; QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource()); try { int count = queryRunner.update(sql, "蛇精"); if (count > 0) { System.out.println("刪除成功"); } else { System.out.println("刪除失败"); } } catch (SQLException e) { e.printStackTrace(); } } // 对于R,需要用到ResultSetHandler接口,该接口有9大实现类 }
-
执行查询语句,将其封装成不同的数据方式。
- 编写接口
public interface employeeDao { /** 實現DBUtils的CRUD 包含九种不同类型的查询结果的封装 */ //CUD操作 public void add()throws SQLException; public void update()throws SQLException; public void delete()throws SQLException; //简单的查询操作 //对结果集的封装 public employee findById(int id)throws SQLException; public List<employee> findAll()throws SQLException; public Long findCount()throws SQLException; public String findArrayHandler()throws SQLException; public List<Object[]> findArrayListHandler()throws SQLException; public Map<Integer, employee> findBeanMapHandler()throws SQLException; public Map<Object, Map<String, Object>> findKeyedHandler(int id )throws SQLException; public Map<String, Object> findMapHandler()throws SQLException; public List<Map<String, Object>> findMapListHandler()throws SQLException; }
- 实现接口
public class employeeDaoImpl implements employeeDao { QueryRunner runner = null; public employeeDaoImpl() { runner = new QueryRunner(C3P0Utils.getDataSource()); } @Test //添加一条employee @Override public void add() throws SQLException { String sql = "insert into employee (username , salary) values (?,?) "; int count = runner.update(sql, "太上老君", 12000); if (count > 0) { System.out.println("添加成功"); } else { System.out.println("添加失败"); } } @Test //更新employee @Override public void update() throws SQLException { String sql = "update employee set username=? where id=?"; int count = runner.update(sql, "牛魔王", 11); if (count > 0) { System.out.println("更新成功"); } else { System.out.println("更新失败"); } } @Test //删除employee @Override public void delete() throws SQLException { String sql = "delete from employee where username=?"; int count = runner.update(sql, "牛魔王"); if (count > 0) { System.out.println("刪除成功"); } else { System.out.println("刪除失败"); } } /** * BeanHandler * BeanListHandler * ScalarHandler * ArrayHandler * ArrayListHandler * MapHandler * MapListHandler * BeanMapHandler * KeyedHandler */ // BeanHandler 过id查找employee(结果集BeanHandler) @Override public employee findById(int id) throws SQLException { String sql = "select * from employee where id =?"; employee e = runner.query(sql, new BeanHandler<employee>(employee.class), id); System.out.println(e); return e; } // BeanListHandler 查找所有employee(结果集BeanListHandler) @Override public List<employee> findAll() throws SQLException { String sql = "select * from employee "; List<employee> list = runner.query(sql, new BeanListHandler<employee>(employee.class)); return list; } // ScalarHandler 查找employee的总数(结果集ScalarHandler) @Override public Long findCount() throws SQLException { String sql = "select count(id) from employee "; Long count = runner.query(sql, new ScalarHandler<Long>()); return count; } @Override // ArrayHandler 将结果集第一行数据保存到Object[]中(结果集ArrayHandler) public String findArrayHandler() throws SQLException { String sql = "select * from employee"; Object[] obj = runner.query(sql, new ArrayHandler()); return Arrays.toString(obj); } @Override // ArrayListHandler 将结果集每一条数据,转为Object[],再保存到list集合中(结果集ArrayListHandler) public List<Object[]> findArrayListHandler() throws SQLException { String sql = "select * from employee"; List<Object[]> list = runner.query(sql, new ArrayListHandler()); return list; } @Override // BeanMapHandler 将结果集每一条数据,转为JavaBean对象,再保存到map集合中(结果集BeanMapHandler) public Map<Integer, employee> findBeanMapHandler() throws SQLException { String sql = "select * from employee"; Map<Integer, employee> map = runner.query(sql, new BeanMapHandler<>(employee.class)); return map; } @Override // KeyedHandler 将结果集每一行数据保存到一个“小”map中,key为列名,value该列的值,再将所有“小”map对象保存到一个“大”map中 // “大”map中的key为指定列,value为“小”map对象(结果集KeyedHandler) public Map<Object, Map<String, Object>> findKeyedHandler(int id) throws SQLException { String sql = "select * from employee"; Map<Object, Map<String, Object>> maps = runner.query(sql, new KeyedHandler<>(id)); return maps; } @Override // MapHandler 将结果集第一行数据封装到Map集合中,key是列名,value为该列的值(结果集MapHandler) public Map<String, Object> findMapHandler() throws SQLException { String sql = "select * from employee"; Map<String, Object> map = runner.query(sql, new MapHandler()); return map; } @Override // MapListHandler 将结果集每一行数据保存到map中,key列名 value该列的值 ---- 再将所有map对象保存到List集合中 //(结果集MapListHandler) public List<Map<String, Object>> findMapListHandler() throws SQLException { String sql = "select * from employee"; List<Map<String, Object>> lists = runner.query(sql, new MapListHandler()); return lists; } }
- 测试类
public class Mian { public static void main(String[] args) throws SQLException { employeeDaoImpl emi = new employeeDaoImpl(); //BeanHandler类 // emi.findById(1); //BeanListHandler类 //List<employee> list = emi.findAll(); //System.out.println(list); //ScalarHandler类 //Long count = emi.findCount(); //System.out.println(count); //ArrayHandler类 //String str = emi.findArrayHandler(); //System.out.println(str); //ArrayListHandler类 //List<Object[]> list = emi.findArrayListHandler(); //for (Object[] objects : list) { //System.out.println(Arrays.toString(objects)); //} //BeanMapHandler类 //Map<Integer, employee> map = emi.findBeanMapHandler(); //for (Integer integer : map.keySet()) { //System.out.println(map.get(integer)); //} //KeyedHandler类 //Map<Object, Map<String, Object>> map = emi.findKeyedHandler(1); //for (Object o : map.keySet()) { //Map<String, Object> map1 = map.get(o); //for (String s : map1.keySet()) { //System.out.print(s + "=" + map1.get(s)+"\t"); //} //System.out.println(); // } //MapHandler类 //Map<String, Object> map = emi.findMapHandler(); //System.out.println(map); //MapListHandler类 List<Map<String, Object>> lists = emi.findMapListHandler(); for (Map<String, Object> map : lists) { for (String s : map.keySet()) { System.out.print(s + "=" + map.get(s) + "\t"); } System.out.println(); } } }
Jdbc Template
JdbcTemplate简介
- Spring框架对JDBC的简单封装。提供了一个JDBCTemplate对象简化JDBC的开发
- Spring对数据库的操作在jdbc上面做了深层次的封装,使用spring的注入功能,可以把DataSource注册到JdbcTemplate之中。
- JdbcTemplate位于spring-jdbc-5.0.0.RELEASE.jar中。其全限定命名为org.springframework.jdbc.core.JdbcTemplate。要使用JdbcTemlate还需一个这个包spring-tx-5.0.0.RELEASE.jar包含了一下事务和异常控制。
- 不要忘记导入数据库的连接jar包
JdbcTemplate主要提供以下四类方法
- execute方法:可以用于执行任何SQL语句,一般用于执行DDL语句;
- update方法及batchUpdate方法:update方法用于执行新增、修改、删除等语句;batchUpdate方法用于执行批处理相关语句;
- query方法及queryForXXX方法:用于执行查询相关语句;
- call方法:用于执行存储过程、函数相关语句。
JdbcTemplate的开发步骤
-
导入相应jar包。
-
创建JdbcTemplate对象。依赖于数据源DataSource
Druid的相关介绍:https://blog.csdn.net/SYJ_1835_NGE/article/details/88694434
//DruidUtils是Druid数据库连接池抽取的工具类 //传入数据源 JdbcTemplate template = new JdbcTemplate(DruidUtils.getDataSource());
-
调用JdbcTemplate的方法来完成CRUD的操作
-
update():执行DML语句。增、删、改语句
-
queryForMap():查询结果将结果集封装为map集合,将列名作为key,将值作为value 将这条记录封装为一个map集合
- 注意:这个方法查询的结果集长度只能是1
-
queryForList():查询结果将结果集封装为list集合
- 注意:将每一条记录封装为一个Map集合,再将Map集合装载到List集合中
-
query():查询结果,将结果封装为JavaBean对象
-
query的参数:RowMapper
-
一般我们使用BeanPropertyRowMapper实现类。可以完成数据到JavaBean的自动封装
-
new BeanPropertyRowMapper<类型>(类型.class)
-
List<User> list= template.query(sql, new BeanPropertyRowMapper<User>(User.class));
-
-
queryForObject:查询结果,将结果封装为对象
- 一般用于聚合函数的查询
-
-
创建一个mydb数据库和一个user表:
user | CREATE TABLE `user` ( `id` int(10) NOT NULL AUTO_INCREMENT, `username` varchar(255) DEFAULT NULL, `password` varchar(20) DEFAULT NULL, `score` double(4,2) DEFAULT NULL, `address` varchar(255) DEFAULT NULL, `brith` date DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8
-
编写User实体类
public class User { Integer id; String username; String password; Double score; String address; Date brith; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Double getScore() { return score; } public void setScore(Double score) { this.score = score; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public Date getBrith() { return brith; } public void setBrith(Date brith) { this.brith = brith; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + ", score=" + score + ", address='" + address + '\'' + ", brith=" + brith + '}'; } }
-
执行增删改操作
public class Test1 { private JdbcTemplate template = new JdbcTemplate(DruidUtils.getDataSource()); //1、修改id为1的score为10000 @Test public void test1() { String sql = "update user set score=? where id=?"; int count = template.update(sql, 88.88, 1); if (count > 0) { System.out.println("更新数据成功!!!"); } else { System.out.println("更新数据失败!!!"); } } //2、添加一条记录 @Test public void test2() { String sql = "insert into user values (?,?,?,?,?,?)"; int count = template.update(sql, null, "孙悟空", "222222", "63.36", "广东", "1996-06-11"); if (count > 0) { System.out.println("插入数据成功!!!"); } else { System.out.println("插入数据失败!!!"); } } //3、删除一条记录 @Test public void test3() { String sql = "delete from user where id=?"; int count = template.update(sql, 8); if (count > 0) { System.out.println("删除数据成功!!!"); } else { System.out.println("删除数据失败!!!"); } } }
-
执行查询语句
/** * Spring JdbcTempalte的练习 */ public class Test1 { private JdbcTemplate template = new JdbcTemplate(DruidUtils.getDataSource()); //4、查询数据库为一将其封装成Map集合 @Test public void test4() { String sql = "select * from user where id=?"; Map<String, Object> map = template.queryForMap(sql, 1); System.out.println(map); } //5、查询数据库所有记录将其封装成List @Test public void test5() { String sql = "select * from user "; List<Map<String, Object>> list = template.queryForList(sql); for (Map<String, Object> map : list) { System.out.println(map); } } //6.1、查询数据库所有记录将其封装成指定的对象 @Test public void test6() { String sql = "select * from user "; List<User> list= template.query(sql, new RowMapper<User>() { @Override public User mapRow(ResultSet rs, int i) throws SQLException { User user = new User(); int id = rs.getInt("id"); String username = rs.getString("username"); String password = rs.getString("password"); double score = rs.getDouble("score"); String address = rs.getString("address"); Date brith = rs.getDate("brith"); user.setId(id); user.setUsername(username); user.setPassword(password); user.setScore(score); user.setAddress(address); user.setBrith(brith); return user; } }); for (User user : list) { System.out.println(user); } } //6.2、查询数据库所有记录将其封装成指定的对象 @Test public void test6_1() { String sql = "select * from user "; // 星标重点 List<User> list= template.query(sql, new BeanPropertyRowMapper<User>(User.class)); for (User user : list) { System.out.println(user); } } //7、查询数据库所有记录的数量 @Test public void test7() { String sql = "select count(id) from user "; Long counts = template.queryForObject(sql, Long.class); System.out.println(counts); } }