JDBC进阶使用
JDBC的事务
1. 什么是事务
事务是指逻辑上的一组操作,组成这组操作各个逻辑单元具有不可分割性,要么全部成功,要么全部失败。
2. 事务的操作方法
修饰符 | 方法 | 描述 |
---|---|---|
void | commit() | 使自上次提交/回滚以来所做的所有更改都将永久性,并释放此 Connection 对象当前持有的任何数据库锁。 |
void | setAutoCommit(boolean autoCommit) | 将此连接的自动提交模式设置为给定状态。 |
boolean | getAutoCommit() | 检索此 Connection 对象的当前自动提交模式。 |
void | rollback() | 撤销在当前事务中所做的所有更改,并释放此Connection 对象当前持有的任何数据库锁。(自动提交关闭时可用) |
3. 事务的使用
Connection conn = null;
PreparedStatement pstmt = null;
String name1 = "崔二二";
String name2 = "陈憨憨";
int money = 3000;
try{
//编写sql语句
String sql = "update accounts set money = money + ? where id = (select id from user where user_name = ?)";
//创建连接
conn = JDBCUtils.getConnection();
//!!!!开启事务,并取消自动提交
conn.setAutoCommit(false);
//预编译
pstmt = conn.prepareStatement(sql);
//设置参数
pstmt.setInt(1, money);
pstmt.setString(2, name1);
pstmt.addBatch();
pstmt.executeBatch();
//int i = 1 / 0;
pstmt.setInt(1, -money);
pstmt.setString(2, name2);
pstmt.addBatch();
//执行批处理
pstmt.executeBatch();
//清空批处理
pstmt.clearBatch();
//!!!!提交事务
conn.commit();
} catch (Exception e){
try {
//!!!!!若出现错误,则进行回滚,这个回滚不会滚好像问题不大,因为事务没有执行成功的时候本身就没有进行修改。
conn.rollback();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
e.printStackTrace();
} finally {
JDBCUtils.release(pstmt, conn);
}
JDBC的连接池
1. 什么是连接池
- 连接池是创建和管理连接的缓冲池
- 这些连接准备好被任何需要他们的线程使用
2. 为什么要使用连接池
- 连接池是稀有的
- 连接对象的创建和销毁往往需要消耗不少的资源
- 在服务器初始化的时候就创建好连接池并放入内存中,使用的时候从内存中获取和归还,这样可以极高的提高运行效率
3. 连接池的基本原理
4. 自定义连接池
1)自定义连接池实现的步骤
- 实现
DataSource
接口
修饰符 | 方法 | 描述 |
---|---|---|
Connection | getConnection() | 尝试建立与此 DataSource 对象所代表的数据源的连接。 |
Connection | getConnection(String username, String password) | 尝试建立与此 DataSource 对象所代表的数据源的连接。 |
- 初始化多个连接到内存中
- 实现归还连接的方法
2)自定义连接池的代码实现
package com.Utils;
import javax.sql.DataSource;
import java.io.PrintWriter;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
/**
* @author YanceyGao
* @createTime 2020/11/14 23:00
* @className MyDataSource
* @description 连接池工具类
* @packageName MyDataSource.java
*/
public class MyDataSource implements DataSource {
private List<Connection> connList = new ArrayList<Connection>();
/**
* @author YanceyGao
* @createTime 2020/11/15 16:33
* @methodName MyDataSource
* @description 初始化连接池
* @param: null
* @return: null
*/
public MyDataSource() throws SQLException {
for(int i = 1; i <= 3; ++i){
connList.add(JDBCUtils.getConnection());
}
}
/**
* @author YanceyGao
* @createTime 2020/11/15 16:34
* @methodName getConnection
* @description 获取链接
* @param: null
* @return: java.sql.Connection
*/
@Override
public Connection getConnection() throws SQLException {
//通过remove实现获取到连接的同时,在连接池中删除连接
Connection conn = connList.remove(0);
return conn;
}
/**
* @author YanceyGao
* @createTime 2020/11/15 16:34
* @methodName getConnection
* @description 获取连接
* @param1 username: 用户名
* @param2 password: 密码
* @return: java.sql.Connection
*/
@Override
public Connection getConnection(String username, String password) throws SQLException {
return null;
}
/**
* @author YanceyGao
* @createTime 2020/11/15 16:35
* @methodName addBackConnection
* @description 返还连接
* @param1 conn: 要返还的连接
* @return: void
*/
public void addBackConnection(Connection conn){
connList.add(conn);
}
/**
* @author YanceyGao
* @createTime 2020/11/15 16:48
* @methodName release
* @description 销毁Statement,归还连接
* @param1 stmt:Statement
* @param2 conn:连接
* @return: void
*/
public void release(Statement stmt, Connection connection){
//it is a good idea to release
//resources in a finally() block
//in reverse-order of their creation
//if they are no-longer needed
if(stmt != null){
try{
stmt.close();
}catch(SQLException sqlEx){
//ignore
sqlEx.printStackTrace();
}
stmt = null;
}
this.addBackConnection(connection);
}
/**
* @author YanceyGao
* @createTime 2020/11/15 16:50
* @methodName release
* @description 归还连接
* @param1 rs: 结果集
* @param2 stmt:Statement
* @param3 conn:连接
* @return: void
*/
public void release(ResultSet rs, Statement stmt, Connection conn){
//it is a good idea to release
//resources in a finally() block
//in reverse-order of their creation
//if they are no-longer needed
if(rs != null){
try{
rs.close();
}catch(SQLException sqlEx){
//ignore
}
rs = null;
}
if(stmt != null){
try{
stmt.close();
}catch(SQLException sqlEx){
//ignore
sqlEx.printStackTrace();
}
stmt = null;
}
this.addBackConnection(conn);
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
return null;
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return false;
}
@Override
public PrintWriter getLogWriter() throws SQLException {
return null;
}
@Override
public void setLogWriter(PrintWriter out) throws SQLException {
}
@Override
public void setLoginTimeout(int seconds) throws SQLException {
}
@Override
public int getLoginTimeout() throws SQLException {
return 0;
}
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
return null;
}
}
3)自定义连接池的使用
package com.RunTestDemo;
import com.Utils.JDBCUtils;
import com.Utils.MyDataSource;
import javax.sql.DataSource;
import java.io.PrintWriter;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
/**
* @author YanceyGao
* @createTime 2020/11/14 23:06
* @className JDBCConnectionPoolDemo
* @description JDBC连接池测试
* @packageName JDBCConnectionPoolDemo.java
*/
public class JDBCConnectionPoolDemo {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
MyDataSource myDataSource = null;
try {
//实例化工具类
myDataSource = new MyDataSource();
//获得连接
connection = myDataSource.getConnection();
//编写sql
String sql = "select * from user";
//预编译
preparedStatement = connection.prepareStatement(sql);
resultSet = preparedStatement.executeQuery();
while(resultSet.next()){
System.out.print(resultSet.getInt("id") + "\t");
System.out.print(resultSet.getString("user_name") + "\t");
System.out.print(resultSet.getString("user_sex") + "\t");
System.out.println(resultSet.getInt("user_age"));
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
myDataSource.release(resultSet, preparedStatement, connection);
}
}
}
4)自定义连接池的常见问题
-
使用接口的实现类完成的构造
-
MyDataSource myDataSource = new MyDataSource();
-
这种写法不方便程序的扩展。
-
-
额外提供了方法(归还链接)
-
myDataSource.release(resultSet, preparedStatement, connection);
-
这种方式增加了连接池使用的难度
-
5)常见问题的解决
- 使用接口名实现接口
- 不提供额外的方法,可以选择增强原来的类中的方法
- 方法一:
- 概述:采用继承的方式,继承原有的类并重写原方法
- 条件:只能增强可以实例化的类(比如驱动包中实现的接口类就无法使用该方式,mysql.Connection就不行)
- 方法二:
- 概述:采用装饰者模式,就是包装
- 条件:
- 增强的类和被增强的类要实现相同的接口
- 在增强的类中获得被增强的类的引用
- 方法三:
- 概述:使用动态代理
- 方法一:
装饰者模式概述:
允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
6)通过装饰者模式增强Connection实现类
- 继承原有Connection的接口
- 获取创建的连接
- 增强close()方法
package com.Utils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
/**
* @author YanceyGao
* @createTime 2020/11/16 10:15
* @className MyConnectionWrapper
* @description 使用装饰者模式增强Connection接口实现类中的Close方法
* @packageName MyConnectionWrapper.java
*/
public class MyConnectionWrapper extends ConnectionTemplate {
//ConnectionTemplate为模板类,只是继承并返回了原有的值
private List<Connection> connectionList = null;
Connection connection = null;
public MyConnectionWrapper(Connection connection, List<Connection> connectionList){
super(connection);
this.connection = connection;
this.connectionList = connectionList;
}
/**
* @author YanceyGao
* @createTime 2020/11/16 9:01
* @methodName close
* @description 增强close方法
* @param: null
* @return: void
*/
@Override
public void close() throws SQLException {
//super.close();
this.connectionList.add(connection);
}
}
- 使用
/**
* @author YanceyGao
* @createTime 2020/11/15 16:34
* @methodName getConnection
* @description 获取链接
* @param: null
* @return: java.sql.Connection
*/
@Override
public Connection getConnection() throws SQLException {
//通过remove实现获取到连接的同时,在连接池中删除连接
Connection conn = connList.remove(0);
MyConnectionWrapper myConnectionWrapper = new MyConnectionWrapper(conn, connList);
return myConnectionWrapper;
}
5. 开源连接池的使用
1)Druid(德鲁伊)
- 阿里巴巴旗下的开源连接池(数据源),可以通过Spring框架进行快速整合。
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
DruidDataSource druidDataSource = null;
DataSource dataSource = null;
Properties properties = new Properties();
try {
properties.load(new FileInputStream("src/main/java/mysqlConnectionUtils.properties"));
//实例化德鲁伊
druidDataSource = new DruidDataSource();
//手动设置连接参数,像个憨憨一样
// druidDataSource.setUrl(properties.getProperty("url"));
// druidDataSource.setUsername(properties.getProperty("username"));
// druidDataSource.setPassword(properties.getProperty("password"));
// druidDataSource.setDriverClassName(properties.getProperty("driverClassName"));
//自动配置连接参数,通过德鲁伊的数据源工厂加载配置文件
dataSource = DruidDataSourceFactory.createDataSource(properties);
//获取连接
//connection = druidDataSource.getConnection();
connection = dataSource.getConnection();
String sql = "select user.id, user_name, user_age, user_sex, user_tele, money from accounts, user where accounts.id = user.id";
preparedStatement = connection.prepareStatement(sql);
resultSet = preparedStatement.executeQuery();
while(resultSet.next()){
System.out.print(resultSet.getInt("id") + "\t");
System.out.print(resultSet.getString("user_name") + "\t");
System.out.print(resultSet.getInt("user_age") + "\t");
System.out.print(resultSet.getString("user_sex") + "\t");
System.out.print(resultSet.getString("user_tele") + "\t");
System.out.println(resultSet.getInt("money"));
}
} catch (SQLException | FileNotFoundException throwables) {
throwables.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.release(resultSet, preparedStatement, connection);
}
2)C3P0
- C3P0是一个开源的连接池,它实现了数据源和JNDI的绑定,支持JDBC3规范和JDBC2的标准扩展,目前使用它的开源项目有Hibernate、Spring等。
//代码使用的是手动配置的方式,因为idea的自动配置不知道怎么回事,无法加载配置文件,后面找到原因后会进行更新
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
//创建连接池
ComboPooledDataSource dataSource = new ComboPooledDataSource();
Properties properties = new Properties();
try {
//c3p0不需要获取配置文件,在创建连接池时会自动在类路径下自动查找属性文件
properties.load(new FileInputStream("src/main/java/mysqlConnectionUtils.properties"));
//配置参数
dataSource.setDriverClass(properties.getProperty("driverClassName"));
dataSource.setJdbcUrl(properties.getProperty("url"));
dataSource.setUser(properties.getProperty("username"));
dataSource.setPassword(properties.getProperty("password"));
connection = dataSource.getConnection();
String sql = "select user.id, user_name, user_age, user_sex, user_tele, money from accounts, user where accounts.id = user.id";
preparedStatement = connection.prepareStatement(sql);
resultSet = preparedStatement.executeQuery();
while(resultSet.next()){
System.out.print(resultSet.getInt("id") + "\t");
System.out.print(resultSet.getString("user_name") + "\t");
System.out.print(resultSet.getInt("user_age") + "\t");
System.out.print(resultSet.getString("user_sex") + "\t");
System.out.print(resultSet.getString("user_tele") + "\t");
System.out.println(resultSet.getInt("money"));
}
} catch (SQLException | PropertyVetoException | FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
JDBCUtils.release(resultSet, preparedStatement, connection);
}
6. DBUtils
1)DBUtils概述
- DBUtils是Apache提供的一个对JDBC进行简单封装的开源工具类库,使用它能够简化JDBC应用程序的开发。同时,也不会影响程序的性能。
- 因为JDBC有大量重复代码,比如获得连接,预编译SQL,释放资源等,往往自行封装浪费了不少时间因此将类似的工具类进行封装,可以减少重复开发。
2)DBUtils的API概述
a. QueryQunner对象:核心运行类
构造函数
//无参,有事务管理时使用
public QueryRunner() {}
//有参,无事务管理时使用
public QueryRunner(DataSource ds) {
super(ds);
}
方法
//插入方法,可以进行增删改,有事务管理时使用
public int update(Connection conn, String sql, Object... params)
//插入方法重载,无事务管理时使用
public int update(String sql, Object... params)
//查询方法,无事务管理时使用
public <T> T query(String sql, ResultSetHandler<T> rsh, Object... params)
//查询方法重载,有事务管理时使用
public <T> T query(Connection conn, String sql, ResultSetHandler<T> rsh, Object... params)
//批处理
public int[] batch(Connection conn, String sql, Object[][] params)
//批处理重载
public int[] batch(String sql, Object[][] params)
b. DBUtils对象:事务操作
方法
//事务提交
public static void commitAndCloseQuietly(Connection conn)
//事务回滚
public static void rollbackAndCloseQuietly(Connection conn)
3)DBUtils的使用
package com.RunTestDemo;
import com.Domain.Account;
import com.Utils.JDBCUtils;
import com.Utils.JDBCUtilsPro;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;
import org.omg.PortableInterceptor.SYSTEM_EXCEPTION;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
* @author YanceyGao
* @createTime 2020/11/17 9:57
* @projectName DemoTest
* @packageName com.RunTestDemo
* @className JDBCDBUtilsTestDemo
* @description DBUtils的使用
*/
public class JDBCDBUtilsTestDemo {
public static void main(String[] args) throws SQLException {
JDBCDBUtilsTestDemo jdbcdbUtilsTestDemo = new JDBCDBUtilsTestDemo();
String sql = "insert into user values(null, ?, ?, ?, ?)";
// jdbcdbUtilsTestDemo.insertTest(sql);
jdbcdbUtilsTestDemo.selectTest("select * from user where id in(?, ?, ?, ?, ?)");
}
/**
* @author YanceyGao
* @createTime 2020/11/18 8:37
* @methodName selectTest
* @description 查询
* @param1 sql: SQL语句
* @return: void
*/
public void selectTest(String sql) throws SQLException {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
DataSource source = JDBCUtilsPro.getDataSource();
QueryRunner queryRunner = new QueryRunner(source);
//Account是一个封装好的实体对象,内容是数据库中表accounts的属性和get、set方法。
final List<Account> accountList = queryRunner.query(sql, new ResultSetHandler<List<Account>>(){
@Override
public List<Account> handle(ResultSet resultSet) throws SQLException {
List<Account> accountList = new ArrayList();
while(resultSet.next()){
Account account = new Account();
account.setId(resultSet.getInt("id"));
account.setUserName(resultSet.getString("user_name"));
account.setUserSex(resultSet.getString("user_sex"));
account.setUserAge(resultSet.getInt("user_age"));
account.setUserTele(resultSet.getString("user_tele"));
accountList.add(account);
}
return accountList;
}
}, 1, 2, 3, 4, 5);
for(Account account : accountList){
System.out.println(account);
/*System.out.print(account.getId() + "\t");
System.out.print(account.getUserName() + "\t");
System.out.print(account.getUserSex() + "\t");
System.out.print(account.getUserAge() + "\t");
System.out.println(account.getUserTele());*/
}
}
/**
* @author YanceyGao
* @createTime 2020/11/17 10:30
* @methodName insertTest
* @description 插入操作
* @param: null
* @return: void
*/
public void insertTest(String sql) throws SQLException {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
DataSource source = JDBCUtilsPro.getDataSource();
QueryRunner queryRunner = new QueryRunner(source);
int ans = queryRunner.update(sql, "嘤嘤嘤", "female", 21, "187-9876-5678");
System.out.println(ans);
/*
while(rs.next()){
System.out.print(rs.getInt("id") + " ");
System.out.print(rs.getString("user_name") + " ");
System.out.print(rs.getString("user_sex") + " ");
System.out.print(rs.getInt("user_age") + " ");
System.out.println(rs.getString("user_tele"));
}
*/
}
}
package com.Utils;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
/**
* @author YanceyGao
* @createTime 2020/11/17 10:04
* @projectName DemoTest
* @packageName com.Utils
* @className JDBCUtilsPro
* @description JDBCUtilsPro使用了Druid的连接池。
*/
public class JDBCUtilsPro {
private static final Properties properties = new Properties();
private static List<Connection> connList = new ArrayList<Connection>();
private static DataSource dataSource = null;
static{
try {
properties.load(new FileInputStream("src/main/java/mysqlConnectionUtils.properties"));
dataSource = DruidDataSourceFactory.createDataSource(properties);;
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* @author YanceyGao
* @createTime 2020/11/17 10:13
* @methodName getConnection
* @description 获得连接
* @param: null
* @return: java.sql.Connection
*/
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
/**
* @author YanceyGao
* @createTime 2020/11/17 10:13
* @methodName getDataSource
* @description 获得连接池
* @param: null
* @return: javax.sql.DataSource
*/
public static DataSource getDataSource(){
return dataSource;
}
/**
* @author YanceyGao
* @createTime 2020/11/17 10:14
* @methodName release
* @description 归还链接
* @param1 rs: 结果集
* @param2 stmt: 执行
* @param3 conn: 连接
* @return: void
*/
public static void release(ResultSet rs, Statement stmt, Connection conn){
//it is a good idea to release
//resources in a finally() block
//in reverse-order of their creation
//if they are no-longer needed
if(rs != null){
try{
rs.close();
}catch(SQLException sqlEx){
//ignore
}
rs = null;
}
if(stmt != null){
try{
stmt.close();
}catch(SQLException sqlEx){
//ignore
sqlEx.printStackTrace();
}
stmt = null;
}
if(conn != null){
try{
conn.close();
}catch(SQLException sqlEx){
//ignore
sqlEx.printStackTrace();
}
conn = null;
}
}
}
4)ResultSetHandler的使用
a. BeanHandler和BeanListHandler
BeanHandler
将一条记录封装到一个JavaBean中
BeanListHandler
将多条记录封装到一个装有JavaBean的List集合中
/**
* @author YanceyGao
* @createTime 2020/11/18 9:14
* @methodName useBeanHandler
* @description 多条记录封装
* @param1 sql:
* @return: void
*/
public void useBeanHandler(String sql) throws SQLException {
QueryRunner queryRunner = new QueryRunner(JDBCUtilsPro.getDataSource());
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
//通过Bean方式实现的话,Account属性名称要和数据库中属性名称一致。不光属性名要一样,get和set方法名也要一样,淦
List<Account> accountList = queryRunner.query(sql, new BeanListHandler<Account>(Account.class), 1, 2, 3, 4, 5);
//要想这样输出必须重写类的toString()方法,不然默认调用Object的toString()方法输出
// 这样输出结果为account.getClass().getName() + '@' + Integer.toHexString(hashCode()).
//就是类的名字加上16进制的哈希值。
for(Account account : accountList){
System.out.println(account);
/*System.out.print(account.getId() + "\t");
System.out.print(account.getUser_name() + "\t");
System.out.print(account.getUser_sex() + "\t");
System.out.print(account.getUser_age() + "\t");
System.out.println(account.getUser_tele());*/
}
}
b. MapHandler和MapListHandler
MapHandler
将一条记录封装到一个Map集合中,Map的key是列名,Map的value就是表中列的记录。
MapListHandler
将多条记录封装到一个装有Map的List集合中。
/**
* @author YanceyGao
* @createTime 2020/11/18 9:18
* @methodName useMapHandler
* @description mapHander的使用
* @param1 sql: sql语句
* @return: void
*/
public void useMapHandler(String sql) throws SQLException {
QueryRunner queryRunner = new QueryRunner(JDBCUtilsPro.getDataSource());
List<Account> ans = new ArrayList<Account>();
List<Map<String, Object>> mapList = queryRunner.query(sql, new MapListHandler(), 1, 2, 3, 4, 5);
for(Map<String, Object> map : mapList){
Account account = new Account();
account.setId((Integer) map.get("id"));
account.setUser_name((String) map.get("user_name"));
account.setUser_sex((String) map.get("user_sex"));
account.setUser_age((Integer) map.get("user_age"));
account.setUser_tele((String) map.get("user_tele"));
ans.add(account);
}
for(Account account : ans){
System.out.println(account);
}
}
c. ColumnListHandler、ScalarHandler、KeyedHandler
ColumnListHandler
将数据中的某列封装到List集合中。
/**
* @author YanceyGao
* @createTime 2020/11/18 9:37
* @methodName useColumnHandler
* @description ColumnHandler的使用
* @param1 sql:
* @return: void
*/
public void useColumnHandler(String sql) throws SQLException {
QueryRunner queryRunner = new QueryRunner(JDBCUtilsPro.getDataSource());
//为了维持数据的通用性,最好用Object
List<Object> name = queryRunner.query(sql, new ColumnListHandler<Object>("user_name"), 1, 2, 3, 4, 5);
for(Object account : name){
System.out.println(account);
}
}
ScalarHandler
将单个值进行封装。
/**
* @author YanceyGao
* @createTime 2020/11/18 9:41
* @methodName useScalarHandler
* @description ScalarHander的使用,单值封装
* @param1 sql: SQL语句
* @return: void
*/
public void useScalarHandler(String sql) throws SQLException {
QueryRunner queryRunner = new QueryRunner(JDBCUtilsPro.getDataSource());
//注意sql使用Count聚合函数返回值为long类型,不能使用Integer接收。
Object query = queryRunner.query(sql, new ScalarHandler<Object>(), 1, 2, 3);
System.out.println(query);
}
KeyedHandler
将一条记录封装到一个Map集合中,将多条记录封装到一个装有Map集合的Mao集合中,并且外层的Map的key自定义。和MapListHandler的区别是,KeyedHandler外层是Map(好一个套娃小能手),MapListHandler外层是List。
/**
* @author YanceyGao
* @createTime 2020/11/18 9:56
* @methodName useKeyedHandler
* @description keyedHandler的使用,套娃是Map,可以指定外层key值
* @param1 sql:sql语句
* @return: void
*/
public void useKeyedHandler(String sql) throws SQLException {
QueryRunner queryRunner = new QueryRunner(JDBCUtilsPro.getDataSource());
//指定key值
Map<Object, Map<String, Object>> mapMap = queryRunner.query(sql, new KeyedHandler<Object>("user_name"), 1, 2, 3, 4, 5);
System.out.println(mapMap);
}
Q.E.D.