本文3-5节是8和9节的底层源码,8与9节是实际开发中会用到的框架
参考资料 JDBC尚硅谷,宋红康主讲
1.JDBC概述
- JDBC是一个“独立与特定数据库管理系统,通用的SQL数据库存取和操作的公共接口(API)”定义了用来访问数据库的标准java类库,(java.sql,javax.sql)使用这些类库可以以一种标准的方法,方便地访问数据库
- JDBC为访问不同的数据库提供了一种统一的途径,为开发者屏蔽了一些细节问题。
- JDBC的目标是使java程序员可以连接任何提供了JDBC驱动程序的数据库系统,这样使得程序员无需对特定的数据库系统的特点有过多的了解,大大简化和加快了开发过程。
有了JDBC以后,我们访问数据库是这样的
2.JDBC编写的步骤
- 导入java.sql包
- 建立驱动
- 获取对数据库的连接(创建Connection对象)
- 创建Statement对象
- 执行sql语句获得ResultSet对象
- 关闭连接
3.获取数据库连接的五种方式
首先导入mysql的jar包 点击:File->Project Structure->Modules->Dependencies
方式一
import java.sql.Connection;
import java.sql.Driver;
import java.sql.SQLException;
import java.util.Properties;
public class ConnectionText {
public static void main(String[] args) throws SQLException {
Driver driver = new com.mysql.cj.jdbc.Driver();
String url = "jdbc:mysql://localhost:3306/donglijiedian";
Properties info = new Properties();
info.setProperty("user","root");
info.setProperty("password","2767");
Connection conn=driver.connect(url,info);
}
}
方式二
import java.sql.Connection;
import java.sql.Driver;
import java.sql.SQLException;
import java.util.Properties;
public class ConnectionText2 {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, SQLException {
Class clazz = Class.forName("com.mysql.cj.jdbc.Driver");
Driver driver = (Driver)clazz.newInstance();
String url = "jdbc:mysql://localhost:3306/donglijiedian";
Properties info = new Properties();
info.setProperty("user","root");
info.setProperty("password","2767");
Connection conn=driver.connect(url,info);
System.out.println(conn);
}
}
方式三
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
public class ConnectionText3 {
public static void main(String[] args) throws Exception {
Class clazz = Class.forName("com.mysql.cj.jdbc.Driver");
Driver driver = (Driver)clazz.newInstance();
DriverManager.registerDriver(driver);
String url = "jdbc:mysql://localhost:3306/donglijiedian";
String user="root";
String password="2767";
Connection conn=DriverManager.getConnection(url,user,password);
}
}
方式四
import java.sql.Connection;
import java.sql.DriverManager;
public class ConnectionText4 {
public static void main(String[] args) throws Exception {
Class clazz = Class.forName("com.mysql.cj.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/donglijiedian";
String user="root";
String password="2767";
Connection conn=DriverManager.getConnection(url,user,password);
}
}
方式五最终版 将连接数据库的四个基本信息写到一个配置文件中,配置文件以.properties结尾 配置文件的数据:
user=root password=2767 url=jdbc:mysql://localhost:3306/donglijiedian driverClass=com.mysql.cj.jdbc.Driver
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
public class ConnectionText5 {
public static void main(String[] args) throws IOException, ClassNotFoundException, SQLException {
InputStream is=ConnectionText5.class.getClassLoader().getResourceAsStream("jdbc.properties");
Properties pros=new Properties();
pros.load(is);
String user=pros.getProperty("user");
String password=pros.getProperty("password");
String url=pros.getProperty("url");
String dricerClass=pros.getProperty("driverClass");
Class.forName(dricerClass);
Connection conn= DriverManager.getConnection(url,user,password);
}
}
4.Statement的弊端(面试)
对于java而言,我们一般使用PreparedStatement取代Statement
- 需要拼写sql语句,如在sql语句中出现变量需要’"++"’
- 有sql注入的问题,缺乏安全性(致命缺点),sql注入:即利用某些系统没有对用户输入的数据进行充分的检查,而且在用户输入数据中注入非法的sql语句段,从而利用系统的sql引擎完成而恶意行为的做法。
5.PreparedStatement的使用
PreparedStatement的优点:
1.通过占位符,减少了拼接操作 2.通过预编译可以解决sql注入问题 3.支持对Blob文件的操作 4.可以实现更高效的批量操作
5.1增删改
5.1.1封装获取连接和关闭连接的操作
由于每次对数据库的操作都要进行连接,所以我们新建建一个util包,把链接操作封装起来
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
public class JDBCutils {
public static Connection getConnection() throws Exception {
InputStream is= ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
Properties pros=new Properties();
pros.load(is);
String user=pros.getProperty("user");
String password=pros.getProperty("password");
String url=pros.getProperty("url");
String dricerClass=pros.getProperty("driverClass");
Class.forName(dricerClass);
Connection conn= DriverManager.getConnection(url,user,password);
return conn;
}
public static void closeResource(Connection conn, Statement ps){
if (null!=ps){
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (null!=null){
try {conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void closeResource(Connection conn, Statement ps, ResultSet rs){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
package util;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class JDBCutils {
public static Connection getConnection() throws Exception {
InputStream is= ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
Properties pros=new Properties();
pros.load(is);
String user=pros.getProperty("user");
String password=pros.getProperty("password");
String url=pros.getProperty("url");
String dricerClass=pros.getProperty("driverClass");
Class.forName(dricerClass);
Connection conn= DriverManager.getConnection(url,user,password);
return conn;
}
public static void closeResource(Connection conn, Statement ps){
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
5.1.2通用的增删改模板
增删改操作仅仅是预编译的sql语句以及占位符的填充有不同,所以我们可以写一个通用的增删改操作的模板
public static void alter(String sql,Object ...args){
Connection conn= null;
PreparedStatement ps= null;
try {
conn = JDBCutils.getConnection();
ps = conn.prepareStatement(sql);
for (int i=0;i<args.length;i++){
ps.setObject(i+1,args[i]);
}
ps.execute();
} catch (Exception e) {
e.printStackTrace();
}finally {
JDBCutils.closeResource(conn,ps);
}
}
5.2查询
在java中查询操作会返回一个结果集ResultSet,重点就是对ResultSet的操作
java与sql对应数据类型转换表
java类型 | sql类型 |
---|
boolean | BIT | byte | TINYINT | short | SAMLLINT | int | INTEGER | long | BIGINT | String | CHAR,VARCHAR,LONGVARCHER | byte array | BINARY,VAR BINARY | java.sql.Date | DATE | java.sql.Time | TIME | java.sql.TimeStap | TIMESTAMP |
customer表
Customer类对应customer表
import java.util.Date;
public class Customer {
private int id;
private String name;
private String email;
private Date birthday;
public Customer() {
}
public Customer(int id, String name, String email, Date date) {
this.id = id;
this.name = name;
this.email = email;
this.date = date;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
@Override
public String toString() {
return "Customer{" +
"id=" + id +
", name='" + name + '\'' +
", email='" + email + '\'' +
", date=" + date +
'}';
}
}
5.2.1通用的查询操作模板(针对customer表)
为了使代码得到更好的复用,我们将对customer表的查询操作封装起来,写成一个通用的模板
public static Customer queryForCustomer(String sql,Object...args) {
Connection conn= null;
PreparedStatement ps= null;
ResultSet rs= null;
try {
conn = JDBCutils.getConnection();
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 colum=rsmd.getColumnCount();
if(rs.next()){
Customer cust=new Customer();
for(int i=0;i<colum;i++){
Object value=rs.getObject(i+1);
String columValue=rsmd.getColumnLabel(i+1);
Field field=Customer.class.getDeclaredField(columValue);
field.setAccessible(true);
field.set(cust,value);
}
return cust;
}
} catch (Exception e) {
e.printStackTrace();
}finally {
JDBCutils.closeResource(conn,ps,rs);
}
return null;
}
5.2.2通用的查询操作模板(针对不同的表)
public static <T> List<T> getForList(Class<T> clazz,String sql,Object... args){
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JDBCutils.getConnection();
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 columCount = rsmd.getColumnCount();
ArrayList<T> list=new ArrayList<T>();
while (rs.next()){
T t = clazz.getDeclaredConstructor().newInstance();
for (int i=0;i<columCount;i++){
Object columValue=rs.getObject(i+1);
String columName = rsmd.getColumnLabel(i+1);
Field field=clazz.getDeclaredField(columName);
field.setAccessible(true);
field.set(t,columValue);
}
list.add(t);
}
return list;
} catch (Exception e) {
e.printStackTrace();
}finally {
JDBCutils.closeResource(conn,ps,rs);
}
return null;
}
5.3操作BLOB类型的字段
5.3.1BLOB类型概述
在Mysql中,一共有四种类型的BLOB
BLOB是一个二进制的大型图像,是一个可以存储大量数据的容器 注:若大量地存储Blob对象,会导致效率下降
类型 | 大小 |
---|
TinyBlob | 最大255K | Blob | 最大65K | MediumBlob | 最大16M | LongBlob | 最大4G |
注意:若存放的图片没有超过类型的大小限制也报错,则应该进入my.ini配置文件加上这个参数:max_allowed+packet=16M
5.3.2Blob类型的插入
import util.JDBCutils;
import java.io.File;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
public class BlobInsertTest {
public static void main(String[] args) {
Connection conn= null;
PreparedStatement ps = null;
try {
conn = JDBCutils.getConnection();
String sql = "insert into customer(id,name,email,birthday,photo)values(?,?,?,?,?)";
ps = conn.prepareStatement(sql);
ps.setObject(1,2);
ps.setObject(2,"zhangwei");
ps.setObject(3,"zhangwei@qq.com");
ps.setObject(4,"1992-09-09");
FileInputStream is = new FileInputStream(new File("C:\\Users\\ryoxm\\Desktop\\pictures\\0.jpg"));
ps.setBlob(5,is);
ps.execute();
} catch (Exception e) {
e.printStackTrace();
}finally {
JDBCutils.closeResource(conn,ps);
}
}
}
5.3.3Blob类型的读取
import bean.Customer;
import util.JDBCutils;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.sql.*;
public class BlobQueryText {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JDBCutils.getConnection();
String sql="select * from customer where id = ?";
ps = conn.prepareStatement(sql);
ps.setObject(1,2);
rs = ps.executeQuery();
if (rs.next()){
int id = rs.getInt("id");
String name = rs.getString("name");
String email = rs.getString("email");
Date birth = rs.getDate("birthday");
Customer customer = new Customer(id,name,email,birth);
System.out.println(customer);
Blob photo = rs.getBlob("photo");
InputStream is = photo.getBinaryStream();
FileOutputStream fos = new FileOutputStream("zhangwei.jpg");
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer))!=-1){
fos.write(buffer,0,len);
}
}
} catch (Exception e) {
e.printStackTrace();
}
JDBCutils.closeResource(conn,ps,rs);
}
}
5.3.4批量插入数据
向goods表中插入20000个货物的id和name
import util.JDBCutils;
import java.sql.Connection;
import java.sql.PreparedStatement;
public class InsetDemo {
public static void main(String[] args) {
Connection conn= null;
PreparedStatement ps = null;
try {
conn = JDBCutils.getConnection();
String sql="insert into goods(id,name)values(?,?)";
ps = conn.prepareStatement(sql);
for (int i=0;i<=20000;i++){
ps.setObject(1,i);
ps.setObject(2,"name_"+i);
ps.addBatch();
if (i%500==0){
ps.executeBatch();
ps.clearBatch();
}
}
} catch (Exception e) {
e.printStackTrace();
}finally {
JDBCutils.closeResource(conn,ps);
}
}
6.事物
6.1事物的引入
下面是user_table
现在假设AA要给BB转账100 我们必须要让两个事件同时发生,不然万一出现网络延迟等等,就可能会出现AA扣了钱,而BB也没到账的情况,所以我们引入了事物。
什么叫数据库事物
一组逻辑操作单元,一个或多个DML操作
事物处理的原则
事物中的所有操作要么同时成功,要么同时失败
注意:数据一旦提交,就不可回滚,回滚操作是回滚到上一次的提交点。 DML操作一旦执行会默认提交,所以我们要取消自动提交 并且在关闭连接后,也会自动提交。
6.2考虑事物之后的增删改操作
import util.JDBCutils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class TransactionText {
public static void main(String[] args) {
Connection conn = null;
try {
conn=JDBCutils.getConnection();
conn = JDBCutils.getConnection();
conn.setAutoCommit(false);
String sql1 = "update user_table set balance = balance-100 where user = ?";
alter(conn,sql1,"AA");
String sql2 = "update user_table set balance = balance+100 where user = ?";
alter(conn,sql2,"BB");
System.out.println("转账成功");
conn.commit();
} catch (Exception e) {
e.printStackTrace();
try {
conn.rollback();
} catch (SQLException ex) {
ex.printStackTrace();
}
}finally {
JDBCutils.closeResource(conn,null);
}
}
public static void alter(Connection conn,String sql,Object ...args){
PreparedStatement ps= null;
try {
ps = conn.prepareStatement(sql);
for (int i=0;i<args.length;i++){
ps.setObject(i+1,args[i]);
}
ps.execute();
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
conn.setAutoCommit(true);
} catch (SQLException e) {
e.printStackTrace();
}
JDBCutils.closeResource(null,ps);
}
}
}
6.3java代码设置数据库的隔离级别
查看当前连接的隔离级别
conn.getTransactionIsolation();
设置当前连接的隔离级别
conn.setTransactionIsolation();
7.数据库操作类Dao
7.1提供操作数据表的BaseDao
封装了针对于数据表的通用操作,根据不同的表,提供不同的Dao
import util.JDBCutils;
import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public abstract class BaseDao {
public int alter(Connection conn, String sql, Object ...args){
PreparedStatement ps= null;
try {
ps = conn.prepareStatement(sql);
for (int i=0;i<args.length;i++){
ps.setObject(i+1,args[i]);
}
return ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}finally {
JDBCutils.closeResource(null,ps);
}
return 0;
}
public static <T> T getInstance(Connection conn,Class<T> clazz,String sql,Object... args){
PreparedStatement ps = null;
ResultSet rs = null;
try {
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 columCount = rsmd.getColumnCount();
if (rs.next()){
T t = clazz.getDeclaredConstructor().newInstance();
for (int i=0;i<columCount;i++){
Object columValue=rs.getObject(i+1);
String columName = rsmd.getColumnLabel(i+1);
Field field=clazz.getDeclaredField(columName);
field.setAccessible(true);
field.set(t,columValue);
}
return t;
}
} catch (Exception e) {
e.printStackTrace();
}finally {
JDBCutils.closeResource(null,ps,rs);
}
return null;
}
public static <T> List<T> getForList(Connection conn,Class<T> clazz, String sql, Object... args){
PreparedStatement ps = null;
ResultSet rs = null;
try {
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 columCount = rsmd.getColumnCount();
ArrayList<T> list=new ArrayList<T>();
while (rs.next()){
T t = clazz.getDeclaredConstructor().newInstance();
for (int i=0;i<columCount;i++){
Object columValue=rs.getObject(i+1);
String columName = rsmd.getColumnLabel(i+1);
Field field=clazz.getDeclaredField(columName);
field.setAccessible(true);
field.set(t,columValue);
}
list.add(t);
}
return list;
} catch (Exception e) {
e.printStackTrace();
}finally {
JDBCutils.closeResource(null,ps,rs);
}
return null;
}
public <E> E getValue(Connection conn,String sql,Object ... args) {
PreparedStatement ps = null;
ResultSet rs = null;
try {
ps = conn.prepareStatement(sql);
for (int i =0;i<args.length;i++){
ps.setObject(i+1,args[i]);
}
rs = ps.executeQuery();
if (rs.next()){
return (E) rs.getObject(1);
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
JDBCutils.closeResource(null,ps,rs);
}
return null;
}
}
7.2CustomerDao及CustomerDaoimpl的实现
此接口用于规范针对于Customer表的常用操作
CustomerDao
import bean.Customer;
import java.sql.Connection;
import java.sql.Date;
import java.util.List;
public interface CustomerDao {
void insert(Connection conn, Customer cust);
void deleteById(Connection conn,int id);
void update(Connection conn,Customer cust);
Customer getCustomerById(Connection conn,int id);
List<Customer> getAll(Connection conn);
long getCount(Connection conn);
Date getMaxDate(Connection conn);
}
CustomerDaoimpl
import bean.Customer;
import java.sql.Connection;
import java.sql.Date;
import java.util.List;
public class CustomerDaoimpl extends BaseDao implements CustomerDao{
@Override
public void insert(Connection conn, Customer cust) {
String sql="insert into customer(id,name,email,birthday)values(?,?,?,?)";
alter(conn,sql,cust.getId(),cust.getName(),cust.getEmail(),cust.getDate());
}
@Override
public void deleteById(Connection conn, int id) {
String sql="delete from customer where id = ?";
alter(conn,sql,id);
}
@Override
public void update(Connection conn,Customer cust) {
String sql="update customer set name = ?,email = ?,birthday = ? where id = ?";
alter(conn,sql,cust.getName(),cust.getEmail(),cust.getDate(),cust.getId());
}
@Override
public Customer getCustomerById(Connection conn, int id) {
String sql="select id,name,email,birthday from customer where id = ?";
Customer customer=getInstance(conn,Customer.class,sql,id);
return customer;
}
@Override
public List<Customer> getAll(Connection conn) {
String sql="select id,name,email,birthday from customer";
List<Customer> list=getForList(conn,Customer.class,sql);
return list;
}
@Override
public long getCount(Connection conn) {
String sql="select count(*) from customer";
return getValue(conn,sql);
}
@Override
public Date getMaxDate(Connection conn) {
String sql="select max(birthday) from customer";
return getValue(conn,sql);
}
}
8.数据库连接池
基本思想
为数据库连接建立一个缓冲池,预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需在缓冲区中取出一个,使用完放回即可,其负责分配管理和释放数据库连接,允许重复使用同一个连接,而不是重复建立连接。
8.1C3P0(了解)
所有的连接池都是需要首先导入jar包。
c3p0-config.xml配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<c3p0-config>
<named-config name="helloc3p0">
<property name="driverClass">com.mysql.cj.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/study</property>
<property name="user">root</property>
<property name="password">2767</property>
<property name="acquireIncrement">5</property>
<property name="initialPoolSize">10</property>
<property name="minPoolSize">10</property>
<property name="maxPoolSize">100</property>
<property name="maxStatements">50</property>
<property name="maxStatementsPerConnection">5</property>
</named-config>
</c3p0-config>
java代码
import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.sql.Connection;
import java.sql.SQLException;
public class C3P0Text1 {
public static void main(String[] args) throws SQLException {
ComboPooledDataSource cpds = new ComboPooledDataSource("helloc3p0");
Connection conn = cpds.getConnection();
System.out.println(conn);
}
}
8.2DBCP(了解)
java代码
import org.apache.commons.dbcp.BasicDataSource;
import java.sql.Connection;
import java.sql.SQLException;
public class DBCPText {
public static void main(String[] args) throws SQLException {
BasicDataSource source = new BasicDataSource();
source.setDriverClassName("com.mysql.cj.jdbc.Driver");
source.setUrl("jdbc:mysql://localhost:3306/study");
source.setUsername("root");
source.setPassword("2767");
source.setInitialSize(10);
source.setMaxActive(10);
Connection conn = source.getConnection();
System.out.println(conn);
}
}
类似于C3P0,我们也可以通过配置文件来进行连接,这里就不演示了,可以在DBCP的帮助文档中找到。
8.3Druid(重点)
Druid是开发中用的最多的连接池,需要掌握
通过加载druid.properties配置文件来建立连接
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Properties;
public class DruidText {
public static void main(String[] args) throws Exception {
Properties pros = new Properties();
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("druid.properties");
pros.load(is);
DataSource source = DruidDataSourceFactory.createDataSource(pros);
Connection conn = source.getConnection();
System.out.println(conn);
}
}
9.Apache-DBUtils实现增删改查
数据库连接池代替了创建连接 这一节就可以替换上文写的增删改查操作 上文写的就类似于底层的源码
还是一样的,使用前要先导入相应的jar包
这是Apache组织提供的一个开源JDBC工具类库,他是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化jdbc编码的工作量,同时也不会影响程序的性能。
9.1QueryRunner
import bean.Customer;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import util2.JDBCutils;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
public class QueryRunnerText {
public static void main(String[] args) {
QueryRunner runner = null;
Connection conn = null;
try {
runner = new QueryRunner();
conn = JDBCutils.getConnection();
String sql1="select id,name,email,birthday from customer where id = ?";
BeanHandler<Customer> handler = new BeanHandler<>(Customer.class);
Customer customer = runner.query(conn,sql1,handler,2);
System.out.println(customer);
String sql2="select id,name,email,birthday from customer where id < ?";
BeanListHandler<Customer> handler1 = new BeanListHandler<>(Customer.class);
List<Customer> list = runner.query(conn,sql2,handler1,3);
list.forEach(System.out::println);
String sql3="select count(*) from customer";
ScalarHandler handler2=new ScalarHandler();
Long count = (Long) runner.query(conn,sql3,handler2);
System.out.println(count);
} catch (SQLException e) {
e.printStackTrace();
}finally {
try {
DbUtils.close(conn);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
|