JavaWeb(5)之JDBC(2)

JDBC的事务环境准备

事务指的是逻辑上的一组操作,组成这组操作各个逻辑单元要么全都成功,要么全都失败。

  1. 创建数据库和表
CREATE TABLE `account` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) DEFAULT NULL,
  `money` double DEFAULT NULL,
  PRIMARY KEY (`id`)
)
  1. 添加数据
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中&分隔符要更换成 &amp ;

<c3p0-config>
	<!-- 默认配置,如果没有指定则使用这个配置 -->
	<default-config>
		<property name="driverClass">com.mysql.cj.jdbc.Driver</property>
		<property name="jdbcUrl">
			jdbc:mysql://localhost:3306/jdbc?useSSL=false&amp;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

DbUtils使用手册

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();
		}
	}

运行结果:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值