目录
2.1 PreparedStatement 预编译的SQL执行环境
2.3 PreparedStatement与Statement谁的性能高?
一,JDBC简介
1,简介
Java DataBase Connectivity Java数据库连接
我们学习的技术是JDBC 不是 MYSQLJDBC 也不是 ORACLE JDBC
JDBC是一套标准,是Java与各大数据库厂商共同定制的一套接口. 这套接口由各大数据库厂商进行了实现.
2,发展历史
自从Java语言于1995年5月正式公布以来,Java风靡全球。
出现大量的用java语言编写的程序,其中也包括数据库应用程序。由于没有一个Java语言的数据库操作API,编程人员不得不在Java程序中加入C语言的ODBC函数调用。这就使很多Java的优秀特性无法充分 发挥,比如平台无关性、面向对象特性等。
随着越来越多的编程人员对Java语言的日益喜爱,越来越多的公司在Java程序开发上投入的精力日益增加,对java语言接口的访问数据库的API的要求越来越强烈。也由于ODBC的有其不足之处,比如它并不容易使用,没有面向对象的特性等等,SUN公司决定开发一Java语言为接口的数据库应用程序开发接口。
在JDK1.x版本中,JDBC只是一个可选部件,到了JDK1.1公布时,SQL类包(也就是JDBCAPI)就成为 Java语言的标准部件。
二,JDBC标准流程
1,使用步骤*
1. 引入jar文件.
2. 加载数据库驱动 (JavaSE项目中可以省略 , JavaWeb项目必须编写此步骤) Class.forName("com.mysql.jdbc.Driver");
3. 通过驱动管理器, 获取JDBC连接对象.
- Connection conn = DriverManager.getConnection("数据库连接地址","帐号","密码");
- // 数据库连接地址格式: 主协议:子协议://ip地址:端口号/数据库名称
- // mysql的连接地址: jdbc:mysql://localhost:3306/java35
- // oracle的连接地址: jdbc:oracle:thin:@localhost:1521:ORCL
4. 通过连接对象, 创建SQL执行对象 (SQL执行环境) Statement state = conn.createStatement();
5. 通过SQL执行对象 ,执行SQL语句. state.execute(String sql语句);
6. 释放资源
- state.close();
- conn.close();
2,配置lib
1,将需要的jar文件复制到lib中
2,打开file/Project Structure,其中Modules、Libraries原样如下:
3,配置Libraries
(记得apply进行保存)
4,配置Modules
(记得apply进行保存)
3,代码实现
1,实现基本的查询流程
package com.java.demo;
import java.sql.*;
public class Demo1 {
public static void createTable() throws ClassNotFoundException, SQLException {
//1. 加载数据库驱动 (可以省略的. 在JavaEE的web项目中,jar包不可以省略.)
// mysql6以下驱动:com.mysql.jdbc.Driver
// mysql6和6以上驱动:com.mysql.cj.jdbc.Driver
Class.forName("com.mysql.jdbc.Driver");// 在mysql-connector-java-5.1.37-bin.jar中
//2. 通过驱动管理器, 获取JDBC的连接对象
// 连接地址格式:
// 主协议:子协议://ip地址:端口号/数据库名称
// mysql: jdbc:mysql://localhost:3306/test
// oracle: jdbc:oracle:thin:@ip地址:1521/ORCL
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "123");
//3. 通过连接对象,创建SQL执行对象 (SQL执行环境)
Statement state = conn.createStatement();
//4. 通过SQL执行对象 执行SQL
state.execute("create table person(id int,nickname varchar(32))");// 返回值不是成功或失败,true:查询语句,false:其他语句
//5. 释放连接
state.close();
conn.close();
}
}
2,添加测试方法
(需要提前引入jar包)
Alt+insert(右击也可找到)调出generate界面,选择Test选项
3,创建添加数据的代码
demo.java
package com.java.demo;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class Demo {
public static void createTable() throws ClassNotFoundException, SQLException {
//1. 加载数据库驱动 (可以省略的. 在JavaEE的web项目中,jar包不可以省略.)
// mysql6以下驱动:com.mysql.jdbc.Driver
// mysql6和6以上驱动:com.mysql.cj.jdbc.Driver
Class.forName("com.mysql.jdbc.Driver");// 在mysql-connector-java-5.1.37-bin.jar中
//2. 通过驱动管理器, 获取JDBC的连接对象
// 连接地址格式:
// 主协议:子协议://ip地址:端口号/数据库名称
// mysql: jdbc:mysql://localhost:3306/test
// oracle: jdbc:oracle:thin:@ip地址:1521/ORCL
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/demo", "root", "2017217905");
//3. 通过连接对象,创建SQL执行对象 (SQL执行环境)
Statement state = conn.createStatement();
//4. 通过SQL执行对象 执行SQL
state.execute("create table person(id int,nickname varchar(32))");// 返回值不是成功或失败,true:查询语句,false:其他语句
//5. 释放连接
state.close();
conn.close();
}
public static void insertData() throws Exception {
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8", "root", "123");
Statement state = conn.createStatement();
state.execute("insert into person values(1,'张三')");
state.close();
conn.close();
}
}
三,增删改查
1,JDBC中常用的类型和方法
1. DriverManager : 驱动管理器
常用方法:
- 获取数据库连接:
static Connection getConnection(String 数据库地址,String 账号 ,String 密 码)
2. Connection : 数据库连接对象
常用方法:
- 创建SQL执行对象:
Statement createStatement();
3. Statement : SQL执行对象
常用方法:
- 执行SQL语句(查询语句返回true, 其它语句返回false)
boolean execute(String sql);
- 执行DML语句(INSERT UPDATE DELETE) 和 DDL语句(create alter drop) (返回int值, 表示语句对数据库表格的影响行数 !) (通常我们认为 返回值>0 表示执行成功.)
int executeUpdate(String sql);
- 执行DQL语句 (select)
ResultSet executeQuery(String sql);
4. ResultSet : 结果集对象 (指的是一个select语句的查询结果)
常用方法:
1. 控制游标移动的常用方法:
// 作用: 控制游标向下一行移动.
// 返回值: 移动成功返回true , 下一行不存在移动失败, 返回 false
boolean next()
// 作用: 控制游标向上一行移动.
// 返回值: 移动成功返回true , 上一行不存在移动失败, 返回 false
boolean privious()
// 作用: 控制游标向指定行移动
// 返回值: 移动成功返回true , 行不存在移动失败, 返回false
boolean absolute(int 行号) //了解
// 作用: 控制游标移动到第一行
// 返回值: 移动成功返回true, 没有第一行数据返回false
boolean beforeFirst() // 了解
// 作用: 控制游标移动到最后一行
// 返回值: 移动成功返回true, 没有最后一行数据返回false
boolean afterLast() // 了解
2. 获取游标指向行的字段值的常用方法:
// 根据字段名, 得到此字段的值
XXX getXXX(String 列名) ***
// 根据字段的索引, 得到字段的值 , 索引从1开始
XXX getXXX(int 字段的索引) *
2,代码演示
package com.java.demo;
import java.sql.*;
public class Demo1 {
public static void createTable() throws ClassNotFoundException, SQLException {
//1. 加载数据库驱动 (可以省略的. 在JavaEE的web项目中,jar包不可以省略.)
// mysql6以下驱动:com.mysql.jdbc.Driver
// mysql6和6以上驱动:com.mysql.cj.jdbc.Driver
Class.forName("com.mysql.jdbc.Driver");// 在mysql-connector-java-5.1.37-bin.jar中
//2. 通过驱动管理器, 获取JDBC的连接对象
// 连接地址格式:
// 主协议:子协议://ip地址:端口号/数据库名称
// mysql: jdbc:mysql://localhost:3306/test
// oracle: jdbc:oracle:thin:@ip地址:1521/ORCL
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "123");
//3. 通过连接对象,创建SQL执行对象 (SQL执行环境)
Statement state = conn.createStatement();
//4. 通过SQL执行对象 执行SQL
state.execute("create table person(id int,nickname varchar(32))");// 返回值不是成功或失败,true:查询语句,false:其他语句
//5. 释放连接
state.close();
conn.close();
}
public static void insertData() throws Exception {
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8", "root", "123");
Statement state = conn.createStatement();
state.execute("insert into person values(1,'张三')");
state.close();
conn.close();
}
public static void insertPerson() throws Exception {
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8", "root", "123");
Statement state = conn.createStatement();
int flag = state.executeUpdate("insert into person values(1,'张三'),(2,'李四'),(3,'王二麻子')");
state.close();
conn.close();
System.out.println("返回:"+flag);
}
public static void deletePerson() throws Exception {
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8", "root", "123");
Statement state = conn.createStatement();
int flag = state.executeUpdate("delete from person where id=1");
state.close();
conn.close();
System.out.println("返回:"+flag);
}
public static void updatePerson() throws Exception {
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8", "root", "123");
Statement state = conn.createStatement();
int flag = state.executeUpdate("update person set nickname='haha' where id=2");
state.close();
conn.close();
System.out.println("返回:"+flag);
}
public static void selectPerson() throws Exception {
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8", "root", "123");
Statement state = conn.createStatement();
ResultSet rs = state.executeQuery("select * from person");
while(rs.next()){
int id = rs.getInt("id");
String nickname = rs.getString("nickname");
System.out.println("id="+id+"\tnickname="+nickname);
}
rs.close();
state.close();
conn.close();
}
}
四,dao概述与工厂设计模式
1,工厂方法设计模式 ( 静态工厂方法模式 )
工厂方法模式一种创建对象的模式.
工厂方法模式基于"输入",应用在超类和多个子类之间的情况,这种模式将创建对象的责任转移到工厂类;
工厂设计模式的优点:
- 1. 面向接口编程,体现了面向对象的思想
- 2. 降低了耦合, 将创建对象的工作转移到了工厂类(连接不同版本数据库时,SQL语句不一致导致的代码重构)
2,DAO
DAO(Data Access Object)是一个数据访问接口,数据访问:顾名思义就是与数据库打交道。夹在业务 逻辑与数据库资源中间。
为了建立一个健壮的Java应用,应该将所有对数据源的访问操作抽象封装在一个公共API中。用程序设计的 语言来说,就是建立一个接口,接口中定义了此应用程序中将会用到的所有事务方法。在这个应用程序中, 当需要和数据源进行交互的时候则使用这个接口,并且编写一个单独的类来实现这个接口在逻辑上对应这个 特定的数据存储。
引入工厂方法后
DAO模式是标准的JavaEE设计模式之一.
开发人员使用这个模式把底层的数据访问操作和上层的商务逻辑分 开.一个典型的DAO实现有下列几个组件:
- 1. 一个DAO工厂类;
- 2. 一个DAO接口;
- 3. 至少一个实现DAO接口的具体类;
- 4. 数据传递对象(有些时候叫做Bean对象).
五,DAO工厂
1,代码示例
一个典型的DAO实现有下列几个组件:
- 1. 一个DAO工厂类;
- 2. 一个DAO接口;
- 3. 至少一个实现DAO接口的具体类;
- 4. 数据传递对象(有些时候叫做Bean对象).
依次设计代码如下:
1,一个DAO工厂类:UserDaoFactory
package com.java.demo3;
public class UserDaoFactory {
public static BaseUserDao get(){
return new MySqlUserDao();
}
}
2,一个DAO接口:BaseUserDao
package com.java.demo3;
import java.util.List;
public interface BaseUserDao {
/**
* 用于向数据库xzk_user表格中插入一行数据
* @param username 是要插入的账号
* @param password 是要插入的密码
* @return 结果, 增加成功返回true
*/
boolean insert(String username,String password);
/**
* 用于从数据库xzk_user表格中查询一行数据
* @param username 是要查询的条件1:账号
* @param password 是要查询的条件2:密码
* @return 结果, 查询成功返回true
*/
boolean findByPassword(String username,String password);
/**
* 用于从数据库xzk_user表格中查询一行数据
* @param username 是要查询的条件1:账号
* @param password 是要查询的条件2:密码
* @return 结果, 查询成功返回true
*/
boolean findByPassword2(String username,String password);
/**
* 查询所有用户信息
* @return 用户列表
*/
List<User> findAll();
}
3,至少一个实现DAO接口的具体类:MySqlUserDao
package com.java.demo3;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class MySqlUserDao implements BaseUserDao{
static{
try {
Class.forName("com.mysql.jdbc.Driver");// 编写一次即可,所以写在静态代码块中
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
@Override
public boolean insert(String username, String password) {
Connection conn = null;
Statement state = null;
try {
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8", "root", "123");
state = conn.createStatement();
//insert into xzk_user values('username','password') : 字符串的定义格式 字符串的表现格式
int row = state.executeUpdate("insert into xzk_user values('" + username + "','" + password + "')");
return row>0;
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
try {
state.close();
} catch (Exception e) {
e.printStackTrace();
}
try {
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return false;
}
@Override
public boolean findByPassword(String username, String password) {
Connection conn = null;
Statement state = null;
ResultSet rs = null;
try {
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8", "root", "123");
state = conn.createStatement();
//执行
rs = state.executeQuery("select * from xzk_user where username='"+username+"' and password='"+password+"'");
return rs.next();
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
try {
rs.close();
} catch (Exception throwables) {
throwables.printStackTrace();
}
try {
state.close();
} catch (Exception throwables) {
throwables.printStackTrace();
}
try {
conn.close();
} catch (Exception throwables) {
throwables.printStackTrace();
}
}
return false;
}
@Override
public List<User> findAll() {
List<User> data = new ArrayList<>();
Connection conn = null;
Statement state = null;
ResultSet rs = null;
try {
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8", "root", "123");
state = conn.createStatement();
rs = state.executeQuery("select * from xzk_user");
while(rs.next()){
String username = rs.getString("username");
String password = rs.getString("password");
data.add(new User(username,password));
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
try {
rs.close();
} catch (Exception e) {
e.printStackTrace();
}
try {
state.close();
} catch (Exception e) {
e.printStackTrace();
}
try {
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return data;
}
}
4,数据传递对象(有些时候叫做Bean对象):User
package com.java.demo3;
import java.util.Objects;
public class User {
private String username;
private String password;
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return Objects.equals(username, user.username) &&
Objects.equals(password, user.password);
}
@Override
public int hashCode() {
return Objects.hash(username, password);
}
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 User(String username, String password) {
this.username = username;
this.password = password;
}
public User() {
}
}
5,测试主函数:Main
package com.java.demo3;
import java.util.List;
import java.util.Scanner;
public class Main {
static Scanner input = new Scanner(System.in);
static BaseUserDao dao = UserDaoFactory.get();
public static void main(String[] args) {
System.out.println("欢迎来到某某软件");
System.out.println("请选择:");
System.out.println("1.注册\t\t2.登陆\t\t3.查看所有用户");
String menu = input.nextLine();
switch (menu){
case "1":
reg();
break;
case "2":
login();
break;
case "3":
showUsers();
break;
}
}
private static void showUsers() {
List<User> data = dao.findAll();
System.out.println("所有用户信息如下:");
System.out.println(data);
}
private static void login() {
System.out.println("请输入账号:");
String username = input.nextLine();
System.out.println("请输入密码:");
String password = input.nextLine();
boolean flag = dao.findByPassword(username, password);
System.out.println(flag?"恭喜你,登陆成功":"很遗憾,登陆失败");
}
private static void reg() {
System.out.println("请输入要注册的账号:");
String username = input.nextLine();
System.out.println("请输入要注册的密码:");
String password = input.nextLine();
boolean flag = dao.insert(username, password);
System.out.println(flag?"恭喜你,注册成功":"很遗憾,注册失败");
}
}
六,预编译处理
1,SQL注入问题 *
进行用户登录时, 输入不存在的帐号 和 如下的密码:
1' or '1'='1
结果显示登录成功. 因为用户输入的密码, 与我们的查询语句拼接后, 使得我们的查询语句产生了歧义:
原查询语句:
select * from xzk_user where username='' and password='密码'
拼接后:(可以看出and后面的条件,不论密码是多少,最终都会返回true)
select * from xzk_user where username='hahahaheiheihei' and password='1' or '1'='1'
2,解决SQL注入问题
我们可以将SQL语句与参数分离,将参数作为SQL的特殊部分进行预处理
2.1 PreparedStatement 预编译的SQL执行环境
内部实现原理:
1. 将未拼接参数的SQL语句, 作为SQL指令, 先传递给数据库 进行编译.
2. 再将参数传递给数据库, 此时传递的参数不会再作为指令执行, 只会被当作文本存在.
操作流程与Statement基本一致:
1. 如何得到一个PreparedStatement 对象?
PreparedStatement state = conn.prepareStatement("预编译的SQL语句");
2. 预编译的SQL语句如何编写 需要填充参数的位置, 使用?
代替即可! 例如:
select id from xzk_user where username=? and password=?
3. 参数如何填充
// setXXX中XXX指的是数据类型 // 参数1: index : SQL语句中?的索引值 , 从1开始 // 参数2: value : 填充的参数值. state.setXXX(int index,XXX value);
4. 如何执行填充完毕参数的SQL
boolean execute(); int executeUpdate(); ResultSet executeQuery();
2.2 代码展示
重写MySqlUserDao中的findByPassword方法;
对比部分以注释的形式呈现
@Override
public boolean findByPassword(String username, String password) {
Connection conn = null;
// 之前:Statement state = null;
PreparedStatement state = null;
ResultSet rs = null;
try {
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8", "root", "123");
// 之前:state = conn.createStatement();
// 参数: 预编译的SQL语句, 参数部分使用?替代.
state = conn.prepareStatement("select * from xzk_user where username=? and password=?");
// 向预编译的执行环境中, 加入参数的内容
state.setString(1,username);
state.setString(2,password);
// 之前:rs = state.executeQuery("select * from xzk_user where username='"+username+"' and password='"+password+"'");
// 执行
rs = state.executeQuery();
return rs.next();
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
try {
rs.close();
} catch (Exception throwables) {
throwables.printStackTrace();
}
try {
state.close();
} catch (Exception throwables) {
throwables.printStackTrace();
}
try {
conn.close();
} catch (Exception throwables) {
throwables.printStackTrace();
}
}
return false;
}
使用Statement
使用PreparedStatement
2.3 PreparedStatement与Statement谁的性能高?
看是什么数据库
- 在mysql中, preparedStatement原理是拼接SQL, 所以Statement性能高.
- 在Oracle中, preparedStatement原理是对SQL指令进行预处理, 再传递的参数不具备特殊含义.有更好 的SQL缓存策略,PreparedStatement高.
由于PreparedStatement可以防止SQL注入问题,所以推荐使用此方法
3,预编译与否的性能对比
七,批处理
将多条语句, 放到一起批量处理 .
批处理的原理: 将多条SQL语句, 转换为一个SQL指令. 显著的提高大量SQL语句执行时的数据库性能.
1,使用方法
1.1 Statement对象使用流程:
1. 得到Statement对象
Statement state = conn.createStatement();
2. 将一条SQL语句, 加入到批处理中.
state.addBatch(String sql);
3. 执行批处理
state.executeBatch();
4. 清空批处理
state.clearBatch();
1.2 PreparedStatement对象使用流程:
1. 得到PreparedStatement对象
PreparedStatement state = conn.prepareStatement("预编译的SQL");
2. 填充预编译的参数
state.setXXX(1,填充参数);
3. 将一条填充完毕参数的SQL, 加入到批处理中.
state.addBatch();
4. 执行批处理
state.executeBatch();
5. 清空批处理
state.clearBatch();
2,代码
package com.java.demo5;
import java.sql.*;
public class Main {
//statment
public static void insert1_1() throws SQLException {
for (int i=0;i<1000;i++) {
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8", "root", "123");
Statement state = conn.createStatement();
state.executeUpdate("insert into person values('admin','123"+i+"')");
state.close();
conn.close();
}
}
//statement 批处理
public static void insert1_2() throws SQLException {
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8", "root", "123");
Statement state = conn.createStatement();
for (int i=0;i<1000;i++) {
//向批处理中 加入一条SQL
state.addBatch("insert into person values('admin','123"+i+"')");
}
//执行批处理
state.executeBatch();
//清空批处理指令
state.clearBatch();
state.close();
conn.close();
}
//PreparedStatement
public static void insert2_1() throws SQLException {
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8", "root", "123");
PreparedStatement state = conn.prepareStatement("insert into person values(?,?)");
for (int i=0;i<10000;i++) {
state.setString(1,"admin");
state.setString(2,"123"+i);
state.executeUpdate();
}
state.close();
conn.close();
}
//PreparedStatement批处理
public static void insert2_2() throws SQLException {
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8", "root", "123");
PreparedStatement state = conn.prepareStatement("insert into person values(?,?)");
for (int i=0;i<10000;i++) {
state.setString(1,"admin");
state.setString(2,"123"+i);
state.addBatch();
}
//执行批处理
state.executeBatch();
//清空批处理指令
state.clearBatch();
state.close();
conn.close();
}
}
八,数据库连接池
1,连接池(DataSource)的使用 *
连接池用于缓存连接! 当我们需要使用连接时, 可以不用再创建连接 ! 可以直接从连接池中获取连接.
- 当连接池中存在空闲连接时, 会将空闲连接给到程序使用.
- 当连接池中不存在空闲连接时, 且连接池未满时 , 则创建连接提供给程序使用 ,并在程序使用完毕后, 缓存连接.
- 当连接池中不存在空闲连接时, 且连接池已满时 , 则排队等候空闲连接的出现.
注意:使用连接池中的连接对象操作数据库时, 操作完毕依然需要释放连接(调用close()).
连接池中的连接在设计时, 使用了动态代理设计模式+装饰者设计模式 . 我们调用它的close方法, 代理没有关闭这个连接, 而是将连接重新放入了池中.
2,Properties 作为配置文件
Properties类 是Java中的Map集合的实现类.
- .properties文件 用于通过文件描述一组键值对!
- .properties文件 ,可以快速的转换为Properties类的对象.
2.1 文件中内容的格式:
- 文件内容都是字符串 ,
- 键与值之间通过等号连接 ,
- 多个键值对之间换行分割.
例如:
url=xxx
user=xxx
password=xxx
2.2 如何将文件 转换为 集合:
1. 创建Properties对象
Properties ppt = new Properties();
2. 创建一个字节输入流 , 指向.properties文件
InputStream is = new FileInputStream("文件地址");
3. 将字节输入流, 传递给properties对象, 进行加载.
ppt.load(is);
3,常用连接池使用步骤
3.1 DBCP连接池的使用步骤 *
1. 引入相关的jar文件
- dbcp.jar
- poll.jar
2. 将配置文件引入
3. 将配置文件, 转换为Properties对象
Properties ppt = new Properties();
ppt.load(配置文件的输入流);
4. 通过连接池的工厂类(BasicDataSourceFactory)的创建连接池的方法(createDataSource())
DataSource ds = BasicDataSourceFactory.createDataSource(ppt);
5. 从连接池中 获取连接对象
Connection conn = ds.getConnection();
3.2 德鲁伊连接池的使用步骤 *
1. 引入相关的jar文件
- druid-1.0.9.jar
2. 将配置文件引入
3. 将配置文件, 转换为Properties对象
Properties ppt = new Properties();
ppt.load(配置文件的输入流);
4. 通过连接池的工厂类(DruidDataSourceFactory)的创建连接池的方法(createDataSource())
DataSource ds = DruidDataSourceFactory.createDataSource(ppt);
5. 从连接池中 获取连接对象
Connection conn = ds.getConnection();
3.3 代码演示——DBCP连接池
1,编写配置文件
dbcp.properties(因为编码问题出现乱码,只要关键地方没问题,其他影响不大)
#���ݿ����ӵ�ַ
url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8
#���ݿ��������ȫ��
driverClassName=com.mysql.jdbc.Driver
#���ݿ��ʺ�
username=root
#���ݿ�����
password=123
#��ʼ�����ӳ�ʱ,��������������
initialSize=5
#���ӳص������������
maxActive=20
#����ʱ�������������������
maxIdle=5
#����ʱ����������С��������
minIdle=5
#�ŶӵȺ�ij�ʱʱ��(����)
maxWait=3000
2,编写demo
package com.java.demo6;
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.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class Demo {
// DBCP
public static void main(String[] args) throws Exception {
//1. 引入jar文件
//2. 将配置文件 properties文件 放到src文件夹下
//3. 将properties文件 转换为Properties对象
Properties ppt = new Properties();
InputStream is = Demo.class.getClassLoader().getResourceAsStream("dbcp.properties");
ppt.load(is);
//4. 通过连接池的工厂类, 创建连接池
DataSource dataSource = BasicDataSourceFactory.createDataSource(ppt);
//5. 从池中获取一个连接
Connection conn = dataSource.getConnection();
Statement state = conn.createStatement();
state.execute("insert into person values('zhangsan','lisi')");
state.close();
conn.close();
}
}
3.3 代码演示——德鲁伊连接池(效果比其他连接池好)
1,编写配置文件
url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8
username=root
password=123
#��������������url�Զ�ʶ����һ�����ɲ��䣬���������druid�����url�Զ�ʶ����Ӧ��driverClassName
driverClassName=com.mysql.jdbc.Driver
#��ʼ��ʱ�����������ӵĸ�������ʼ����������ʾ����init���������ߵ�һ�� getConnectionʱ
initialSize=5
#������ӳ�����
maxActive=10
#��С���ӳ�����
minIdle=5
#��ȡ����ʱ���ȴ�ʱ�䣬��λ���롣
maxWait=3000
2,编写demo
4,连接池工具类
之前编写代码时,下面一行代码反复出现,为了避免重复的工作,引入了连接池工具类
4.1 Druid
public class DruidUtil{
private static DataSource data = null;
static {
InputStream is = DruidUtil.class.getClassLoader().getResourceAsStream("druid.properties");
Properties ppt = new Properties();
try {
ppt.load(is);
data = DruidDataSourceFactory.createDataSource(ppt);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 用于从DBCP连接池中 获取一个连接
* @return DBCP连接池中的一个连接对象.
*/
public static Connection getConnection() {
try {
return data.getConnection();
} catch (SQLException e) {
e.printStackTrace();
return null;
}
}
/**
* 用于释放连接 , 执行环境 , 结果集 等资源
* @param conn 要释放的连接资源
* @param state 要释放的执行环境资源
* @param result 要释放的结果集资源
*/
public static void close(Connection conn,Statement state,ResultSet result) {
if(result != null) {
try {
result.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(state != null) {
try {
state.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(conn != null) {
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Demo
package com.java.util;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
public class Demo {
public static void main(String[] args) {
try {
Connection conn = DruidUtil.getConnection();
Statement state = conn.createStatement();
state.execute("insert into person values('jinpingguo','123')");
state.close();
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
章节汇总在这里(づ ̄3 ̄)づ╭❤~@&再见萤火虫&【05-数据库】
对学习Java感兴趣的同学欢迎加入QQ学习交流群:1126298731
有问题欢迎提问,大家一起在学习Java的路上打怪升级!(o゜▽゜)o☆[BINGO!]