JDBC
https://www.bilibili.com/video/BV1Vy4y1z7EX/?spm_id_from=autoNext学习网址
JDBC
1.数据库驱动
驱动:声卡,显卡、数据库
我们的程序会通过数据库驱动,和数据库打交道!
2.JDBC
SUN公司为了简化开发人员的对数据库的统一 操作,提供了一一个Java操作数据库的规范,俗称JDBC
这些规范的实现由具体的厂商去做~对于开发人员来说,我们只需要掌握JDBC接口的操作即可
在框架中:没有什么是加一层解决不了的
java.sql
javax.sql
还需要导入一个数据库驱动包mysql-connector-java-8.0.25.jar这个8.0.25就是你数据库的版本
3第一个JDBC程序
创建测试数据库
CREATE TABLE users (
id INT PRIMARY KEY,
NAME VARCHAR (40) ,
PASSWORD VARCHAR (40),
email VARCHAR (60),
birthday DATE
);
INSERT INTO users (id, NAME, PASSWORD, email, birthday)
VALUES (1, 'zhansan', '123456', 'zs@sina.com', '1980-12-04'),
(2, 'lisi', '123456', 'lisiesina.com', '1981-12-04'),
(3,'wangwu','123456' ,' wangwuesina.com', ' 1979-12-04') ;
1.创建一个普通项目
2.导入数据库驱动
先新建一个lib目录:
将jar包导入
将其添加到library,否则不生效。
关闭这个就可以产生层级目录
3.编写测试代码
理解几个过程:
数据库登录账号密码,连接成功登录。现在给我们返回了一个数据库对象。这个数据库对象可以查看表的信息。真正去执行的时候我们需要编写sql。select * from users。
编写sql,点击运行就是执行对象。在数据库中可以点击的在java 中肯定是一个对象
在这里,执行的时候只有两种方法,我们把除了查询之外的都叫做update
一定要保证和数据库中的列名对应
可以按照类型去取假设不知道的话可以用getObject
package com.kuang.lesson01;
import java.sql.*;
//我的第一个JDBC程序
public class JdbcFirst {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1.加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");//固定写法,加载驱动
//2.用户信息和url
String url = "jdbc:mysql://localhost:3306/jdbctest?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8&useSSL=false";
String username = "root";
String password = "123456";
//3.连接成功,返回数据库对象connection就代表数据库
//驱动管理去获得连接
Connection connection = DriverManager.getConnection(url,username,password);
//4.执行的sql对象,这个就是用来执行sql对象
Statement statement = connection.createStatement();
//5.执行sql的对象 去执行sql 可能存在结果存在返回结果
String sql = "select * from users";
ResultSet resultSet = statement.executeQuery(sql);//返回结果集,结果集中封装了我们查询的所有对象
while(resultSet.next()){
System.out.println("id="+resultSet.getObject("id"));
System.out.println("name="+resultSet.getObject("NAME"));
System.out.println("PASSWORD="+resultSet.getObject("PASSWORD"));
System.out.println("email="+resultSet.getObject("email"));
System.out.println("birthday="+resultSet.getObject("birthday"));
System.out.println("-------------------");
}
//6.释放连接
resultSet.close();
statement.close();
connection.close();
}
}
运行结果:
步骤总结:
1、加载驱动
2、连接数据库DriverManager
3、获得执行sql的对象Statement
4、获得返回的结果集
5、释放连接
分析代码:
DriverManage
//其实我们可以这样写
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
但是点进Driver类的源码,可以看到这里面已经帮我注册好了
所以直接使用
Class.forName("com.mysql.cj.jdbc.Driver");//固定写法,加载驱动
//Connection代表数据库
Connection connection = DriverManager.getConnection(url,username,password);
//数据库设置自动提交
//事务提交
//自动回滚
connection.setAutoCommit();
connection.rollback();
connection.commit();
URL
String url = "jdbc:mysql://localhost:3306/jdbctest?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8&useSSL=false";
//但是mysql就是默认一个3306
//协议://主机地址:端口号/数据库名字?参数1&参数2&参数3
//Oracle默认1521
//jdbc:oracle:think@localhost:1521:sid
Statement执行SQL的对象
PrepareStatement
//4.执行的sql对象,这个就是用来执行sql对象
Statement statement = connection.createStatement();
String sql = "select * from users";//编写sql
statement.executeQuery();//查询操作返回结果集
statement.execute();//能够执行所有过程,但是需要一个判断的过程效率会低一点
statement.executeUpdate()//更新、插入、删除。都是用这个,返回一个受影响的行数
statement.executeBatch();//批处理,把多个sql放入进行执行
ReSultSet查询的结果集,封装了所有的查询结果
获得执行的数据类型
resultSet.getObject();//在不知道列类型的情况下使用
//如果知道列的类型就使用指定的类型
resultSet.getInt();
resultSet.getInt();
resultSet.getDate();
...
遍历,指针
resultSet.beforeFirst();//移动到最前面
resultSet.afterLast();//移动到最后面
resultSet.next()//移动到下一个数据
resultSet.previous();//移动到前一行
resultSet.absolute(row);//移动到指定行,拿到指定的数据
释放资源
//6.释放连接
resultSet.close();
statement.close();
connection.close();//消耗资源用完关掉
4statement对象
Jdbc中的statement对象用于向数据库发送SQL语句, 想完成对数据库的增删改查,只需要通过这个对象向数据库发送增删改
查语句即可。
Statement对象的executeUpdate方法,用于向数据库发送增、删、改的sql语句,executeUpdate执行完后, 将会返回一个整数(即增删改语句导致了数据库几行数据发生了变化)。
Statement.executeQuery方法用于向数据库发送查询语句,executeQuery方法返回代表查询结果的ResultSet对象。
CRUD操作 -create
使用executeUpdate(String sql)方法完成数据添加操作,示例操作:
Statement st = conn. createstatement();
String sq1 = "insert into ser...) values(...) ";
int num = st. executeupdate(sq1);
//如果受影响的行数大于1就说明执行插入成功
if (num>0){
System. out. print1n("插入成功! !");
}
CRUD操作 -delete
使用executeUpdate(String sql)方法完成数据删除操作,示例操作:
Statement st = conn.createstatement();
String sq1 = "delete from user where id=1";
int num = st.executeUpdate(sq1);
if(num>0){
System.out.print1n("删除成功! !");
}
CRUD操作 -update
使用executeUpdate(String sqI)方法完成数据修改操作,示例操作:
Statement st = conn. createstatement() ;
String sq1 = "update user set name='' where name=''";
int num = st. executeUpdate (sq1);
if (num>0){
System. out. printIn("修改成功! !");
}
CRUD操作-read
使用executeQuery(String sql)方法完成数据查询操作,示例操作:
Statement st = conn.createstatement() ;
String sq1 = "select * from user where id=1";
Resultset rs = st. executequery(sq1);
while(rs. next(){
//根据 获取列的数据类型,分别调用rs的相应方法映射到java对象中
}
代码实现
-
提取工具类
package com.kuang.lesson02.utils; import java.io.IOException; import java.io.InputStream; import java.sql.*; import java.util.Properties; public class JdbcUtils { private static String driver = null; private static String url = null; private static String username = null; private static String password = null; static { try{ InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");//获取具体的资源,一定要放在src目录下, // 如果放在其它目录下要写层级文件 Properties properties = new Properties(); properties.load(in); driver = properties.getProperty("driver"); url = properties.getProperty("url"); username = properties.getProperty("username"); password = properties.getProperty("password"); //1.驱动只需要加载一次 Class.forName(driver); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); } } //获取连接 public static Connection getConnection() throws SQLException { return DriverManager.getConnection(url,username,password); } //释放资源 public static void release(Connection conn, Statement st, ResultSet rs) throws SQLException { if(rs!=null){ try { rs.close(); }catch (Exception e){ e.printStackTrace(); } } if(st!=null){ try { st.close(); }catch (Exception e){ e.printStackTrace(); } } if( conn!=null){ try { conn.close(); }catch (Exception e){ e.printStackTrace(); } } } }
-
建立一个db.properties文件,放在src目录下,内容为:
driver = com.mysql.cj.jdbc.Driver
url = jdbc:mysql://localhost:3306/jdbctest?userUnicode = true&characterEncoding = utf8&&useSSL = true
username = root
password = 123456
错误:
处理:提示信息表明数据库驱动com.mysql.jdbc.Driver'已经被弃用了、应当使用新的驱动com.mysql.cj.jdbc.Driver'
所以,按照提示更改jdbc.properties配置 .com.mysql.jdbc.Driver 改为 com.mysql.cj.jdbc.Driver
-
编写工具类
package com.kuang.lesson02.utils; import java.io.IOException; import java.io.InputStream; import java.sql.*; import java.util.Properties; public class JdbcUtils { private static String driver = null; private static String url = null; private static String username = null; private static String password = null; static { try{ InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");//获取具体的资源,一定要放在src目录下, // 如果放在其它目录下要写层级文件 Properties properties = new Properties(); properties.load(in); driver = properties.getProperty("driver"); url = properties.getProperty("url"); username = properties.getProperty("username"); password = properties.getProperty("password"); //1.驱动只需要加载一次 Class.forName(driver); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); } } //获取连接 public static Connection getConnection() throws SQLException { return DriverManager.getConnection(url,username,password); } //释放资源 public static void release(Connection conn, Statement st, ResultSet rs) throws SQLException { if(rs!=null){ try { rs.close(); }catch (Exception e){ e.printStackTrace(); } } if(st!=null){ try { st.close(); }catch (Exception e){ e.printStackTrace(); } } if( conn!=null){ try { conn.close(); }catch (Exception e){ e.printStackTrace(); } } } }
-
编写增删改的方法
excuteUpdate
package com.kuang.lesson02;
import com.kuang.lesson02.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class TestInsert {
public static void main(String args[]) throws SQLException {
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();//获取数据库连接
st = conn.createStatement();//获得SQL的执行对象
String sql = "INSERT INTO users(id,NAME,PASSWORD,email,birthday)VALUES(4,'kuangshen','123456','12345679@qq.com','2021-01-01');";
int i = st.executeUpdate(sql);//返回的结果集
if(i>0){
System.out.println("插入成功");
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
JdbcUtils.release(conn,st,rs);
}
}
}
测试删除
package com.kuang.lesson02;
import com.kuang.lesson02.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class TestDelete {
public static void main(String args[]) throws SQLException {
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();//获取数据库连接
st = conn.createStatement();//获得SQL的执行对象
String sql = "DELETE FROM users WHERE id = 4;";
int i = st.executeUpdate(sql);//返回的结果集
if(i>0){
System.out.println("删除成功");
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
JdbcUtils.release(conn,st,rs);
}
}
}
测试更新
package com.kuang.lesson02;
import com.kuang.lesson02.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class TestUpdate {
public static void main(String args[]) throws SQLException {
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();//获取数据库连接
st = conn.createStatement();//获得SQL的执行对象
String sql = "UPDATE users SET id = 5 WHERE id = 3;";
int i = st.executeUpdate(sql);//返回的结果集
if(i>0){
System.out.println("更新成功");
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
JdbcUtils.release(conn,st,rs);
}
}
}
- 测试更新 excuteQuery
package com.kuang.lesson02;
import com.kuang.lesson02.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class TestSelect {
public static void main(String args[]) throws SQLException {
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();//获取数据库连接
st = conn.createStatement();//获得SQL的执行对象
String sql = "SELECT * from users";
rs = st.executeQuery(sql);//返回的结果集
while (rs.next()){
System.out.println(rs.getString("NAME"));
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
JdbcUtils.release(conn,st,rs);
}
}
}
sql注入的问题
sql存在漏洞,会被攻击导致数据泄露,SQL 拼接'or'
package com.kuang.lesson02;
import com.kuang.lesson02.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class SQLzhuru {
public static void main(String[] args) throws SQLException {
// login("kuangshen","123456");//正常登陆
login("'or '1=1","123456");//非正常登陆
}
//登录业务
public static void login(String username,String password) throws SQLException {
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();//获取数据库连接
st = conn.createStatement();//获得SQL的执行对象
//Select * from users where 'Name' = 'kuangshen' and 'password' = '123456';
String sql = "SELECT * from users where `name` = '" + username+"' and `password` = '" +password +"'";
rs = st.executeQuery(sql);//返回的结果集
while (rs.next()){
System.out.println(rs.getString("NAME"));
System.out.println(rs.getString("PASSWORD"));
System.out.println("===========================");
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
JdbcUtils.release(conn,st,rs);
}
}
}
正常登陆输出:
非正常登陆输出:(将数据里面有的东西全部都倒了出来)
上面那个实际上是执行了这个
Select * from users where 'Name' = ''or '1=1' and 'password' = '123456';
sql注入说白了就是拼接字符串
5 prepareStatement
PreparedStatement可以防止SQL注入。效率更好!
1.新增
package com.kuang.lesson03;
import com.kuang.lesson02.utils.JdbcUtils;
import java.sql.*;
import java.util.Date;
public class TestInsert {
public static void main(String args[]) throws SQLException {
Connection conn = null;
PreparedStatement st = null;
try {
conn = JdbcUtils.getConnection();
//区别
//使用 ?占位符代替参数
String sql = "insert into users(id,NAME,PASSWORD,EMAIL,birthday) values(?,?,?,?,?)";
st = conn.prepareStatement(sql);//预编译sql,先写sql,然后不执行
//手动给参数赋值
st.setInt(1, 3);
st.setString(2, "zhangsanfeng");
st.setString(3, "123456");
st.setString(4, "zs@sina.com");
//注意点 sql. Date 数据库 java. sql. Date()
//util. Date Java new Date(). getTime()获得时间戳
st.setDate(5, new java.sql.Date(new Date().getTime()));
//执行
int i = st.executeUpdate();
if (i > 0) {
System.out.println("插入成功");
}
}catch (Exception e){
e.printStackTrace();
}finally {
JdbcUtils.release(conn,st,null);
}
}
}
2.删除
package com.kuang.lesson03;
import com.kuang.lesson02.utils.JdbcUtils;
import java.sql.*;
import java.util.Date;
public class TestDelete{
public static void main(String args[]) throws SQLException {
Connection conn = null;
PreparedStatement st = null;
try {
conn = JdbcUtils.getConnection();
//区别
//使用 ?占位符代替参数
String sql = "delete from users where id = ?";
st = conn.prepareStatement(sql);//预编译sql,先写sql,然后不执行
//手动给参数赋值
st.setInt(1,3);
//执行
int i = st.executeUpdate();
if (i > 0) {
System.out.println("删除成功");
}
}catch (Exception e){
e.printStackTrace();
}finally {
JdbcUtils.release(conn,st,null);
}
}
}
删除成功
注意这里的1号和2号代表的是第一个?和第二个?,不是对应数据库里的第一列和第二类!!!所以第一个问号应该是String类型的name,第二个应该是 int 类型的id。
3.更新
package com.kuang.lesson03;
import com.kuang.lesson02.utils.JdbcUtils;
import java.sql.*;
import java.util.Date;
public class TestUpdate{
public static void main(String args[]) throws SQLException {
Connection conn = null;
PreparedStatement st = null;
try {
conn = JdbcUtils.getConnection();
//区别
//使用 ?占位符代替参数
String sql = "update users set NAME =? where id = ?";
st = conn.prepareStatement(sql);//预编译sql,先写sql,然后不执行
//手动给参数赋值
st.setString(1, "haha");
st.setInt(2, 1);
//执行
int i = st.executeUpdate();
if (i > 0) {
System.out.println("更新成功");
}
}catch (Exception e){
e.printStackTrace();
}finally {
JdbcUtils.release(conn,st,null);
}
}
}
注意几点:
从这里可以看出第一个参数是下标,第二个参数是具体的值。
参数是从1开始的
插入成功
4.查询
package com.kuang.lesson03;
import com.kuang.lesson02.utils.JdbcUtils;
import java.sql.*;
import java.util.Date;
public class TestSelect{
public static void main(String args[]) throws SQLException {
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();
//区别
//使用 ?占位符代替参数
String sql = "select * from users where id = ?;";
st = conn.prepareStatement(sql);//预编译sql,先写sql,然后不执行
//手动给参数赋值
st.setInt(1, 1);
//执行
rs = st.executeQuery();
if (rs.next()) {
System.out.println(rs.getString("NAME"));
}
}catch (Exception e){
e.printStackTrace();
}finally {
JdbcUtils.release(conn,st,rs);
}
}
}
5.注入测试
package com.kuang.lesson03;
import com.kuang.lesson02.utils.JdbcUtils;
import java.sql.*;
public class SQLzhuru {
public static void main(String[] args) throws SQLException {
login("lisi","123456"); //正常登录
// login("'or'1=1","123456");// 技巧
}
//登录业务
public static void login(String username,String password) throws SQLException {
Connection conn =null;
PreparedStatement st = null;
ResultSet rs = null;
try {
//在try里面的变量最后要释放是释放不了的必须提到前面去
conn = JdbcUtils.getConnection();//获取数据库连接
//PreparedStatement防止SQL注入的本质,把传递进来的参数当作字符、
//假设其中存在转移字符,就直接都忽略,比如说引号都会被直接转义
String sql = "select * from users where `NAME`= ? and `PASSWORD` = ?";
st = conn.prepareStatement(sql);//预编译
st.setString(1,username);
st.setString(2,password);
rs = st.executeQuery();//查询完毕会返回一个结果集
while(rs.next()){
System.out.println(rs.getString("NAME"));
System.out.println(rs.getString("password"));
System.out.println("======================");
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
JdbcUtils.release(conn,st,rs);
}
}
}
补充几个tips:
ctrl alt v可以快捷生成对象
ctrl alt t可以快捷生成包裹
6用idea连接数据库
点击这个图标,在侧边可以显示database
然后选中mysql
填写用户名密码,进行测试
此时进来发现只有一个schema数据库,然后我们点击刚才的页面点击schema选择
点击选择你想选择的数据库
双击数据库
打开表,随便选择一个进行修改,此时必须要点击提交按钮
点击这里可以进行sql语句的编写
几个注意的点:
连接失败查看原因
如果在idea里连接不上数据库的话,看一下lib目录是否导入
选中数据库配置,看看当前class是啥,可能版本不对
7事务
要么都成功,要么都失败
ACID原则
原子性:要么全部完成,要么都不完成
一致性:总数不变
隔离性:多个进程互不干扰
持久性:一单提交不可逆,持久化数据库了
隔离性的问题:
脏读:一个事务读取了另一个没有提交的事务。
不可重复读:在同一个事务内重复读取表中的数据,表的数据发生了改变
虚读:在一个事务内,读取到了别人插入的 数据,导致前后读出的数据不一致
关闭自动提交就是开启事务
报这个错的时候:
C:\Users\sgc\Downloads\demo\jdbc\out\production\jdbc;C:\Users\sgc\Downloads\demo\jdbc\lib\mysql-connector-java-8.0.25.jar com.kuang.lesson04.TestTransaction
java.sql.SQLException: Can not issue data manipulation statements with executeQuery().
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:129)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:89)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:63)
at com.mysql.cj.jdbc.StatementImpl.checkForDml(StatementImpl.java:365)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeQuery(ClientPreparedStatement.java:962)
at com.kuang.lesson04.TestTransaction.main(TestTransaction.java:22)
executeQurery()改成excuteUpdate()
executeQurery()改成execute()
那显然问题出在executeQurery()方法
继续百度,查出executeQurery()是一个查询方法,而不能进行修改操作(吐槽一句:……不都是让sql语句起作用嘛,干嘛还要设置多个方法)因此,如果你想要执行insert、update这类需要修改的操作,可以使用excuteUpdate()、execute()方法
失败了之后走了rollback,默认最终会回滚
代码实现
1.开启事务conn.setAutoCommit(false);
2.一组业务执行完毕提交事务
3.在catch语句中显示定义的回滚语句,但默认会回滚
package com.kuang.lesson04;
import com.kuang.lesson02.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class TestTransaction {
public static void main(String[] args) throws SQLException {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();
//对数据进行操作之前要关闭数据库的自动提交功能
conn.setAutoCommit(false);//开启事务
String sql1 = "update account set money = money-200 where name = 'A' ";
ps = conn.prepareStatement(sql1);
ps.executeUpdate();
int x = 1/0;//报错
String sql2 = "update account set money = money+100 where name = 'B'";
ps = conn.prepareStatement(sql2);
ps.executeUpdate();
//义务完毕提交事务
conn.commit();
System.out.println("操作成功");
} catch (SQLException e) {
try {
conn.rollback();
} catch (Exception throwables) {
throwables.printStackTrace();
}
e.printStackTrace();
}finally {
JdbcUtils.release(conn,ps,rs);
}
}
}
8数据库连接池
数据库连接-- 执行完毕--释放 连接--释放十分浪费系统资源
池化技术:准备一些预先的资源,过来就连接预先准备好的
开门-业务员:等待---服务---
常用连接数:10个
最小连接数: 10
最小连接数根据你的常用连接数来定。
最大连接数:15 业务最高承载上限,超过15个就得排队等待。
等待超时:100ms
编写连接池,实现一个接口datasource
开源数据源实现(拿来即用)
DBCP
C3P0
Druid:阿里巴巴
使用了数据库连接池之后,在项目中开发时就不用使用连接数据库的代码了
DBCP
需要用到的jar包
commons-dbcp-1.4.jar、commons-pool-1.6.jar
如果这里没有显示的话
将lib先delete掉,apply
然后右键lib,选择add as library
这样新东西就可以进来
在src目录下,新建一个dbcpconfig.properties
#连接设置 这里面的名字是 DBCP数据源中定义好的
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbctest?useUnicode=true&characterEncoding=utf8&useSSL=true
username=root
password=123456
#!-- 初始化连接 --
initialSize=10
#最大连接数量
maxActive=50
#!-- 最大空闲连接 --
maxIdle=20
#!-- 最小空闲连接 --
minIdle=5
#!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 --
maxWait=60000
#JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:【属性名=property;】
#注意:user 与 password 两个属性会被明确地传递,因此这里不需要包含他们。
connectionProperties=useUnicode=true;characterEncoding=UTF8
#指定由连接池所创建的连接的自动提交(auto-commit)状态。
defaultAutoCommit=true
#driver default 指定由连接池所创建的连接的只读(read-only)状态。
#如果没有设置该值,则“setReadOnly”方法将不被调用。(某些驱动并不支持只读模式,如:Informix)
defaultReadOnly=
#driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。
#可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
defaultTransactionIsolation=READ_UNCOMMITTED
package com.kuang.lesson05.utils;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
public class JdbcUtils_DBCP {
private static DataSource dataSource = null;
static {
try{
InputStream in = JdbcUtils_DBCP.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");//获取具体的资源,一定要放在src目录下,
// 如果放在其它目录下要写层级文件
Properties properties = new Properties();
properties.load(in);
//创建数据源 工厂模式--->创建对象
dataSource = BasicDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
//获取连接
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();//从数据源中获取连接
}
//释放资源
public static void release(Connection conn, Statement st, ResultSet rs) throws SQLException {
if(rs!=null){
try {
rs.close();
}catch (Exception e){
e.printStackTrace();
}
}
if(st!=null){
try {
st.close();
}catch (Exception e){
e.printStackTrace();
}
}
if( conn!=null){
try {
conn.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
}
package com.kuang.lesson05;
import com.kuang.lesson02.utils.JdbcUtils;
import com.kuang.lesson05.utils.JdbcUtils_DBCP;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Date;
public class TestDBCP {
public static void main(String[] args) throws SQLException {
Connection conn = null;
PreparedStatement st = null;
try {
conn = JdbcUtils_DBCP.getConnection();
//区别
//使用 ?占位符代替参数
String sql = "insert into users(id,NAME,PASSWORD,EMAIL,birthday) values(?,?,?,?,?)";
st = conn.prepareStatement(sql);//预编译sql,先写sql,然后不执行
//手动给参数赋值
st.setInt(1, 7);
st.setString(2, "zhangsanfeng");
st.setString(3, "123456");
st.setString(4, "zs@sina.com");
//注意点 sql. Date 数据库 java. sql. Date()
//util. Date Java new Date(). getTime()获得时间戳
st.setDate(5, new java.sql.Date(new Date().getTime()));
//执行
int i = st.executeUpdate();
if (i > 0) {
System.out.println("插入成功");
}
}catch (Exception e){
e.printStackTrace();
}finally {
JdbcUtils_DBCP.release(conn,st,null);
}
}
}
C3P0
需要导入的jar包
c3p0-0.9.5.5.jar、mchange-commons-java-0.2.19.jar
<?xml version="1.0" encoding="UTF-8"?>
<!--
c3p0-config.xml必须位于类路径下面
private static ComboPooledDataSource ds;
static{
try {
ds = new ComboPooledDataSource("MySQL");
} catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
}
-->
<c3p0-config>
<!--
C3P0的缺省(默认)配置,
如果在代码中“ComboPooledDataSource ds = new ComboPooledDataSource();”这样写就表示使用的是C3P0的缺省(默认)配置信息来创建数据源
-->
<default-config>
<property name="driverClass">com.mysql.cj.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbctest</property>
<property name="user">root</property>
<property name="password">123456</property>
<property name="acquireIncrement">5</property>
<property name="initialPoolSize">10</property>
<property name="minPoolSize">5</property>
<property name="maxPoolSize">20</property>
</default-config>
<!--
C3P0的命名配置,
如果在代码中“ComboPooledDataSource ds = new ComboPooledDataSource("MySQL");”这样写就表示使用的是name是MySQL的配置信息来创建数据源
-->
<named-config name="MySQL">
<property name="driverClass">com.mysql.cj.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbctest</property>
<property name="user">root</property>
<property name="password">123456</property>
<property name="acquireIncrement">5</property>
<property name="initialPoolSize">10</property>
<property name="minPoolSize">5</property>
<property name="maxPoolSize">20</property>
</named-config>
</c3p0-config>
package com.kuang.lesson05.utils;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class JdbcUtils_c3p0 {
private static ComboPooledDataSource dataSource = null;
static {
try{
//代码版配置
// dataSource = new ComboPooledDataSource();
// dataSource.setDriverClass();
// dataSource.setUser();
// dataSource.setPassword();
// dataSource.setJdbcUrl();
// dataSource.setMaxPoolSize();
// dataSource.setMinPoolSize();
//xml自动导入都不用读取
//创建数据源 工厂模式--->创建对象
dataSource = new ComboPooledDataSource("MySQL");//配置文件写法
} catch (Exception e) {
e.printStackTrace();
}
}
//获取连接
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();//从数据源中获取连接
}
//释放资源
public static void release(Connection conn, Statement st, ResultSet rs) throws SQLException {
if(rs!=null){
try {
rs.close();
}catch (Exception e){
e.printStackTrace();
}
}
if(st!=null){
try {
st.close();
}catch (Exception e){
e.printStackTrace();
}
}
if( conn!=null){
try {
conn.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
}
package com.kuang.lesson05;
import com.kuang.lesson05.utils.JdbcUtils_DBCP;
import com.kuang.lesson05.utils.JdbcUtils_c3p0;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Date;
public class Testc3p0 {
public static void main(String[] args) throws SQLException {
Connection conn = null;
PreparedStatement st = null;
try {
conn = JdbcUtils_c3p0.getConnection();//原来是自己实现的,现在用别人实现的
//区别
//使用 ?占位符代替参数
String sql = "insert into users(id,NAME,PASSWORD,EMAIL,birthday) values(?,?,?,?,?)";
st = conn.prepareStatement(sql);//预编译sql,先写sql,然后不执行
//手动给参数赋值
st.setInt(1, 9);
st.setString(2, "zhangsanfeng");
st.setString(3, "123456");
st.setString(4, "zs@sina.com");
//注意点 sql. Date 数据库 java. sql. Date()
//util. Date Java new Date(). getTime()获得时间戳
st.setDate(5, new java.sql.Date(new Date().getTime()));
//执行
int i = st.executeUpdate();
if (i > 0) {
System.out.println("插入成功");
}
}catch (Exception e){
e.printStackTrace();
}finally {
JdbcUtils_c3p0.release(conn,st,null);
}
}
}
结论
无论使用什么数据源,本质还是一样的,DataSource接口不会变,方法就不会变