JDBC的事务环境准备
事务指的是逻辑上的一组操作,组成这组操作各个逻辑单元要么全都成功,要么全都失败。
- 创建数据库和表
CREATE TABLE `account` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
`money` double DEFAULT NULL,
PRIMARY KEY (`id`)
)
- 添加数据
INSERT INTO account VALUES (NULL,'aaa',10000);
INSERT INTO account VALUES (NULL,'bbb',10000);
INSERT INTO account VALUES (NULL,'ccc',10000);
JDBC的事务管理
编写转账的案例,账户aaa给bbb转账1000元
@Test
/**
* 完成转账的案例
*/
public void demo1() {
Connection conn = null;
PreparedStatement pstmt = null;
try {
/**
* 完成转账代码: *扣除某个账号的钱 *给另外一个账号加钱
*/
// 获得连接
conn = JDBCUtils.getConnection();
// 编写SQL语句
String sql = "update account set money=money+? where name=?";
// 预编译SQL
pstmt = conn.prepareStatement(sql);
// 设置参数
// 用aaa账号给bbb账号转1000元
pstmt.setDouble(1, -1000);
pstmt.setString(2, "aaa");
// 执行SQL扣除aaa账号的1000元
pstmt.executeUpdate();
// 给bbb账号加钱
pstmt.setDouble(1, 1000);
pstmt.setString(2, "bbb");
// 执行SQLbbb账号添加1000元
pstmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
// 释放资源
JDBCUtils.release(pstmt, conn);
}
}
运行结果:
数据库显示,aaa转账减去1000,bbb增加1000。
这是正常的操作,没有错误,如果在执行的过程中有错误出现是什么情况那?数据还会不会扣除和增加那?
修改代码:
在扣除和转账之间添加一个错误
// 用aaa账号给bbb账号转1000元
pstmt.setDouble(1, -1000);
pstmt.setString(2, "aaa");
// 执行SQL扣除aaa账号的1000元
pstmt.executeUpdate();
int i = 1 / 0;
// 给bbb账号加钱
pstmt.setDouble(1, 1000);
pstmt.setString(2, "bbb");
// 执行SQLbbb账号添加1000元
运行结果:
控制台显示报错
但是数据库中显示aaa账号的钱已经被扣掉了,但是bbb账号的钱并没有增加。
那怎么解决那?解决办法就添加事务。
事务的管理API:
在转账中添加事务管理
先将数据库中的money全部更改为10000
@Test
/**
* 完成转账的案例
*/
public void demo1() {
Connection conn = null;
PreparedStatement pstmt = null;
try {
/**
* 完成转账代码: *扣除某个账号的钱 *给另外一个账号加钱
*/
// 获得连接
conn = JDBCUtils.getConnection();
// 开启事务
conn.setAutoCommit(false);
// 编写SQL语句
String sql = "update account set money=money+? where name=?";
// 预编译SQL
pstmt = conn.prepareStatement(sql);
// 设置参数
// 用aaa账号给bbb账号转1000元
pstmt.setDouble(1, -1000);
pstmt.setString(2, "aaa");
// 执行SQL扣除aaa账号的1000元
pstmt.executeUpdate();
int i = 1 / 0;
// 给bbb账号加钱
pstmt.setDouble(1, 1000);
pstmt.setString(2, "bbb");
// 执行SQLbbb账号添加1000元
pstmt.executeUpdate();
// 提交事务
conn.commit();
} catch (Exception e) {
// 回滚事务
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
} finally {
// 释放资源
JDBCUtils.release(pstmt, conn);
}
}
运行结果:
控制台提示错误
数据库数据没有任何改变,说明事务管理已经生效,发生错误时数据回滚成功。
连接池的概述
什么是连接池
连接池是装有连接的容器,使用连接的话,可以从连接池中进行获取,使用完成之后将连接归还给连接池。
为什么学习连接池
连接对象创建和销毁是需要耗费时间的,在服务器初始化的时候就初始化一些连接。把这些连接放入到内存中,使用的时候可以从内存中获取,使用完成之后将连接放入连接池中。从内存中获取和归还的效率要远远高于创建和销毁的效率。(提升性能)。
连接池原理
Druid开源连接池的使用
Druid的概述
Druid阿里旗下开源连接池产品,使用非常简单,可以与Spring框架进行快速整合。
使用Druid连接池,连接数据库时JDBC工具类中就不需要写连接方法了,因为我们使用的是Druid连接,JDBC工具类中写一个释放资源的方法就可以了。
使用时引入相关的jar包
Druid的使用-手动设置数据库连接的参数
代码示例:
使用DruidDataSource对象连接数据库,手动设置数据连接的参数。
@Test
public void demo1() {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
// 使用连接池,创建连接池对象
DruidDataSource dds = new DruidDataSource();
// 手动设置数据库连接的参数
dds.setDriverClassName("com.mysql.cj.jdbc.Driver");
dds.setUrl(" jdbc:mysql://localhost:3306/jdbc?useSSL=false&serverTimezone=UTC");
dds.setUsername("root");
dds.setPassword("123456");
// 获得连接
conn = dds.getConnection();
// 编写SQL语句
String sql = "select * from account";
// 预编译SQL
pstmt = conn.prepareStatement(sql);
// 执行SQL
rs = pstmt.executeQuery();
// 遍历结果集
while (rs.next()) {
System.out.println(rs.getInt("id") + " " + rs.getString("name") + " " + rs.getInt("money"));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//使用工具类释放资源
JDBCUtils.release(rs, pstmt, conn);
}
}
运行结果:
Druid的使用-属性文件设置数据库连接的参数
创建属性文件:
文件名称没有规定但是属性文件中的key要一定的。
文件名:db.properties
#驱动程序名
driverClassName = com.mysql.cj.jdbc.Driver
#URL指向要访问的数据库名
url = jdbc:mysql://localhost:3306/jdbc?useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true
#MySQL配置时的用户名
username = root
# MySQL配置时的密码
password = 123456
代码实现:
@Test
public void demo2() {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
// 使用连接池
// 从属性文件中获取
Properties pr = new Properties();
pr.load(new FileInputStream("src/db.properties"));// 使用web项目时更换为InputStream
DataSource ds = DruidDataSourceFactory.createDataSource(pr);
// 获得连接
conn = ds.getConnection();
// 编写SQL语句
String sql = "select * from account";
// 预编译SQL
pstmt = conn.prepareStatement(sql);
// 执行SQL
rs = pstmt.executeQuery();
// 遍历结果集
while (rs.next()) {
System.out.println(rs.getInt("id") + " " + rs.getString("name") + " " + rs.getInt("money"));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//使用工具类释放资源
JDBCUtils.release(rs, pstmt, conn);
}
}
运行结果:
连接成功
c3p0连接池的使用
使用时引入相关的jar包
c3p0的使用-手动设置数据库连接的参数
代码示例:
@Test
/**
* 手动设置参数的方式
*/
public void demo1() {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
// 获得连接:从连接池中获取
// 创建连接池
ComboPooledDataSource ds = new ComboPooledDataSource();
// 手动设置连接参数
ds.setDriverClass("com.mysql.cj.jdbc.Driver");
ds.setJdbcUrl("jdbc:mysql://localhost:3306/jdbc?useSSL=false&serverTimezone=UTC");
ds.setUser("root");
ds.setPassword("123456");
// 从连接池中获取连接
conn = ds.getConnection();
// 编写SQL
String sql = "select * from account";
// 预编译SQL
pstmt = conn.prepareStatement(sql);
// 执行SQL
rs = pstmt.executeQuery();
// 遍历结果集
while (rs.next()) {
System.out.println(rs.getInt("id") + " " + rs.getString("name") + " " + rs.getInt("money"));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 使用JDBC工具类释放资源
JDBCUtils.release(rs, pstmt, conn);
}
}
运行结果:
c3p0的使用-XML文件设置数据库连接的参数
使用XML文件设置数据库连接的参数必须有固定的XML文件名称才可以使用:c3p0-config.xml
创建c3p0-config.xml文件:
c3p0配置详解
在c3p0中&分隔符要更换成 & ;
<c3p0-config>
<!-- 默认配置,如果没有指定则使用这个配置 -->
<default-config>
<property name="driverClass">com.mysql.cj.jdbc.Driver</property>
<property name="jdbcUrl">
jdbc:mysql://localhost:3306/jdbc?useSSL=false&serverTimezone=UTC
</property>
<property name="user">root</property>
<property name="password">123456</property>
<property name="checkoutTimeout">30000</property>
<property name="idleConnectionTestPeriod">30</property>
<property name="initialPoolSize">3</property>
<property name="maxIdleTime">30</property>
<property name="maxPoolSize">100</property>
<property name="minPoolSize">2</property>
<property name="maxStatements">200</property>
</default-config>
</c3p0-config>
代码实现:
@Test
/**
* XML文件设置数据库连接的参数
*/
public void demo2() {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
// 获得连接:从连接池中获取
// 创建连接池,创建连接池默认去类路径下查找c3p0-config.xml
ComboPooledDataSource ds = new ComboPooledDataSource();
// 从连接池中获取连接
conn = ds.getConnection();
// 编写SQL
String sql = "select * from account";
// 预编译SQL
pstmt = conn.prepareStatement(sql);
// 执行SQL
rs = pstmt.executeQuery();
// 遍历结果集
while (rs.next()) {
System.out.println(rs.getInt("id") + " " + rs.getString("name") + " " + rs.getInt("money"));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 使用JDBC工具类释放资源
JDBCUtils.release(rs, pstmt, conn);
}
}
运行结果:
更改工具类
连接池对象应该是一个应用只创建一次就可以的,不需要每次使用都创建一个新的连接池。
修改后的工具类:
将static代码块去掉,注册驱动方法去掉,修改获得连接的方法,添加一个获得连接池的方法,保留释放资源的两个方法。
使用的是c3p0的连接池
/**
* JDBC的工具类
*
* @author 25858
*
*/
public class JDBCUtils2 {
// 创建连接池,创建连接池默认去类路径下查找c3p0-config.xml
// 创建一个连接池:但是这个连接池只创建一次即可。
private static final ComboPooledDataSource ds = new ComboPooledDataSource();
/**
* 获得连接的方法
*
* @throws SQLException
*/
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
/**
* 获得连接池
*/
public static DataSource getDataSource() {
return ds;
}
/**
* 释放资源的方法
*/
public static void release(Statement stmt, Connection conn) {
if (stmt != null) {
try {
stmt.close();
System.out.println("释放Statement成功");
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if (conn != null) {
try {
conn.close();
System.out.println("释放Connection成功");
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
public static void release(ResultSet rs, Statement stmt, Connection conn) {
if (rs != null) {
try {
rs.close();
System.out.println("释放ResultSet成功");
} catch (SQLException e) {
e.printStackTrace();
}
rs = null;
}
if (stmt != null) {
try {
stmt.close();
System.out.println("释放Statement成功");
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if (conn != null) {
try {
conn.close();
System.out.println("释放Connection成功");
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
}
测试类:
@Test
/**
* 使用新的工具类的测试
*/
public void demo2() {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
// 获得连接:从连接池中获取
// 从连接池中获取连接
conn = JDBCUtils2.getConnection();
// 编写SQL
String sql = "select * from account";
// 预编译SQL
pstmt = conn.prepareStatement(sql);
// 执行SQL
rs = pstmt.executeQuery();
// 遍历结果集
while (rs.next()) {
System.out.println(rs.getInt("id") + " " + rs.getString("name") + " " + rs.getInt("money"));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 使用JDBC工具类释放资源
JDBCUtils2.release(rs, pstmt, conn);
}
}
运行结果:
JDBC框架-DBUtils
DbUtils jar包下载
JDBC框架——DBUtils
什么是DBUtils
对JDBC的简单封装,而且没有影响性能。
为什么学习DBUtils
因为JDBC手写比较麻烦,而且有非常多的代码是类似的。比如获得连接,预编译SQL,释放资源等.那么可以将这些代码抽取出来放到工具类中。将类似的代码进行抽取。大大简化JDBC的编程。
DBUtils的API
QueryRunner对象:核心运行类
- 构造方法:
默认的构造方法
需要一个javax.sql.DataSource来作参数的构造方法。
- 方法
执行给定的插入、更新或删除SQL语句。
执行SQL插入、更新或删除查询。
执行给定的SELECT SQL查询并返回一个结果对象。
执行带有替换参数的SQL SELECT查询。
在一般情况下如果执行CRUD的操作使用:
构造方法:
QuerxBunner(DataSource da);
方法:
int update(String sq1,Obiect...axga) ;
T query(String sq1. ResultSetHandler rsh,0biect...arga);
如果有事务管理的话使用另一套完成CRUD操作:
构造方法:
QueryBunner();
方法:
int update(Connection conn,String sql,0biect...arga) ;
T guery(Connection conn,String sql.ReaultSetHandler rsh,obiect...arga) ;
执行一批SQL插入、更新或删除查询。
DbUtils对象
提交一个连接,然后关闭它,如果为空则避免关闭,并隐藏发生的任何SQLExceptions。
对连接执行回滚,然后关闭它,如果为空则避免关闭,并隐藏发生的任何SQLExceptions。
DbUtils的使用之增删改的操作
DbUtils的增删改都是同一种操作,只是SQL语句不同而已。
DbUtils的添加操作
代码示例:
@Test
/**
* 添加操作
*/
public void demo1() {
// 创建核心类:QueryRunner
QueryRunner qr = new QueryRunner(JDBCUtils2.getDataSource());// 通过JDBC工具类获得连接池
try {
//执行添加SQL语句
qr.update("insert into account values (null,?,?)", "ddd", 10000);
} catch (SQLException e) {
e.printStackTrace();
}
}
运行结果:
数据库显示添加成功
DbUtils的修改操作
代码示例:
@Test
/**
* 修改操作
*/
public void demo2() {
// 创建核心类:QueryRunner
QueryRunner qr = new QueryRunner(JDBCUtils2.getDataSource());// 通过JDBC工具类获得连接池
try {
//执行修改SQL语句
qr.update("update account set name=?,money=? where name=?", "eee", 100, "ddd");
} catch (SQLException e) {
e.printStackTrace();
}
}
运行结果:
数据库显示修改成功
DbUtils的删除操作
@Test
/**
* 删除操作
*/
public void demo3() {
// 创建核心类:QueryRunner
QueryRunner qr = new QueryRunner(JDBCUtils2.getDataSource());// 通过JDBC工具类获得连接池
try {
//执行删除SQL语句
qr.update("delete from account where name=?", "eee");
} catch (SQLException e) {
e.printStackTrace();
}
}
运行结果:
数据库显示删除成功
DbUtils的使用之查询的操作
我们之前在做查询的时候,是拿到结果集,直接在遍历的过程中就将数据输出到控制台上了。
但是打印到控制台上并不是我们的目的,目的是我们拿到数据将它存起来,然后在我们想用的地方再显示出来,比如说在页面中把一些相关的信息展现出来。
查询一条记录时,封装到对象中。
查询多条数据时,一般封装到装有对象的集合当中。
查询一条记录
查询一条记录时,封装到对象中。
**ResultSetHandler< T >**是一个结果集的处理接口,需要我们自己使用匿名内部类(handle)的方式把结果集封装。
将ResultSet(结果集)转换为对象。
代码示例:
创建一个用于封装数据的对象类
public class Account {
private Integer id;
private String name;
private double money;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
@Override
public String toString() {
return "Account [id=" + id + ", name=" + name + ", money=" + money + "]";
}
}
测试类:
@Test
/**
* 查询一条记录的操作
*/
public void demo1() {
// 创建核心类:QueryRunner
QueryRunner qr = new QueryRunner(JDBCUtils2.getDataSource());// 通过JDBC工具类获得连接池
try {
// 执行查询
//将结果集返回到封装的对象类中
Account account = qr.query("select * from account where name=?", new ResultSetHandler<Account>() {
@Override
public Account handle(ResultSet rs) throws SQLException {
//创建Account对象用于将数据封装到对象中
Account account = new Account();
// 遍历结果集
//因为是查询一条记录,使用可以使用if也可以使用while
if(rs.next()) {
//将结果集的数据封装到对象中
account.setId(rs.getInt("id"));
account.setName(rs.getString("name"));
account.setMoney(rs.getDouble("money"));
}
return account;
}
}, "aaa");
System.out.println(account);
} catch (SQLException e) {
e.printStackTrace();
}
}
运行结果:
查询多条记录
查询多条数据时,一般封装到装有对象的集合当中。
对象类参考上一文章
参数类:
@Test
/**
* 查询多条记录
*/
public void demo2() {
// 创建核心类:QueryRunner
QueryRunner qr = new QueryRunner(JDBCUtils2.getDataSource());// 通过JDBC工具类获得连接池
try {
// 执行查询
List<Account> list = qr.query("select * from account", new ResultSetHandler<List<Account>>() {
@Override
public List<Account> handle(ResultSet rs) throws SQLException {
// 创建一个集合用于封装数据
List<Account> list = new ArrayList<Account>();
// 遍历结果集
// 因为是查询一条记录,使用可以使用if也可以使用while
while (rs.next()) {
// 将结果集的数据封装到对象中
Account account = new Account();
account.setId(rs.getInt("id"));
account.setName(rs.getString("name"));
account.setMoney(rs.getDouble("money"));
// 将对象存入List集合
list.add(account);
}
return list;
}
});
// 遍历集合
for (Account account : list) {
System.out.println(account);
}
} catch (SQLException e) {
e.printStackTrace();
}
}
运行结果:
DBUtils的使用之ResultSetHandler的实现类
前面我们学习了DBUtils的查询操作了,但是DBUtils查询时比较麻烦,因为我们需要手动的封装结果集当中的数据。
其实在DBUtils里面提供了ResultSetHandler的一些实现类可以帮助我们快速的把数据封装完成。
ArrayHandler和ArrayListHandler:可以把数据装到数组当中
BeanHandler和BeanListHandle:可以将数据装到Javabean当中
MapHandler和MapListHandler:可以将数据装到Map当中
ColumnListHandler:将数据中的某列封装到List集合中。
ScalarHandler:将单个值封装。
KeyedHandler:
ArrayHandler和ArrayListHandler
ArrayHandler
将一条记录封装到一个数组当中。这个数组应该是Object[ ]
代码示例:
@Test
/**
* ArrayHandler:将一条记录封装到一个Object[ ]数组当中
*/
public void demo1() {
// 创建核心类:QueryRunner
QueryRunner qr = new QueryRunner(JDBCUtils2.getDataSource());// 通过JDBC工具类获得连接池
try {
//执行SQL
Object[] obj = qr.query("select * from account where name=?", new ArrayHandler(), "aaa");
System.out.println(Arrays.toString(obj));
} catch (SQLException e) {
e.printStackTrace();
}
}
运行结果:
ArrayListHandler
将多条记录封装到一个装有Object[ ]数组的List集合中
代码示例:
@Test
/**
* ArrayListHandler:将多条记录封装到一个装有Object数组的List集合中
* *一条记录封装到Obiecct[ ]数组中,多条记录就是多个Object[ ],那么多个Object数组就将其装入List集合中即可。
*/
public void demo2() {
// 创建核心类:QueryRunner
QueryRunner qr = new QueryRunner(JDBCUtils2.getDataSource());// 通过JDBC工具类获得连接池
try {
//执行SQL
List<Object[]> list = qr.query("select * from account", new ArrayListHandler());
for (Object[] obj : list) {
System.out.println(Arrays.toString(obj));
}
} catch (SQLException e) {
e.printStackTrace();
}
}
运行结果:
BeanHandler和BeanListHan
BeanHandler
将一条记录封装到一个JavaBean中,其实就封装到类对象中。
代码示例:
@Test
/**
* BeanHandler:将一条记录封装到Javabean中
*/
public void demo3() {
// 创建核心类:QueryRunner
QueryRunner qr = new QueryRunner(JDBCUtils2.getDataSource());// 通过JDBC工具类获得连接池
try {
//执行SQL
Account account = qr.query("select * from account where name=?", new BeanHandler<Account>(Account.class),
"aaa");
System.out.println(account);
} catch (SQLException e) {
e.printStackTrace();
}
}
运行结果:
BeanListHandler
将多条记录封装到一个装有JavaBean的List集合中。
代码示例:
@Test
/**
* BeanListHandler:将多条记录封装到一个装有JavaBean的List集合中。
* *一条记录就是一个Java的对象(JavaBean),如果多条记录(多个Java的对象),将多个Java对象装到一个List集合中。
*/
public void demo4() {
// 创建核心类:QueryRunner
QueryRunner qr = new QueryRunner(JDBCUtils2.getDataSource());// 通过JDBC工具类获得连接池
try {
//执行SQL
List<Account> list = qr.query("select * from account", new BeanListHandler<Account>(Account.class));
for (Account account : list) {
System.out.println(account);
}
} catch (SQLException e) {
e.printStackTrace();
}
}
运行结果:
MapHandler和MapListHandler
MapHandler
将一条记录封装到一个Map集合中,Map的key是列名,Map的value就是表中列的记录的值。
@Test
/**
* MapHandler:将一条记录封装到一个Map集合中 ,Map的key是列名,Map的value就是表中列的记录值。
*/
public void demo5() {
// 创建核心类:QueryRunner
QueryRunner qr = new QueryRunner(JDBCUtils2.getDataSource());// 通过JDBC工具类获得连接池
try {
// 执行SQL
Map<String, Object> map = qr.query("select * from account where name=?", new MapHandler(), "aaa");
System.out.println(map);
} catch (SQLException e) {
e.printStackTrace();
}
}
运行结果:
MapListHandler
将多条记录封装到一个装有Map的list集合中。
@Test
/**
* MapListHandler:将多条记录封装到一个装有Map的list集合中。
*/
public void demo6() {
// 创建核心类:QueryRunner
QueryRunner qr = new QueryRunner(JDBCUtils2.getDataSource());// 通过JDBC工具类获得连接池
try {
// 执行SQL
List<Map<String, Object>> list = qr.query("select * from account", new MapListHandler());
for (Map<String, Object> map : list) {
System.out.println(map);
}
} catch (SQLException e) {
e.printStackTrace();
}
}
运行结果:
ColumnListHandler,ScalarHandler,KeyedHandler
ColumnListHandler
将数据中的某列封装到List集合中。
代码示例:
@Test
/**
* ColumnListHandler:将某列的值封装到List集合当中
*/
public void demo7() {
// 创建核心类:QueryRunner
QueryRunner qr = new QueryRunner(JDBCUtils2.getDataSource());// 通过JDBC工具类获得连接池
try {
// 执行SQL
List<Object> list = qr.query("select name from account", new ColumnListHandler<>("name"));
for (Object object : list) {
System.out.println(object);
}
} catch (SQLException e) {
e.printStackTrace();
}
}
运行结果:
控制台显示查询了name列
ScalarHandler
将单个值封装。
比如我们想要查询一张表里面的所有记录数,它查到的数就一个值,就可以使用ScalarHandler。
代码示例:
@Test
/**
* ScalarHandler:将单个值封装
*/
public void demo8() {
// 创建核心类:QueryRunner
QueryRunner qr = new QueryRunner(JDBCUtils2.getDataSource());// 通过JDBC工具类获得连接池
try {
// 执行SQL
Object obj = qr.query("select count(*) from account", new ScalarHandler<>());
System.out.println(obj);
} catch (SQLException e) {
e.printStackTrace();
}
}
运行结果:
KeyedHandler(了解)
将一条记录封装到一个Map集合中。
将多条记录封装到一个装有Map集合的Map集合中。
而且外面的Map的key是可以指定的。
将一条记录封装到一个Map集合中。
@Test
/**
* KeyedHandler:将一条记录封装到一个Map集合中
*/
public void demo10() {
// 创建核心类:QueryRunner
QueryRunner qr = new QueryRunner(JDBCUtils2.getDataSource());// 通过JDBC工具类获得连接池
try {
// 执行SQL,知道name为key就name在开头
Map<Object, Map<String, Object>> map = qr.query("select * from account where name=?",
new KeyedHandler<>("name"), "aaa");
for (Object key : map.keySet()) {
System.out.println(key + " " + map.get(key));
}
} catch (SQLException e) {
e.printStackTrace();
}
}
运行结果:
将多条记录封装到一个装有Map集合的Map集合中。
@Test
/**
* KeyedHandler:将多条记录封装到一个装有Map集合的Map集合中。
*/
public void demo9() {
// 创建核心类:QueryRunner
QueryRunner qr = new QueryRunner(JDBCUtils2.getDataSource());// 通过JDBC工具类获得连接池
try {
// 执行SQL,知道name为key就name在开头
Map<Object, Map<String, Object>> map = qr.query("select * from account", new KeyedHandler<>("name"));
for (Object key : map.keySet()) {
System.out.println(key + " " + map.get(key));
}
} catch (SQLException e) {
e.printStackTrace();
}
}
运行结果: