JDBC
概述
JDBC,Java Database Connectivity(Java数据库连接),Sun公司退出的Java访问数据库的标准规范(接口),JDBC是一种用于执行SQL语句的Java API。
Sun公司提供访问数据库的规范叫做JDBC,而生产厂商提供规范的实现类叫做驱动。
JUnit


JUnit叫做单元测试,记得得先引入jar包,才能使用@Test注解,选中哪个方法就运行哪个方法,如果都不选,那么就运行所有具备@Test注解的方法
注意:单元测试的方法的格式必须是
@Test
public void 方法名(){
}
体验JDBC


package com.darksnow;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.junit.Test;
public class JDBCTest {
@Test
public void testQueryAll() {
ResultSet rs = null;
Statement stmt = null;
Connection conn = null;
try {
/*
* JDBC规范了定义驱动接口 ---> java.sql.Driver
* MySQL驱动包提供了上述规范的实现类 ---> com.mysql.jdbc.Driver
*
* 在java.sql.DriverManager中提供了注册驱动的方法:
* DriverManager.registerDriver(new com.mysql.jdbc.Driver());
* 但是以上的方式不推荐使用,原因:
* 1.硬编码,因为直接new的是对象,后期不便于扩展和维护
* 2.驱动被注册了两次
*
* 综上所述,我们通常使用Class.forName的方式将驱动类加载到内存
*/
//1.注册驱动 你不明白原理,你就把它当成记死的
Class.forName("com.mysql.jdbc.Driver");
/*
* public static Connection getConnection(String url, String user, String password)
*
* url参数:
* 连接mysql的地址,由三部分组成,每个部分用冒号(:)隔开
* 第一个部分,jdbc,这个是固定的
* 第二个部分,属于什么数据库,因为你用的是mysql的驱动,所以是连接mysql的,因此这里固定写mysql
* 第三个部分,一般都是“ //ip地址:端口号/要访问的数据库名 ” 这样的格式
* 注意:如果你要连接的数据库是本地数据库(自己电脑上),且端口号是默认的3306,那么可以简写为
* jdbc:mysql:///darksnow
* 其实就是省略掉了ip地址和端口号
*
* user参数:数据库的账号
*
* password参数:数据库的密码
*/
//2.获得mysql连接
String url = "jdbc:mysql://127.0.0.1:3306/darksnow";
String user = "root";
String password = "root";
conn = DriverManager.getConnection(url,user,password);
//3.通过连接对象Connection获得sql语句执行对象Statement
stmt = conn.createStatement();
//4.通过Statement对象执行sql语句 ResultSet的意思是"结果集" executeQuery的意思是"执行查询"
String sql = "select * from user";
rs = stmt.executeQuery(sql);
//5.处理结果集
while(rs.next()) {
/*
* boolean next() 类似于迭代器中的方法,判断是否还有下一条记录
*
* 注意:字段的索引从1开始计数
* String getString(int columnIndex):通过表中字段的索引来获取对应数据
* String getString(String columnLabel):通过表中字段的名称来获取对应数据
* int getInt(int columnIndex):作用和getString一样,只不过字段的类型int,所以用getInt,如果字段的类型是char或者varchar用getString
* int getInt(String columnLabel):通过表中字段的名称来获取对应数据
*
*/
//System.out.println("id:" + rs.getInt(1) + " --- name:" + rs.getString(2) + " --- age:" + rs.getInt(3));
System.out.println("id:" + rs.getInt("id") + " --- name:" + rs.getString("name") + " --- age:" + rs.getInt("age"));
}
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}finally {
//6.释放资源 不管程序是否正常执行,最后我们都要释放资源,但是有资源我们就释放,没资源就不管
if(rs != null) {
try {
rs.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if(stmt != null) {
try {
stmt.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if(conn != null) {
try {
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
模拟登陆
package com.darksnow;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;
import org.junit.Test;
/**
* 模拟登陆
* @author Administrator
*/
public class JDBCTestLogin {
@Test
public void testLogin() {
Scanner sc = new Scanner(System.in);
System.out.print("请输入账号:");
String username = sc.nextLine();
System.out.print("请输入密码:");
String password = sc.nextLine();
//调用登陆方法
//如果账号密码都是darksnow' or '1'='1也能够登录成功,这叫做SQL注入漏洞
//loginOne(username,password);
//调用登陆方法,已解决SQL主图
loginTwo(username,password);
sc.close();
}
/**
* 登陆的业务逻辑 此代码存在SQL注入的问题
* @param username 账号
* @param password 密码
*/
public static void loginOne(String username,String password){
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
conn = DriverManager.getConnection("jdbc:mysql:///darksnow","root","root");
//3.创建执行SQL语句的对象
stmt = conn.createStatement();
//4.执行SQL语句
String sql = "select * from t_user where username = '" + username + "' and password = '" + password + "'";
rs = stmt.executeQuery(sql);
//5.处理结果集 next刚开始是从0开始的,如果你的username和password正确,那么就会得到一条记录,next的结果为true,因为从0到1了
if(rs.next()) {
System.out.println("恭喜您," + rs.getString("name") + "登录成功!");
}else {
System.out.println("账号或密码错误!");
}
System.out.println(sql);
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
} finally {
//6.释放资源
if(rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
/**
* 登陆的业务逻辑 此代码可以解决SQL注入的问题
* @param username 账号
* @param password 密码
*/
public static void loginTwo(String username,String password){
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
conn = DriverManager.getConnection("jdbc:mysql:///darksnow","root","root");
//3.创建执行SQL语句的对象,下面SQL语句中的问号就是占位符
String sql = "select * from t_user where username = ? and password = ?";
pstmt = conn.prepareStatement(sql); //预编译处理对象
//4.设置参数,给占位符设置值
//参数一是占位符所在的位置(也就是问号所在的位置,从1开始计数),参数二是给占位符指定值
pstmt.setString(1, username);
pstmt.setString(2, password);
//5.执行查询操作
rs = pstmt.executeQuery();
//6.处理结果集 next刚开始是从0开始的,如果你的username和password正确,那么就会得到一条记录,next的结果为true,因为从0到1了
if(rs.next()) {
System.out.println("恭喜您," + rs.getString("name") + "登录成功!");
}else {
System.out.println("账号或密码错误!");
}
System.out.println(sql);
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
} finally {
//7.释放资源
if(rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(pstmt != null) {
try {
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
封装工具类
1.JDBCUtilVersion1
package com.darksnow.utils;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
* 我们发现每次都会去注册驱动,获取连接,释放资源 感觉比较重复
* 所以我们将这些操作封装成了一个工具类,以便于提高代码的复用性
*/
public class JDBCUtilVersion1 {
private JDBCUtilVersion1() {}
/**
* 获取连接的方法
* @return 连接对象
*/
public static Connection getConnection() {
Connection conn = null;
try {
//注册驱动
Class.forName("com.mysql.jdbc.Driver");
//获取连接
conn = DriverManager.getConnection("jdbc:mysql:///darksnow","root","root");
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
return conn;
}
/**
* 释放资源的方法
* @param conn 连接对象
* @param pstmt 预编译处理对象
* @param rs 结果集对象
*/
public static void close(Connection conn, Statement pstmt, ResultSet rs) {
if(rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(pstmt != null) {
try {
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
2.JDBCUtilVersion2
package com.darksnow.utils;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ResourceBundle;
/**
* JDBCUtilVersion1 虽然提高了代码的复用性
* 但是,里面的链接信息,驱动信息都是写死的(存在硬编码问题)
* 所以在JDBCUtilVersion2 我们主要解决的就是硬编码问题
*
* 思路:通过配置文件来获取配置,不写死在代码中
*/
public class JDBCUtilVersion2 {
private JDBCUtilVersion2() {}
private static String driver;
private static String url;
private static String username;
private static String password;
//静态代码块加载配置文件信息,随着类的加载,而只加载一次
static {
//读取db.properties文件
ResourceBundle bundle = ResourceBundle.getBundle("db");
driver = bundle.getString("driver");
url = bundle.getString("url");
username = bundle.getString("username");
password = bundle.getString("password");
}
/**
* 获取连接的方法
* @return 连接对象
*/
public static Connection getConnection() {
Connection conn = null;
try {
//注册驱动
Class.forName(driver);
//获取连接
conn = DriverManager.getConnection(url,username,password);
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
return conn;
}
/**
* 释放资源的方法
* @param conn 连接对象
* @param pstmt 预编译处理对象
* @param rs 结果集对象
*/
public static void close(Connection conn, Statement pstmt, ResultSet rs) {
if(rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(pstmt != null) {
try {
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
3.JDBCUtilVersion3
package com.darksnow.utils;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
/**
* 在JDBCUtilVersion2 这个工具类中properties配置文件是通过ResourceBundle来加载
* 现在我们使用另外一种方式来加载配置文件。
*
* JDBCUtilVersion3和JDBCUtilVersion2只是加载配置文件的方式不同,效果是一样的。
*/
public class JDBCUtilVersion3 {
private JDBCUtilVersion3() {
}
private static String driver;
private static String url;
private static String username;
private static String password;
// 静态代码块加载配置文件信息,随着类的加载,而只加载一次
static {
try {
//通过当前类获取类加载器
ClassLoader classLoader = JDBCUtilVersion3.class.getClassLoader();
//通过类加载器获得一个输入流 ---> 用来读
InputStream is = classLoader.getResourceAsStream("db.properties");
//创建一个Properties对象
Properties props = new Properties();
//加载输入流
props.load(is);
//获取相关的配置信息
driver = props.getProperty("driver");
url = props.getProperty("url");
username = props.getProperty("username");
password = props.getProperty("password");
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 获取连接的方法
* @return 连接对象
*/
public static Connection getConnection() {
Connection conn = null;
try {
//注册驱动
Class.forName(driver);
//获取连接
conn = DriverManager.getConnection(url,username,password);
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
return conn;
}
/**
* 释放资源的方法
* @param conn 连接对象
* @param pstmt 预编译处理对象
* @param rs 结果集对象
*/
public static void close(Connection conn, Statement pstmt, ResultSet rs) {
if(rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(pstmt != null) {
try {
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
db.properties
这个是配置文件,这个配置文件需要放到src下面
driver=com.mysql.jdbc.Driver
url=jdbc:mysql:///darksnow
username=root
password=root
结合工具类做CRUD操作
package com.darksnow;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.junit.Test;
import com.darksnow.utils.JDBCUtilVersion3;
/**
* 结合前面写的工具类,作增删改查的操作
* CRUD(增查改删):增(Create),检索(Retrieve),更新(Update),删除(Delete)
*
* 增删改用的都是executeUpdate方法
* 查询用的是executeQuery方法
*/
public class JDBCTestCrud {
/**
* 根据id更新用户名称
*/
@Test
public void testUpdateById() {
Connection conn = null;
PreparedStatement pstmt = null;
try {
//获取连接
conn = JDBCUtilVersion3.getConnection();
//编写SQL语句
String sql = "update t_user set username=? where id=?";
//获取执行sql语句的对象
pstmt = conn.prepareStatement(sql);
//设置参数
pstmt.setString(1, "admin");
pstmt.setInt(2, 2);
//执行更新操作
int row = pstmt.executeUpdate(); //返回值表示更新了多少行
if(row > 0) {
System.out.println("更新成功~");
}else {
System.out.println("更新失败~");
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
//释放资源
JDBCUtilVersion3.close(conn, pstmt, null);
}
}
/**
* 根据id删除信息
*/
@Test
public void testDeleteById() {
Connection conn = null;
PreparedStatement pstmt = null;
try {
//获取连接
conn = JDBCUtilVersion3.getConnection();
//编写SQL语句
String sql = "delete from t_user where id=?";
//获取执行sql语句的对象
pstmt = conn.prepareStatement(sql);
//设置参数
pstmt.setInt(1, 2);
//执行删除操作
int row = pstmt.executeUpdate(); //返回值表示删除了多少行
if(row > 0) {
System.out.println("删除成功~");
}else {
System.out.println("删除失败~");
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
//释放资源
JDBCUtilVersion3.close(conn, pstmt, null);
}
}
/**
* 添加用户信息
*/
@Test
public void testInsert() {
Connection conn = null;
PreparedStatement pstmt = null;
try {
//获取连接
conn = JDBCUtilVersion3.getConnection();
//编写SQL语句
String sql = "insert into t_user values(null,?,?,?)";
//获取执行sql语句的对象
pstmt = conn.prepareStatement(sql);
//设置参数
pstmt.setString(1, "maliu");
pstmt.setString(2, "12580");
pstmt.setString(3, "马六");
//执行新增操作
int row = pstmt.executeUpdate(); //返回值表示新增了多少行
if(row > 0) {
System.out.println("新增成功~");
}else {
System.out.println("新增失败~");
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
//释放资源
JDBCUtilVersion3.close(conn, pstmt, null);
}
}
/**
* 根据id查询用户信息
*/
@Test
public void testFindById() {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
//获取连接
conn = JDBCUtilVersion3.getConnection();
//编写sql语句
String sql = "select * from t_user where id=?";
//获取执行SQL语句的对象
pstmt = conn.prepareStatement(sql);
//设置参数
pstmt.setInt(1, 3);
//执行查询操作
rs = pstmt.executeQuery();
//处理结果集
while(rs.next()) {
System.out.println(rs.getString("username") + " --- " + rs.getString("password") + " --- " + rs.getString("name"));
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
//关闭资源
JDBCUtilVersion3.close(conn, pstmt, rs);
}
}
}
连接池
1.存在的问题
原来我们写的程序,获取连接和释放资源是非常消耗系统资源的,所以我们可以使用连接池技术来解决这个问题。

2.实现自定义连接池
package com.darksnow.utils;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.LinkedList;
public class JDBCPoolUtil {
private JDBCPoolUtil() {
}
//1.创建一个容器(连接池),用于存放Connection
private static LinkedList<Connection> pool = new LinkedList<>();
//2.初始化连接池的连接 让连接池一开始就具备一些连接
static {
try {
//注册驱动
Class.forName("com.mysql.jdbc.Driver");
for(int i=1; i<=5; i++) {
//生成连接
Connection conn = DriverManager.getConnection("jdbc:mysql:///darksnow","root","root");
//将生成的连接放入到连接池中
pool.add(conn);
}
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
}
/**
* 从连接池中获取连接
* @return 连接对象
*/
public static Connection getConnection() throws InterruptedException {
//如果连接池有连接的情况下
//pool.isEmpty() == true,连接池是空的;pool.isEmpty() == false,连接池不是空的。
if(!pool.isEmpty()) {
//连接池不是空的才能够进到if内部
//使用get方法时不合理的,因为get方法虽然能够拿到连接,但是拿到的连接依旧还在连接池
//removeFirst() 删除集合中的第一个元素,并且将这个第一个元素给返回
return pool.removeFirst();
}
//如果连接池没有连接的情况下 等5秒再获取
Thread.sleep(5000);
return getConnection();
}
/**
* 将使用完的连接放回连接池
* @param conn
*/
public static void backConn(Connection conn) {
if(conn != null) {
pool.add(conn);
}
}
}
package com.darksnow;
import java.sql.Connection;
import com.darksnow.utils.JDBCPoolUtil;
class ThreadTest extends Thread{
@Override
public void run() {
try {
Connection conn = JDBCPoolUtil.getConnection();
System.out.println(conn + "---" + Thread.currentThread().getName());
JDBCPoolUtil.backConn(conn);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class TestPool {
public static void main(String[] args) {
for(int x=1; x<=15; x++) {
new ThreadTest().start();
}
}
}
C3P0连接池

1.配置文件
此配置文件名字必须叫做c3p0-config.xml,别乱改
此配置文件目前放在src下
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql:///darksnow</property>
<property name="user">root</property>
<property name="password">root</property>
<!-- 指定最开始连接池的连接数量 -->
<property name="initialPoolSize">5</property>
<!-- 指定最最大连接数 -->
<property name="maxPoolSize">20</property>
</default-config>
<named-config name="darksnow">
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql:///darksnow</property>
<property name="user">root</property>
<property name="password">root</property>
</named-config>
</c3p0-config>
2.封装工具类
package com.darksnow.utils;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
/**
* C3P0的相关工具类
*
* 你可以把数据源看成是连接池
*/
public class C3P0Util {
//私有构造函数,不让其创建对象
private C3P0Util() {
}
/*
* 这里ComboPooledDataSource的构造函数传入了一个"darksnow"的字符串参数,那么就会去使用c3p0-config.xml配置文件中的
* <named-config name="darksnow">下面的配置
*
* 如果ComboPooledDataSource用的是无参构造,那么就会去使用c3p0-config.xml配置文件中的
* <default-config>下面的配置
*/
// private static ComboPooledDataSource dataSource = new ComboPooledDataSource("darksnow");
private static ComboPooledDataSource dataSource = new ComboPooledDataSource(); //设置数据源
/**
* javax.sql.DataSource 是Java提供的原生接口,各大厂商实现连接池需要实现这个接口
* 获取数据源的方法
*/
public static DataSource getDataSource() {
return dataSource;
}
/**
* 获取连接的方法
*/
public static Connection getConnection() {
try {
return dataSource.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
3.编写测试类
package com.darksnow.test;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import org.junit.Test;
import com.darksnow.utils.C3P0Util;
public class C3P0Test {
@Test
public void testC3P0() {
Connection conn = null;
PreparedStatement pstmt = null;
try {
//从连接池里获取连接
conn = C3P0Util.getConnection();
//编写SQL
String sql = "insert into t_user values(null,?,?,?)";
//获取预编译处理对象
pstmt = conn.prepareStatement(sql);
//给占位符设置值
pstmt.setString(1, "laoba");
pstmt.setString(2, "laoba666");
pstmt.setString(3, "老八");
//执行SQL语句
int rows = pstmt.executeUpdate();
if(rows > 0) {
System.out.println("数据添加成功~");
}else {
System.out.println("数据添加失败~");
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
if(pstmt != null) {
try {
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
DBCP连接池

1.配置文件
这个配置文件的名字可以任意命名,但是要以properties结尾
properties文件不支持中文
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///darksnow
username=root
password=root
2.封装工具类
package com.darksnow.utils;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
public class DBCPUtil {
private DBCPUtil() {
}
private static DataSource dataSource = null;
static {
try {
//将db.properties配置加载到文件输入流中
InputStream is = DBCPUtil.class.getClassLoader().getResourceAsStream("db.properties");
//加载文件输入流来获取配置信息
Properties properties = new Properties();
properties.load(is);
//得到数据源 BasicDataSourceFactory ---> 数据源工厂
dataSource = BasicDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取数据源的方法
*/
public static DataSource getDataSource() {
return dataSource;
}
/**
* 获取连接的方法
*/
public static Connection getConnection() {
try {
return dataSource.getConnection();
} catch (SQLException e) {
throw new RuntimeException();
}
}
}
3.编写测试类
package com.darksnow.test;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import org.junit.Test;
import com.darksnow.utils.DBCPUtil;
public class DBCPTest {
@Test
public void testDBCP() {
Connection conn = null;
PreparedStatement pstmt = null;
try {
//获取连接
conn = DBCPUtil.getConnection();
//编写SQL语句
String sql = "update t_user set name=? where id=?";
//获取预编译处理对象
pstmt = conn.prepareStatement(sql);
//给占位符设置值
pstmt.setString(1, "龙霸天");
pstmt.setInt(2, 4);
//执行SQL语句
int rows = pstmt.executeUpdate();
if(rows > 0) {
System.out.println("老八下线,龙霸天上线~");
}else {
System.out.println("龙霸天谋朝串位失败~");
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
//释放资源
if(pstmt != null) {
try {
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
DBUtils工具
1.概述
作用:简化书写,提升开发效率,顾名思义它是针对JDBC相关开发的。
三大核心:
QueryRunner:该类提供了对SQL进行操作的一些API
ResultSetHandler:它是一个接口,跟结果处理有关,提供了好几种结果处理的方式
DBUtils还提供了关闭资源与事物处理的方法
用于做增删改的API

2.利用DBUtils做增删改
package com.darksnow.test;
import java.sql.SQLException;
import org.apache.commons.dbutils.QueryRunner;
import org.junit.Test;
import com.darksnow.utils.C3P0Util;
public class TestDBUtilsOne {
/**
* 添加用户
*/
@Test
public void testAddUser() {
try {
//创建QueryRunner对象
QueryRunner qr = new QueryRunner(C3P0Util.getDataSource());
//编写SQL
String sql = "insert into t_user values(null,?,?,?)";
//给占位符设置值
Object[] params = {"fastjson","tomcat","程序猿"};
//执行SQL语句
int rows = qr.update(sql,params);
if(rows > 0) {
System.out.println("添加成功~");
}else {
System.out.println("添加失败~");
}
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 修改用户的真实名称(name字段)
*/
@Test
public void testUpdateByName() {
try {
//创建QueryRunner对象
QueryRunner qr = new QueryRunner(C3P0Util.getDataSource());
//编写SQL
String sql = "update t_user set name=? where id=?";
//给占位符设置值
Object[] params = {"随便", 5};
//执行SQL语句
int rows = qr.update(sql,params);
if(rows > 0) {
System.out.println("修改成功~");
}else {
System.out.println("修改失败~");
}
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 删除用户
*/
@Test
public void testDeleteById() {
try {
//创建QueryRunner对象
QueryRunner qr = new QueryRunner(C3P0Util.getDataSource());
//编写SQL
String sql = "delete from t_user where id=?";
//执行SQL语句
int rows = qr.update(sql, 5);
if(rows > 0) {
System.out.println("删除成功~");
}else {
System.out.println("删除失败~");
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
3.利用DBUtils做查询
Ctrl + T 可以查看一个接口的实现类

(1)KeyedHandler:可以将结果集中的每一条数据都封装到一个Map<String,Object>集合中,再将这个map作为另外一个map的value,而另一个map的key是指定的字段名(Map<String,Map<String,Object>>)
(2)ArrayListHandler:将结果集的每一条数据都封装到一个Object数组中,再将这些数组封装到List集合中(List<Object[]>)
(3)ColumnListHandler:将结果集中指定的列的字段值封装到一个List集合中
(4)MapListHandler:将结果集中的每一条数据都封装到一个Map<String,Object>集合中,再将Map集合封装到List集合中(List<Map<String,Object>>),key为字段名,value为字段的值
(5)ArrayHandler:将结果集中的第一条数据封装到一个Object数组中,数组中的每一个元素是这条数据的每个字段的值
(6)BeanHandler(重点):将结果集中的每一条数据封装到一个指定的JavaBean中
(7)BeanListHandler(重点):将结果集中的每一条数据封装到一个指定的JavaBean中,再把JavaBean封装到List集合中
(8)MapHandler:将结果集中的每一条数据都封装到一个Map<String,Object>集合中,key为字段名,value为字段的值
(9)ScalarHandler(重点):它一般用于单个数据的处理,比如:select count(*) from user;
用于做查询的API

JavaBean实体
package com.darksnow.bean;
/**
* 这就是JavaBean 对象实体
* 此对象的成员变量名和数据库的字段名是一一对应的,数据类型也是对应的
*
* 一个实体对象基本上对应一条数据
*/
public class User {
private int id;
private String username;
private String password;
private String name;
public User() {
}
public User(int id, String username, String password, String name) {
this.id = id;
this.username = username;
this.password = password;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", password=" + password + ", name=" + name + "]";
}
}
查询操作
package com.darksnow.test;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import org.junit.Test;
import com.darksnow.bean.User;
import com.darksnow.utils.C3P0Util;
/**
* 利用DBUtils做查询
*/
public class TestDBUtilsTwo {
/**
* 查询所有用户
*/
@Test
public void testFindAll() {
try {
QueryRunner qr = new QueryRunner(C3P0Util.getDataSource());
String sql = "select * from t_user";
//BeanListHandler的泛型为指定的JavaBean的类型,参数为指定的JavaBean的字节码文件对象
List<User> result = qr.query(sql, new BeanListHandler<User>(User.class));
//遍历结果
for(User u : result) {
System.out.println(u);
}
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 查询单条用户数据
*/
@Test
public void testFindById() {
try {
QueryRunner qr = new QueryRunner(C3P0Util.getDataSource());
String sql = "select * from t_user where id=?";
User result = qr.query(sql, new BeanHandler<User>(User.class), 1);
System.out.println(result);
}catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 统计用户的个数
*/
@Test
public void testCountUser() {
try {
QueryRunner qr = new QueryRunner(C3P0Util.getDataSource());
String sql = "select count(id) from t_user";
/*
* 如果对于重载的query觉得太难看懂了,那么你就记住调用query方法的时候,
* 第一个传sql,第二个传结果集处理对象,第三个传参数(可选项)
* 如果不需要传参数,那么你第一个传sql,第二个传结果集处理对象就行了
*/
Long result = (Long) qr.query(sql, new ScalarHandler()); //返回值本来是Object,但一般我们把它转为包装类型Long
System.out.println("用户的总数为:" + result);
}catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 自己动手处理结果集 了解
*
* 需求:根据id查询出一条数据,查出来的数据,对name字段的值加上一个"开发部"
*/
@Test
public void testHandler() {
try {
QueryRunner qr = new QueryRunner(C3P0Util.getDataSource());
String sql = "select * from t_user where id=?";
User user = qr.query(sql, new ResultSetHandler<User>() {
@Override
public User handle(ResultSet rs) throws SQLException {
try {
//编写自己的处理逻辑
User u = new User();
if(rs.next()) {
u.setId(rs.getInt("id"));
u.setName(rs.getString("username"));
u.setPassword(rs.getString("password"));
u.setName("开发部" + rs.getString("name"));
return u;
}
}finally {
if(rs != null) {
rs.close();
}
}
return null;
}
}, 1);
System.out.println(user);
}catch (SQLException e) {
e.printStackTrace();
}
}
}

浙公网安备 33010602011771号