目录
一,JDBC简介
1,简介
2,发展历史
二,JDBC标准流程
1,使用步骤*
2,配置lib
3,代码实现
三,增删改查
1,JDBC中常用的类型和方法
2,代码演示
四,dao概述与工厂设计模式
1,工厂方法设计模式 ( 静态工厂方法模式 )
2,DAO
五,DAO工厂
1,代码示例
六,预编译处理
1,SQL注入问题 *
2,解决SQL注入问题
2.1 PreparedStatement 预编译的SQL执行环境
2.2 代码展示
2.3 PreparedStatement与Statement谁的性能高?
3,预编译与否的性能对比
七,批处理
1,使用方法
1.1 Statement对象使用流程:
1.2 PreparedStatement对象使用流程:
2,代码
八,数据库连接池
1,连接池(DataSource)的使用 *
2,Properties 作为配置文件
2.1 文件中内容的格式:
2.2 如何将文件 转换为 集合:
3,常用连接池使用步骤
3.1 DBCP连接池的使用步骤 *
3.2 德鲁伊连接池的使用步骤 *
3.3 代码演示——DBCP连接池
3.3 代码演示——德鲁伊连接池(效果比其他连接池好)
4,连接池工具类
4.1 Druid
一,JDBC简介
1,简介
Java DataBase Connectivity Java数据库连接
我们学习的技术是JDBC 不是 MYSQLJDBC 也不是 ORACLE JDBC
JDBC是一套标准,是Java与各大数据库厂商共同定制的一套接口. 这套接口由各大数据库厂商进行了实现.
2,发展历史
Java DataBase Connectivity Java数据库连接
我们学习的技术是JDBC 不是 MYSQLJDBC 也不是 ORACLE JDBC
JDBC是一套标准,是Java与各大数据库厂商共同定制的一套接口. 这套接口由各大数据库厂商进行了实现.
自从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文件.
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();
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对象).
一个典型的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!]