关卡18JDBC
一、JDBC概述
1.数据持久化
持久化(persistence):**把数据保存到可掉电式存储设备中以供之后使用**。大多数情况下,特别是企业级应用,**数据持久化意味着将内存中的数据保存到硬盘**上加以”固化”**,而持久化的实现过程大多通过各种关系数据库来完成**。
2.Java中的数据存储技术
(1)JDBC直接访问数据库(是Java访问数据库的基石)
(2)JDO(Java data Ojbect)技术
(3)第三方工具(o/r工具),如Hibernate,mybatis等
3.JDBC介绍
(1)JDBC(Java Database Connectivity)是一个独立于特定数据库管理系统、通用的SQL数据库存取和操作的公共接口(一组API),定义了用来访问数据库的标准Java类库,(java.sql,javax.sql)使用这些类库可以以一种标准的方法、方便地访问数据库资源。
(2)JDBC可以连接任何提供了JDBC驱动程序的数据库系统
4.JDBC的体系结构
(1)面向应用的api:Java API,抽象接口,供应用程序开发人员使用(连接数据库,执行SQL语句,获得结果)。
(2)面向数据库的api:Java Driver API,供开发商开发数据库驱动程序用。
5.JDBC程序编写步骤
(1)开始、(2)导入java.sql包、(3)Oracle.mysql、(4)加载注册驱动程序、(5)创建Connection对象、(6)创建Statement对象、(7)执行SQl语句、(8)使用ResultSet对象、(9)关闭ResultSet对象以及(5)(6)的对象、(10)结束
二、获取数据建库
1.导入一个mysql-connector-Java的一个lib文件
2.加载与注册JDBC驱动
(1)加载驱动:调用 Class 类的静态方法 forName(),向其传递要加载的 JDBC 驱动的类名;Driver driver=new com.mysql.jdbc.Driver();
(2)注册驱动:DriverManager 类是驱动程序管理器类,负责管理驱动程序
3.URL
(1)JDBC URL 用于标识一个被注册的驱动程序,驱动程序管理器通过这个 URL 选择正确的驱动程序,从而建立到数据库的连接。
(2)JDBC URL的标准由三部分组成,各部分间用冒号分隔。
①jdbc:子协议:子名称
②协议:JDBC URL中的协议总是JDBC
③子协议:子协议用于标识一个数据库驱动程序
④一种标识数据库的方法。子名称可以依不同的子协议而变化,用子名称的目的是为了**定位数据库**提供足够的信息。包含**主机名**(对应服务端的ip地址)**,端口号,数据库名**
(3)mysql连接URL的编写方式:
(1)jdbc:mysql://主机名称:mysql服务端口号/数据库名称?参数=值&参数=值;jdbc:mysql://localhost:3306/test
(2)如果JDBC程序与服务器端的字符集不一致,会导致乱码,那么可以通过参数指定服务器端的字符集;jdbc:mysql://localhost:3306/test**?useUnicode=true&characterEncoding=utf8**
4.连接数据库的最优化
(1)将文件与代码分离,配置文件中存储数据库的基本信息,需要修改配置信息时则不需要修改源代码,直接修改配置文件
(2)修改了配置信息,省掉重新编译文件的步骤
三、使用PreparedStatement实现crud操作
1.数据库连接被用于向数据库服务器发送命令和sql语句,并接受数据建库服务器返回的结果,其实数据库连接是一个socket连接
2.Statement:用于执行静态sql语句并返回生成结果的对象
①通过调用Connection对象的createStatement()方法创建对象,该对象用于执行sql语句,并且返回执行结果
②Stratement接口中定义了:int excuteUpdate(String sql);执行更新操作(insert、update、delete)
③Resultser excuteQuery(String sql):执行查询操作select
④弊端:需要拼写SQL语句,并且存在SQL注入问题
3.使用PreparedStatemend优化Statement
(1)采用了预编译方式解决了Statement存在的问题存在的问题
(2)?代表占位符:String sql="sql语句";
(3)PreparedStatement ps=conn.prepareStatement(sql);创建对象填充占位符
(4)preparedDtatement可以实现更高效的批量处理
4.小结
(1)ResultSet获取结果集
(2)ResultSetMetaData获取结果集的元素
(3)getColumnCount()获取列数
(4)getColumnLabel()获取列的别名
(5)getColumnName()获取列名
(6)用(4)取代(5)的好处:
①当查询语句时,java中实体类属性与MySQL中的字段名表示方式不同时,可根据属性名取对应的别名
②在查询时没有对mysql中的字段名取别名时默认字段名为别名
四、操作BLOB类型字段
1.定义:mysql中BLOB是一个二进制的大型对象,是一个可以存储大量数据的容器,他能容纳不同大小的数据
2.特点:插入BLOB类型的数据必须使用PreparedStatement,因为BLOB类型的数据无法使用字符串拼接
3.MySQL中的四种BLOB数据类型:TinyBlob最大255字节、Blob最大65k字节、MediumBlob最大16M字节、LongBLob最大4G字节
4.如果在指定了相关的Blob类型以后,还报错:xxx too large,那么在mysql的安装目录下,找my.ini文件加上如下的配置参数: **max_allowed_packet=16M**。同时注意:修改了my.ini文件之后,需要重新启动mysql服务。
5.插入更新BLOB类型数据与一般插入更新相似;读取BLOB类型数据时,需要从数据库中下载以对应文件形式存储到本地
五、批量插入处理
1.preparedStatement,能对sql语句进行预编译处理,DBServer的编译器编译后的执行代码被缓存下来,下次调用时,只要是相同的预编译语句就不需要编译,只要将参数直接传入编译过的语句执行代码,预编译语句可以被重复调用
2.Statement语句中每次执行一次都需要传入预编译语句
3.注意
(1)mysql服务器默认是关闭批量处理,需要在配置文件中url后面加上:?rewriteBatchedStatements=true
(2)需要将mysql驱动5.1.7更改为5.1.37
1.使用JDBC实现修改库存量小于10本的图书的库存量为100
package Guanqia18;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.List;
public class T1_test {
public static <T> List<T> getForList(Class<T> clazz, String sql, Object... args){
PreparedStatement ps=null;
ResultSet rs=null;
Connection con=null;
try {
con=T1.testConnection5();
//con=Druid.Druid_test.getDruid();
ps= con.prepareStatement(sql);
for (int i=0;i<args.length;i++){
ps.setObject(i+1,args[i]);
}
rs=ps.executeQuery();
ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();
//ps.close();
ArrayList<T> list=new ArrayList<T>();
while(rs.next()){
books b = new books();
for (int i=0;i<columnCount;i++){
Object obj=rs.getObject(i+1);
String name=rsmd.getColumnLabel(i+1);
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
field.set(b,obj);
}
list.add((T) b);
}
return list;
}catch (Exception e){
e.printStackTrace();
}finally {
T1.closeResource(con,ps,rs);
}
return null;
}
public static void main(String[] args) {
String sql="SELECT b_id id,b_name 'name',parice ,amount FROM `books`";
List<books> list= getForList(books.class,sql);
System.out.println("-------修改前--------");
for (books b:list){
System.out.println(b);
}
String sql1="update books set amount=100 where amount<10;";
update(sql1);
//String sql2="SELECT b_id id,b_name 'name',parice ,amount FROM `books`";
List<books> list1= getForList(books.class,sql);
System.out.println("-------修改后--------");
for (books b:list1){
System.out.println(b);
}
}
public static void update(String sql,Object ... args){
Connection con=null;
PreparedStatement ps=null;
try {
con = T1.testConnection5();
ps = con.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
ps.execute();
con.close();
ps.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
2.从键盘输入用户名,实现查询该用户的订单和订单明细(表数据自己给)
package Guanqia18;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
public class T2_test {
public static void main(String[] args) {
String sql="select u_id id,u_name,users.b_id b_id,b_name ,parice \n" +
"from users\n" +
"inner join books\n" +
"on users.b_id=books.b_id\n"
+ "where u_name=?;";
List<User> list=T2.getForList(User.class,sql,"张三");
for (User u:list){
System.out.println(u);
}
}
public static class T2{
public static <T>List<T> getForList(Class<T> clazz,String sql,Object ... args) {
Connection conn=null;
PreparedStatement ps=null;
ResultSet rs=null;
try {
conn = t2con();
ps=conn.prepareStatement(sql);
for (int i=0;i<args.length;i++){
ps.setObject(i+1,args[i]);
}
rs = ps.executeQuery();
ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();
ArrayList<T> list = new ArrayList<>();
while (rs.next()){
User user = new User();
for (int i=0;i<columnCount;i++){
Object obj=rs.getObject(i+1);
String name=rsmd.getColumnLabel(i+1);
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
field.set(user,obj);
}
list.add((T) user);
}
return list;
}catch (Exception e){
e.printStackTrace();
}finally {
T1.closeResource(conn,ps,rs);
}
return null;
}
public static Connection t2con(){
Connection conn=null;
try{
//1.加载配置文件
InputStream is =ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
Properties pros = new Properties();
pros.load(is);
//2.读取配置信息
String user = pros.getProperty("user");
String password = pros.getProperty("password");
String url = pros.getProperty("url");
String driverClass = pros.getProperty("driverClass");
//3.加载驱动
Class.forName(driverClass);
//4.获取连接
conn = DriverManager.getConnection(url, user, password);
}catch (Exception e){
e.printStackTrace();
}
return conn;
}
}
}
3.使用JDBC实现删除订单“15275760194821”的相关信息,注意涉及到两张表
( 需要使用到级联删除)
package Guanqia18;
import java.sql.Connection;
import java.sql.PreparedStatement;
public class T3_test {
public static void delete(String sql,Object ...args){
try {
Connection conn = T2_test.T2.t2con();
PreparedStatement ps = conn.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
ps.execute();
ps.close();
conn.close();
}catch (Exception e){
e.printStackTrace();
}
}
public static void main(String[] args) {
String sql="delete users,books from books\n" +
"inner join users on users.b_id=books.b_id \n" +
"where books.b_id=2 ;";
delete(sql);
}
}
删除前
删除后
六、数据库事务
1.定义:有一个或一组DML语言组成的不可在分割的最小单元,其中的sql操纵语言要么都执行要么都不执行,操纵的数据从一个一致状态转换到另一个一致状态
2.事务处理原则:保证所有的事务都作为一个工作执行单元,当一个事务执行多个操时,要么所有的事务操作全都提交(commit),这些修改后的数据将永久保存下来,要么数据库管理系统放弃所有的修改,整个事务将回滚(rollback)回到最初状态
3.TDBC事务处理
(1)数据一旦提交不可再回滚
(2)哪些操作会导致数据自动提交
①DDL操作一旦执行都会自动提交
②DML默认情况下一旦执行就会自动提交,的可以通过:set autocommit=flase的方式取消自动提交操作,这个方式对数据定义语言无效
③默认在关闭连接时,会自动提交数据
(3)在Java中执行插入,更新,删除,查找时所有的的数据库连接从主方法中传入,等待整个事务执行完成之后再关闭
(4)测试方法中连接后,设置取消自动提交:conn.setAutoCommit(false);等到整个事务执行完毕在关闭资源前进行提交数据:conn.commit();数据提交完之后恢复自动提交状态:setAutoCommit(true),主要针对连接池
(5)整个事务中如果一条语句出现异常try..catch回滚数据:conn.rollback();
4.事务的ACID属性:原子性、一致性、隔离性、持久性
5.事务的并发问题:脏读、不可重复读、幻读
6.事务的四种隔离级别
(1)READ UNCOMMITTED:读未提交,允许所有的并发问题存在
(2)READ COMMITED:读已提交,可以避免脏读问题,但不可重复读以及幻读问题依然存在
(3)REPEATABLE READ:可重复读,可以避免脏读以及不可重复读问题,但是幻读问题还是存在
(4)SERIALIZABLE:串行话,可以避免所有的并发问题
7.在MySQL中设置隔离级别
(1)查看当前隔离级别:select @@tx_isolation
(2)设置当前mysql连接隔离级别:set transaction isolation level read committed;
(3)设置数据库系统的全局的隔离级别:set global transaction isolation level read committed
(4)补充操作:
①创建mysql数据库用户:create user tom identified by 'abc123';
②授予权限
授予通过网络方式登录的tom用户,对所有库所有表的全部权限,密码为:abc123; grant all privileges on *.* to tom@'%' identified by 'abc123';
给tom用户使用本地命令行方式,授予atguigudb库下的所有表的插入删除更新查找权限:grant select,insert,delete,update on atguigudb.* to tom@localhost identified by 'abc123';
七、DAO及相关的实现类
1.DAO:访问数据信息的封装类和接口,其中方法包括了对数据的增删改查操作
2.作用:实现功能的模块化,更有利于代码的更新和升级
3.每一个功能的连接从主方法中传入
4.通过对应的方法获取当前BaseDAO类的实现类继承父类中得到范型,代码块放到父类中(抽象BaseDAO)中
八、数据库连接池
1.JDBC数据亏连接池的必要性
(1)在使用开发基于数据库的web程序时基本步骤
①在主程序(如servlet、beans)中建立数据库连接
②进行sql操作
③断开连接
(2)基于数据库的web程序,存在的问题
①普通的JDBC数据库连接使用DrverManager来获取每次都要将Connection加载到内存之中,再验证用户名和密码,会消耗大量的资源和时间,数据库的连接资源并没有得到很好的重复利用
②对于每一次数据库连接,使用完后都得断开。否则,如果程序出现异常而未能关闭,将会导致数据库系统中的内存泄漏,最终重启数据库
③这种开发不能控制被创建的连接数,系统资源会被毫无顾忌地分配出去,连接过多也可能导致内存泄漏,服务器崩溃
2.数据库连接池技术
(1)数据库连接池的基本思想:就是为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。
(2)数据库连接池作用:**数据库连接池**负责分配、管理和释放数据库连接,它**允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个**。
(3)数据库连接池特点
①数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中,这些数据库连接的数量是由**最小数据库连接数来设定**的
②无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量。
③连接池的**最大数据库连接数量**限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中。
3.数据库连接池的优点
(1)由于数据库连接得以重用,避免了频繁创建,释放连接引起的大量性能开销。在减少系统消耗的基础上,另一方面也增加了系统运行环境的平稳性。
(2)更快的系统反应速度:数据库连接池在初始化过程中,往往已经创建了若干数据库连接置于连接池中备用。此时连接的初始化工作均已完成。对于业务请求处理而言,直接利用现有可用连接,避免了数据库连接初始化和释放过程的时间开销,从而减少了系统的响应时间
(3)新的资源分配手段:对于多应用共享同一数据库的系统而言,可在应用层通过数据库连接池的配置,实现某一应用最大可用数据库连接数的限制,避免某一应用独占所有的数据库资源
(4)统一的连接管理:在较为完善的数据库连接池实现中,可根据预先的占用超时设定,强制回收被占用连接,从而避免了常规数据库连接操作中可能出现的资源泄露
4.数据库连接池类别
(1)JDBC的数据库连接池
①DBCP:是Apache提供的数据库连接池。tomcat 服务器自带dbcp数据库连接池。**速度相对c3p0较快**,但因自身存在BUG,Hibernate3已不再提供支持。
②C3P0:是一个开源组织提供的一个数据库连接池,**速度相对较慢,稳定性还可以。**hibernate官方推荐使用
③Proxool:是sourceforge下的一个开源项目数据库连接池,有监控连接池状态的功能,**稳定性较c3p0差一点**
④BoneCP:是一个开源组织提供的数据库连接池,速度快
④Druid:是阿里提供的数据库连接池,据说是集DBCP 、C3P0 、Proxool 优点于一身的数据库连接池,但是速度不确定是否有BoneCP快
(2)DataSource 通常被称为数据源,它包含连接池和连接池管理两个部分,习惯上也经常把 DataSource 称为连接池
(3)**DataSource用来取代DriverManager来获取Connection,获取速度快,同时可以大幅度提高数据库访问速度。
(4)注意事项:
①数据源和数据库连接不同,数据源无需创建多个,它是产生数据库连接的工厂,因此**整个应用只需要一个数据源即可。**
②当数据库访问结束后,程序还是像以前一样关闭数据库连接:conn.close(); 但conn.close()并没有关闭数据库的物理连接,它仅仅把数据库连接释放,归还给了数据库连接池。
5.数据库连接池的使用
(1)C3P0
①ComboPooledDataSource cpds = new ComboPooledDataSource();
②C3P0:设置初始时数据连接池中的连接数量:cpds.setInitialooolsize(10);
③设置C3P0最大连接数:cpds.setMaxPoolSize(100);
package C3P0;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.mchange.v2.log.ModifyLogLevel;
import org.junit.Test;
import javax.sql.DataSource;
import java.sql.Connection;
import java.util.logging.Level;
public class C3P0_test {
public static Connection getConnection1() throws Exception{
ComboPooledDataSource cpds = new ComboPooledDataSource();
cpds.setDriverClass("com.mysql.cj.jdbc.Driver");
cpds.setJdbcUrl("jdbc:mysql://localhost:3306/library?serverTimezone=UTC&useSSL=false");
cpds.setUser("root");
cpds.setPassword("123456");
// cpds.setMaxPoolSize(100);
Connection conn = cpds.getConnection();
//System.out.println(conn);
return conn;
}
static {
ModifyLogLevel.modifyInfoLevel(Level.ALL);
}
private static DataSource cpds = new ComboPooledDataSource("helloc3p0");
public static void main(String[] args) throws Exception {
//System.out.println(getConnection1());
Connection conn = cpds.getConnection();
System.out.println(conn);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<named-config name="helloc3p0">
<!-- 获取连接的4个基本信息 -->
<property name="user">root</property>
<property name="password">123456</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/library?&useSSL=false&serverTimezone=UTC</property>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<!-- 涉及到数据库连接池的管理的相关属性的设置 -->
<!-- 若数据库中连接数不足时, 一次向数据库服务器申请多少个连接 -->
<property name="acquireIncrement">5</property>
<!-- 初始化数据库连接池时连接的数量 -->
<property name="initialPoolSize">5</property>
<!-- 数据库连接池中的最小的数据库连接数 -->
<property name="minPoolSize">5</property>
<!-- 数据库连接池中的最大的数据库连接数 -->
<property name="maxPoolSize">10</property>
<!-- C3P0 数据库连接池可以维护的 Statement 的个数 -->
<property name="maxStatements">20</property>
<!-- 每个连接同时可以使用的 Statement 对象的个数 -->
<property name="maxStatementsPerConnection">5</property>
</named-config>
</c3p0-config>
(2)DBCP
①导入Commons-dbcp.jar:连接池的实现
②导入Commons-pool.jar:连接池实现的依赖库
③Tomcat 的连接池正是采用该连接池来实现的。该数据库连接池既可以与应用服务器整合使用,也可由应用程序独立使用。
package DBCP;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import org.junit.Test;
import javax.sql.DataSource;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Connection;
import java.util.Properties;
public class DBCP_test {
private static DataSource source=null;
static {
try {
Properties pros=new Properties();
FileInputStream is = new FileInputStream(new File("E:\\阶段一\\jdbc\\src\\DBCP.properties"));
pros.load(is);
source= BasicDataSourceFactory.createDataSource(pros);
is.close();
}catch (Exception e){
e.printStackTrace();
}
}
public static void testGet() throws Exception {
Connection conn = source.getConnection();
System.out.println(conn);
conn.close();
}
public static void main(String[] args) throws Exception {
testGet();
}
}
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql:///library?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&useSSL=false
username=root
password=123456
initialSize=10
(3)Druid
package Druid;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.util.Properties;
public class Druid_test {
private static DataSource source=null;
static {
try {
Properties pros=new Properties();
FileInputStream is = new FileInputStream(new File("E:\\阶段一\\jdbc\\src\\Druid.properties"));
pros.load(is);
source = DruidDataSourceFactory.createDataSource(pros);
is.close();
}catch (Exception e){
e.printStackTrace();
}
}
public static Connection getDruid() throws Exception {
Connection conn = source.getConnection();
//System.out.println(conn);
//conn.close();
return conn;
}
public static void main(String[] args) throws Exception {
System.out.println(getDruid());
}
}
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql:///library?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&useSSL=false
username=root
password=123456
initialSize=10
maxActive=10
九、Apache-DBUtils实现CRUD操作
1.Apache-DBUtils简介
commons-dbutils 是 Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化jdbc编码的工作量,同时也不会影响程序的性能。
2.BeanHandler:将结果集中的第一行数据封装到一个对应的JavaBean实例中。
3.BeanListHandler:将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里。
4.MapHandler:将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值。
5.**MapListHandler:**将结果集中的每一行数据都封装到一个Map里,然后再存放到List
6.**ScalarHandler:**查询单个值对象
package DBUtils;
import Druid.Druid_test;
import Guanqia18.User;
import Guanqia18.books;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.*;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
public class DBUtils_test {
public static void testInsert() {
try {
QueryRunner runner = new QueryRunner();
Connection conn = Druid_test.getDruid();
String sql="insert into books values(?,?,?,?)";
int insertCount = runner.update(conn, sql, "12", "机器学习", "55", "30");
System.out.println("添加了"+insertCount+"条信息");
conn.close();
}catch (Exception e){
e.printStackTrace();
}
}
public static void main(String[] args) {
//testInsert();
//testSelect();
//testSelect1();
//testSelect2();
//testSelect3();
testSelect4();
}
public static void testSelect() {
try {
QueryRunner runner = new QueryRunner();
Connection conn = Druid_test.getDruid();
String sql = "select * from books where bid=?";
BeanHandler<books> handler = new BeanHandler<>(books.class);
books books = runner.query(conn, sql,handler, 12);
System.out.println(books);
conn.close();
}catch (Exception e){
e.printStackTrace();
}
}
public static void testSelect1() {
try {
QueryRunner runner = new QueryRunner();
Connection conn = Druid_test.getDruid();
String sql = "select * from books ";
BeanListHandler<books> handler = new BeanListHandler<>(books.class);
List<books> query = runner.query(conn, sql, handler);
//System.out.println(query);
for (books b:query){
System.out.println(b);
}
conn.close();
}catch (Exception e){
e.printStackTrace();
}
}
public static void testSelect2() {
try {
QueryRunner runner = new QueryRunner();
Connection conn = Druid_test.getDruid();
String sql = "select * from books where bid=10";
MapHandler handler = new MapHandler();
Map<String, Object> query = runner.query(conn, sql, handler);
System.out.println(query);
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void testSelect3() {
try {
QueryRunner runner = new QueryRunner();
Connection conn = Druid_test.getDruid();
String sql = "select * from books";
MapListHandler handler = new MapListHandler();
List<Map<String, Object>> query = runner.query(conn, sql, handler);
//System.out.println(query);
for (Map<String, Object> m:query){
System.out.println(m);
}
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void testSelect4() {
try {
QueryRunner runner = new QueryRunner();
Connection conn = Druid_test.getDruid();
String sql = "select count(*) from books";
ScalarHandler handler = new ScalarHandler();
Object count = runner.query(conn, sql, handler);
System.out.println(count);
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}