JDBC简介
JDBC全称为:Java DataBase Connectivity (Java数据库连接)
SUN公司为了简化、统一对数据库的操作,定义了一套Java操作数据库的规范,称之为JDBC
Sun公司为了简化数据库开发,定义了一套JDBC接口,这套接口由数据库厂商去实现,这样,开发人员只需要学习JDBC接口, 并通过JDBC加载具体的驱动,就可以操作数据库。
组成JDBC的2个包(java.sql 、javax.sql)
(1)java.sql
类:DriverManager
接口:Connection Statement ResultSet PreparedStatement
CallableStatement(它用于调用存储过程)
(2)javax.sql
接口 DataSource
开发JDBC应用需要以上2个包的支持外
还需要导入相应JDBC的数据库驱动(即数据库驱动 mysql-connector-java-x.x.x-bin.jar)
什么是驱动?
两个设备要进行通信,满足一定通信数据格式,数据格式由设备提供商规定,设备提供商为设备提供驱动软件,通过软件可以与该设备进行通信。
第一个JDBC程序
创建user表
create table user(
id int primary key auto_increment,
username varchar(20) unique not null,
password varchar(20) not null,
email varchar(40) not null
);
INSERT INTO USER VALUES(NULL,'tom','123','tom@163.com');
INSERT INTO USER VALUES(NULL,'fox','123','fox@163.com');
编程从user表中读取数据,并打印在命令行窗口中。
(一)搭建实验环境
1、在MySQL中创建一个库,并创建user表和插入表的数据。
2、新建一个Java工程,并导入数据驱动
(二)编写程序,在程序中加载数据库驱动(称为注册驱动)
DriverManager.registerDriver(Driver driver);
(三)建立连接(Connection)
Connection conn = DriverManager.getConnection(url, user, pass);
(四)创建用于向数据库发送SQL的Statement对象,并发送SQL
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery(sql);
(五)从代表结果集的ResultSet中取出数据,打印到命令行窗口
(六)断开与数据库的连接,并释放相关资源。
新建项目工程,创建cn.itcast.jdbc包 创建JdbcDemo1.java
package cn.itcast.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import com.mysql.jdbc.Driver;
public class JdbcDemo1 {
public static void main(String[] args) throws SQLException {
// 1.注册驱动
DriverManager.registerDriver(new Driver());
// 2.获取连接对象
Connection con = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/mydb1", "root", "root");
// 3.通过连接对象获取操作sql语句Statement
Statement st = con.createStatement();
// 4.操作sql语句
String sql = "select * from user";
// 操作sql语句(select语句),会得到一个ResultSet结果集
ResultSet rs = st.executeQuery(sql);
// 5.遍历结果集
// boolean flag = rs.next(); // 向下移动,返回值为true,代表有下一条记录.
// int id = rs.getInt("id");
// String username=rs.getString("username");
// System.out.println(id);
// System.out.println(username);
while(rs.next()){
int id=rs.getInt("id");
String username=rs.getString("username");
String password=rs.getString("password");
String email=rs.getString("email");
System.out.println(id+" "+username+" "+password+" "+email);
}
//6.释放资源
rs.close();
st.close();
con.close();
}
}
JDBC 编程步骤以及JDBC访问数据库的流程
JDBC编程步骤
简单的说,JDBC的意义在于在Java程序中执行SQL语句。
驱动程序的意义在于提供统一的接口并隐藏实现细节。驱动程序定义了数据库能做什么,比如上面所说的几个步骤,数据库的制造商(例如Oracle)提供符合这些接口的实现(怎么做),我们在编写Java程序中只需要调用驱动程序中的接口就可以操作数据库,完成这四个步骤。同计算机硬件的驱动程序类似,JDBC的驱动实现了 "做什么"和"怎么做"的分离。
与使用SQLPlus访问数据库类似,在操作数据库之前,需要先跟数据库建立连接。建立连接后,可以通过获得的连接对象来调用SQL语句。
操作数据基本的含义是执行SQL语句,包括DML,DDL,DCL 均可,还可以调用数据库中已有的存储过程,释放资源。
使用JDBC编程时,与数据库建立的连接以及通过这个连接创建的语句对象,都有可能需要调用响应的close方法来释放底层建立的网络连接,或者打开文件。
JDBC访问数据库的流程
- 通过DriverManager加载驱动程序driver;
- 通过DriverManager类获得表示数据库连接的Connection类对象;
- 通过Connection对象绑定要执行的语句,生成Statement类对象;
- 执行SQL语句,接收执行结果集ResultSet;
- 可选的对结果集ResultSet类对象的处理;
- 必要的关闭ResultSet、Statement和Connection
程序详解—DriverManager
JDBC程序中的DriverManager用于加载驱动,并创建与数据库的链接,这个API的常用方法:
DriverManager.registerDriver(new Driver);
DriverManager.getConnection(url, user, password);
它是java.sql包下的一个驱动管理的工具类,可以理解成是一个容器(Vector),可以装入很多数据库驱动
它的registDriver方法分析
public static synchronized void registerDriver(java.sql.Driver driver)
参数:java.sql.Driver
我们传递的是 com.mysql.jdbc.Driver;
在com.mysql.jdbc.Driver类中有一段静态代码块:
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
它的registDriver方法分析
public static synchronized void registerDriver(java.sql.Driver driver)
参数:java.sql.Driver
我们传递的是 com.mysql.jdbc.Driver;
在com.mysql.jdbc.Driver类中有一段静态代码块:
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
注意:在实际开发中并不推荐采用registerDriver方法注册驱动。原因有二:
(一)有上述的的源代码可知,如果采用此种方式,会导致驱动程序注册两次,也就是说在内存中会有两个Driver对象
(二)程序依赖MySQL的API,脱离MySQL的jar包,程序将无法编译,将来程序切换底层数据库将会非常麻烦。
推荐方式:利用反射Class.forName("com.mysql.jdbc.Driver");
采用此种方式不会导致驱动对象在内存中重复出现,并且采用此种方式,程序仅仅需要一个字符串,不需要依赖具体的驱动,使程序的灵活性更高。
同样,在开发中也不建议采用具体的驱动类型指向getConnection方法返回connection对象。
在cn.itcast.jdbc包下新建JdbcDemo2.java 如下:
package cn.itcast.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
//解决关于加载驱动问题
public class JdbcDemo2 {
public static void main(String[] args) throws SQLException,
ClassNotFoundException {
// 1.注册驱动
// DriverManager.registerDriver(new Driver()); //加载了两个驱动
Class.forName("com.mysql.jdbc.Driver"); // 加载mysql驱动
Class.forName("oracle.jdbc.driver.OracleDriver");// 加载oracle驱动
// String url="jdbc:mysql://localhost:3306/day17";
String url = "jdbc:mysql:///mydb1";
// 2.获取连接对象
Connection con = DriverManager.getConnection(url, "root", "root");
// 3.通过连接对象获取操作sql语句Statement
Statement st = con.createStatement();
// 4.操作sql语句
String sql = "select * from user";
// 操作sql语句(select语句),会得到一个ResultSet结果集
ResultSet rs = st.executeQuery(sql);
// 5.遍历结果集
// boolean flag = rs.next(); // 向下移动,返回值为true,代表有下一条记录.
// int id = rs.getInt("id");
// String username=rs.getString("username");
// System.out.println(id);
// System.out.println(username);
while (rs.next()) {
int id = rs.getInt("id");
String username = rs.getString("username");
String password = rs.getString("password");
String email = rs.getString("email");
System.out.println(id + " " + username + " " + password + " "
+ email);
}
// 6.释放资源
rs.close();
st.close();
con.close();
}
}
数据库URL
URL用于标识数据库位置,程序员通过URL地址告诉JDBC程序连接哪个数据库,URL的写法为:
jdbc:mysql://localhost:3306/test?key=value
- jdbc: 协议
- mysql:子协议
- localhost:3306:主机:端口号
- test:要连接的数据库名称
常用数据库URL地址的写法:
Oracle写法:jdbc:oracle:thin:@localhost:1521:sid
MySQL写法:jdbc:mysql://localhost:3306/sid
MySQL的url地址的简写方式:jdbc:mysql:///sid
简写的前提是:主机是localhost 端口是3306
常用属性:useUnicode=true&characterEncoding=UTF-8
程序详解—Connection
JDBC程序中的Connection,它用于代表数据库的连接,Connection是数据库编程中最重要的一个对象,客户端与数据库所有交互都是通过connection对象完成的,这个对象常用的方法:
- createStatement():创建向数据库发送SQL的Statement对象。
- prepareStatement():创建向数据库发送预编译SQL的PrepareStatement对象。
- prepareCall(sql):创建执行存储过程的callableStatement对象——执行存储过程
- setAutoCommit(boolean autoCommit):设置事务是否自动提交
- commit():在链接上提交事务——与事务相关
- rollback():在此链接上回滚事务
java.sql.Connection 作用:
Connection作用:
1.可以通过Connection获取操作sql的Statement对象。
Statement createStatement() throws SQLException
示例:
Statement st=con.createStatement();
了解:
1).可以获取执行预处理的PreparedStatement对象.
PreparedStatement prepareStatement(String sql) throws SQLException
2).可以获取执行存储过程的 CallableStatementStatement createStatement() throws SQLException
示例:
Statement st=con.createStatement();
了解:
1).可以获取执行预处理的PreparedStatement对象.
PreparedStatement prepareStatement(String sql) throws SQLException
CallableStatement prepareCall(String sql) throws SQLException
2.操作事务
setAutoCommit(boolean flag);开启事务
rollback();事务回滚
commit();事务提交
setAutoCommit(boolean flag);开启事务
rollback();事务回滚
commit();事务提交
程序详解—Statement (一次操作)
JDBC程序中的Statement对象用于向数据库发送SQL语句,Statement对象常用方法:
- ResultSet executeQuery(String sql):用于向数据库发送查询语句(DQL)。
- int executeUpdate(String sql):用于向;数据库发送insert、update或delete语句(DML)。利用返回值判断非0来确定sql语句是否执行成功
- execute(String sql):用于向数据库发送任意的sql语句
- addBatch(String sql):把多条SQL语句放到一个批处理中。
- executeBatch():向数据库发送一批SQL语句执行。
- clearBatch():清空批处理
程序详解—ResultSet
java.sql.ResultSet 它是用于封装select语句执行后查询的结果。
常用API:
(1)next()方法
public boolean next();
用于判断是否有下一条记录。如果有返回true,并且让游标向下移动一行。
如果没有返回false.
(2)可以通过ResultSet提供的getXxx()方法来获取当前游标指向的这条记录中的列数据。
常用:
getInt()、getString()、getDate()、getDouble()
参数有两种
1.getInt(int columnIndex);
2.getInt(String columnName);
如果列的类型不知道,可以通过下面的方法来操作
getObject(int columnIndex);
getObject(String columnName);
getInt()、getString()、getDate()、getDouble()
参数有两种
1.getInt(int columnIndex);
2.getInt(String columnName);
如果列的类型不知道,可以通过下面的方法来操作
getObject(int columnIndex);
getObject(String columnName);
常用数据类型转换表:
程序详解—释放资源
- Jdbc程序运行完后,切记要释放程序在运行过程中,创建的那些与数据库进行交互的对象,这些对象通常是ResultSet, Statement和Connection对象。
- 特别是Connection对象,它是非常稀有的资源,用完后必须马上释放,如果Connection不能及时、正确的关闭,极易导致系统宕机。Connection的使用原则是尽量晚创建,尽量早的释放。
- 为确保资源释放代码能运行,资源释放代码也一定要放在finally语句中。
package cn.itcast.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
//演示executeUpdate方法
public class JdbcDemo3 {
public static void main(String[] args) throws SQLException,
ClassNotFoundException {
// 1.注册驱动
Class.forName("com.mysql.jdbc.Driver"); // 加载mysql驱动
String url = "jdbc:mysql:///mydb1";
// 2.获取连接对象
Connection con = DriverManager.getConnection(url, "root", "root");
// 3.通过连接对象获取操作sql语句Statement
Statement st = con.createStatement();
// 4.执行update语句
int row = st.executeUpdate("update user set password='135' where id=1");
System.out.println(row);
// 6.释放资源
st.close();
con.close();
}
}
package cn.itcast.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
//ResultSet介绍
public class JdbcDemo4 {
public static void main(String[] args) throws SQLException,
ClassNotFoundException {
// 1.注册驱动
Class.forName("com.mysql.jdbc.Driver"); // 加载mysql驱动
String url = "jdbc:mysql:///mydb1";
// 2.获取连接对象
Connection con = DriverManager.getConnection(url, "root", "root");
// 3.通过连接对象获取操作sql语句Statement
Statement st = con.createStatement();
// 4.操作sql语句
String sql = "select * from user";
ResultSet rs = st.executeQuery(sql);
// 5.遍历结果集
while (rs.next()) {
String id = rs.getString("id");
String username = rs.getString("username");
String password = rs.getString("password");
String email = rs.getString("email");
System.out.println(id + " " + username + " " + password + " "
+ email);
}
// 6.释放资源
rs.close();
st.close();
con.close();
}
}
由代码可以看出 其实任何类型都可以由getString()方法进行接收
package cn.itcast.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
//对异常进行try-catch
public class JdbcDemo5 {
public static void main(String[] args) {
Connection con = null;
Statement st = null;
ResultSet rs = null;
try {
// 1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2.获取连接
con = DriverManager.getConnection("jdbc:mysql:///mydb1", "root",
"root");
// 3.获取操作sql语句对象Statement
st = con.createStatement();
// 4.执行sql
rs = st.executeQuery("select * from user");
// 5.遍历结果集
while (rs.next()) {
int id = rs.getInt("id");
String username = rs.getString("username");
String password = rs.getString("password");
String email = rs.getString("email");
System.out.println(id + " " + username + " " + password
+ " " + email);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 6.释放资源
try {
if (rs != null) {
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (st != null)
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (con != null)
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
使用JDBC对数据库进行CRUD
- Jdbc中的statement对象用于向数据库发送SQL语句,想完成对数据库的增删改查,只需要通过这个对象向数据库发送增删改查语句即可。
- Statement对象的executeUpdate方法,用于向数据库发送增、删、改的sql语句,executeUpdate执行完后,将会返回一个整数(即增删改语句导致了数据库几行数据发生了变化)。
- Statement.executeQuery方法用于向数据库发送查询语句,executeQuery方法返回代表查询结果的ResultSet对象。
练习:编写程序对User表进行增删改查操作。
练习:编写工具类简化CRUD操作。(异常暂不处理)
练习:编写工具类简化CRUD操作。(异常暂不处理)
关于JdbcUtils抽取(只抽取到Connection)
package cn.itcast.utils;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class JdbcUtils {
public static Connection getConnection() throws ClassNotFoundException,
SQLException {
Class.forName("com.mysql.jdbc.Driver");
// 2.获取连接
Connection con = DriverManager.getConnection("jdbc:mysql:///day17",
"root", "abc");
return con;
}
}
关于上述的抽取JdbcUtils的缺点: 1. 它只能针对于MySQL数据库
2. 每一次调用,都会注册一次驱动
对于上述问题,对JdbcUtils进行修改:
将关于连接数据库的信息定义到配置文件中。
读取配置文件进行加载。
在src下新建jdbc.properties文件,编辑如下:
在src下新建cn.itcast.utils包,在包内重新封装JdbcUtils.java工具类
package cn.itcast.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;
//使用配置文件
public class JdbcUtils {
private static final String DRIVERCLASS;
private static final String URL;
private static final String USERNAME;
private static final String PASSWORD;
static {
DRIVERCLASS = ResourceBundle.getBundle("jdbc").getString("driverClass");
URL = ResourceBundle.getBundle("jdbc").getString("url");
USERNAME = ResourceBundle.getBundle("jdbc").getString("username");
PASSWORD = ResourceBundle.getBundle("jdbc").getString("password");
}
static {
try {
// 将加载驱动操作,放置在静态代码块中.这样就保证了只加载一次.
Class.forName(DRIVERCLASS);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection getConnection() throws SQLException {
// 2.获取连接
Connection con = DriverManager.getConnection(URL, USERNAME, PASSWORD);
return con;
}
//关闭操作
public static void closeConnection(Connection con) throws SQLException{
if(con!=null){
con.close();
}
}
public static void closeStatement(Statement st) throws SQLException{
if(st!=null){
st.close();
}
}
public static void closeResultSet(ResultSet rs) throws SQLException{
if(rs!=null){
rs.close();
}
}
}
测试CURD操作,并测试工具类、package cn.itcast.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.junit.Test;
import cn.itcast.utils.JdbcUtils;
import cn.itcast.utils.JdbcUtils1;
//jdbc的crud操作
public class JdbcDemo6 {
@Test
public void findByIdTest() {
// 1.定义sql
String sql = "select * from user where id=1";
Connection con = null;
Statement st = null;
ResultSet rs = null;
try {
// 1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2.获取连接
con = DriverManager.getConnection("jdbc:mysql:///mydb1", "root",
"root");
// 3.获取操作sql语句对象Statement
st = con.createStatement();
// 4.执行sql
rs = st.executeQuery(sql);
// 5.遍历结果集
while (rs.next()) {
int id = rs.getInt("id");
String username = rs.getString("username");
String password = rs.getString("password");
String email = rs.getString("email");
System.out.println(id + " " + username + " " + password
+ " " + email);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 6.释放资源
try {
if (rs != null) {
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (st != null)
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (con != null)
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
// 添加操作
@Test
public void addTest() {
// 定义sql
String sql = "insert into user values(null,'张三','123','zs@163.com')";
Connection con = null;
Statement st = null;
ResultSet rs = null;
try {
// 1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2.获取连接
con = DriverManager.getConnection("jdbc:mysql:///day17", "root",
"abc");
// 3.获取操作sql语句对象Statement
st = con.createStatement();
// 4.执行sql
int row = st.executeUpdate(sql);
if (row != 0) {
System.out.println("添加成功");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 6.释放资源
try {
if (rs != null) {
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (st != null)
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (con != null)
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
// update操作
@Test
public void updateTest() {
// 将id=3的人的password修改为456
String password = "456";
String sql = "update user set password='" + password + "' where id=3";
// 1.得到Connection
Connection con = null;
Statement st = null;
try {
con = JdbcUtils1.getConnection();
// 3.获取操作sql语句对象Statement
st = con.createStatement();
// 4.执行sql
int row = st.executeUpdate(sql);
if (row != 0) {
System.out.println("修改成功");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 关闭资源
try {
if (st != null)
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (con != null)
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
// delete测试
@Test
public void deleteTest() {
// 将id=3的人删除
String sql = "delete from user where id=2";
// 1.得到Connection
Connection con = null;
Statement st = null;
try {
con = JdbcUtils.getConnection();
// 3.获取操作sql语句对象Statement
st = con.createStatement();
// 4.执行sql
int row = st.executeUpdate(sql);
if (row != 0) {
System.out.println("删除成功");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 关闭资源
try {
JdbcUtils.closeStatement(st);
JdbcUtils.closeConnection(con);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
滚动结果集
默认得到的ResultSet它只能向下遍历(next()),对于ResultSet它可以设置成是滚动的,可以向上遍历,或者直接定位到一个指定的物理行号.
问题:怎样得到一个滚动结果集?
Statement st=con.createStatement();
ResultSet rs=st.executeQuery(sql);
这是一个默认结果集:只能向下执行,并且只能迭代一次。
Statement stmt = con.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATABLE);
ResultSet rs = stmt.executeQuery(sql);
这个就可以创建滚动结果集.
简单说,就是在创建Statement对象时,不使用createStatement();
而使用带参数的createStatement(int,int)
问题:怎样得到一个滚动结果集?
Statement st=con.createStatement();
ResultSet rs=st.executeQuery(sql);
这是一个默认结果集:只能向下执行,并且只能迭代一次。
Statement stmt = con.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATABLE);
ResultSet rs = stmt.executeQuery(sql);
这个就可以创建滚动结果集.
简单说,就是在创建Statement对象时,不使用createStatement();
而使用带参数的createStatement(int,int)
Statement createStatement(int resultSetType,int resultSetConcurrency) throws SQLException
resultSetType - 结果集类型,它是 ResultSet.TYPE_FORWARD_ONLY、ResultSet.TYPE_SCROLL_INSENSITIVE 或 ResultSet.TYPE_SCROLL_SENSITIVE 之一
resultSetConcurrency - 并发类型;它是 ResultSet.CONCUR_READ_ONLY 或 ResultSet.CONCUR_UPDATABLE 之一
第一个参数值
ResultSet.TYPE_FORWARD_ONLY 该常量指示光标只能向前移动的 ResultSet 对象的类型。
ResultSet.TYPE_SCROLL_INSENSITIVE 该常量指示可滚动但通常不受 ResultSet 底层数据更改影响的 ResultSet 对象的类型。
ResultSet.TYPE_SCROLL_SENSITIVE 该常量指示可滚动并且通常受 ResultSet 底层数据更改影响的 ResultSet 对象的类型。
第二个参数值
ResultSet.CONCUR_READ_ONLY 该常量指示不可以更新的 ResultSet 对象的并发模式。
ResultSet.CONCUR_UPDATABLE 该常量指示可以更新的 ResultSet 对象的并发模式。
以上五个值,可以有三种搭配方式
ResultSet.TYPE_FORWARD_ONLY ResultSet.CONCUR_READ_ONLY 默认
ResultSet.TYPE_SCROLL_INSENSITIVE ResultSet.CONCUR_READ_ONLY
ResultSet.TYPE_SCROLL_SENSITIVE ResultSet.CONCUR_UPDATABLE
常用API
next():移动到下一行
previous():移动到前一行
absolute(int row):移动到指定行
beforeFirst():移动resultSet的最前面
afterLast() :移动到resultSet的最后面
updateRow() :更新行数据
resultSetType - 结果集类型,它是 ResultSet.TYPE_FORWARD_ONLY、ResultSet.TYPE_SCROLL_INSENSITIVE 或 ResultSet.TYPE_SCROLL_SENSITIVE 之一
resultSetConcurrency - 并发类型;它是 ResultSet.CONCUR_READ_ONLY 或 ResultSet.CONCUR_UPDATABLE 之一
第一个参数值
ResultSet.TYPE_FORWARD_ONLY 该常量指示光标只能向前移动的 ResultSet 对象的类型。
ResultSet.TYPE_SCROLL_INSENSITIVE 该常量指示可滚动但通常不受 ResultSet 底层数据更改影响的 ResultSet 对象的类型。
ResultSet.TYPE_SCROLL_SENSITIVE 该常量指示可滚动并且通常受 ResultSet 底层数据更改影响的 ResultSet 对象的类型。
第二个参数值
ResultSet.CONCUR_READ_ONLY 该常量指示不可以更新的 ResultSet 对象的并发模式。
ResultSet.CONCUR_UPDATABLE 该常量指示可以更新的 ResultSet 对象的并发模式。
以上五个值,可以有三种搭配方式
ResultSet.TYPE_FORWARD_ONLY ResultSet.CONCUR_READ_ONLY 默认
ResultSet.TYPE_SCROLL_INSENSITIVE ResultSet.CONCUR_READ_ONLY
ResultSet.TYPE_SCROLL_SENSITIVE ResultSet.CONCUR_UPDATABLE
常用API
next():移动到下一行
previous():移动到前一行
absolute(int row):移动到指定行
beforeFirst():移动resultSet的最前面
afterLast() :移动到resultSet的最后面
updateRow() :更新行数据
package cn.itcast.jdbc;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import cn.itcast.utils.JdbcUtils;
//滚动结果集
public class JdbcDemo7 {
public static void main(String[] args) throws SQLException {
// 1.得到一个Connection
Connection con = JdbcUtils.getConnection();
// 2.得到一个执行sql语句Statement
Statement st = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_UPDATABLE);
// 3.执行sql,得到结果集
ResultSet rs = st.executeQuery("select * from user");
// 4.定位
rs.absolute(3);
// System.out.println(rs.getInt("id") + " " +
// rs.getString("username"));
// rs.afterLast();
//
// while (rs.previous()) {
// System.out.println(rs.getInt("id") + " "
// + rs.getString("username"));
// }
rs.updateString("password", "456");
rs.updateRow();
// 5.关闭
rs.close();
st.close();
con.close();
}
}
JavaEE模式—DAO模式
- 封装对于数据源的操作
- 数据源可能是文件、数据库等任意存储方式
- 负责管理与数据库的连接
- 负责数据的存取(CURD)
DAO模式(Data Access Object 数据访问对象):在持久层通过DAO将数据源操作完全封装起来,业务层通过操作Java对象,完成对数据源操作
业务层无需知道数据源底层实现 ,通过java对象操作数据源
DAO模式结构 :
1、数据源(MySQL数据库)
2、Business Object 业务层代码,调用DAO完成 对数据源操作
3、DataAccessObject 数据访问对象,持久层DAO程序,封装对数据源增删改查,提供方法参数都是Java对象
4、TransferObject 传输对象(值对象) 业务层通过向数据层传递 TO对象,完成对数据源的增删改查
业务层无需知道数据源底层实现 ,通过java对象操作数据源
DAO模式结构 :
1、数据源(MySQL数据库)
2、Business Object 业务层代码,调用DAO完成 对数据源操作
3、DataAccessObject 数据访问对象,持久层DAO程序,封装对数据源增删改查,提供方法参数都是Java对象
4、TransferObject 传输对象(值对象) 业务层通过向数据层传递 TO对象,完成对数据源的增删改查
使用dao模式完成登录操作
1.web层
login.jsp LoginServlet User
2.service层
UserService
3.dao层
UserDao
sql注入
由于没有对用户输入进行充分检查,而SQL又是拼接而成,在用户输入参数时,在参数中添加一些SQL 关键字,达到改变SQL运行结果的目的,也可以完成恶意攻击。
示例:
在输入用户名时 tom' or '1'='1
这时就不会验证密码了。
解决方案:
PreparedStatement(重点)
它是一个预处理的Statement,它是java.sql.Statement接口的一个子接口。
总结PreparedStatement使用:
1.在sql语句中,使用"?"占位
String sql="select * from user where username=? and password=?";
2.得到PreparedStatement对象
PreparedStatement pst=con.prepareStatement(String sql);
3.对占位符赋值
pst.setXxx(int index,Xxx obj);
例如:
setInt()
setString();
参数index,代表的是"?"的序号.注意:从1开始。
4.执行sql
DML: pst.executeUpdate();
DQL: pst.executeQuery();
注意:这两方法无参数
关于PreparedStatement优点:
1.解决sql注入(具有预处理功能)
2.不需要在拼sql语句。
1.web层
login.jsp LoginServlet User
2.service层
UserService
3.dao层
UserDao
sql注入
由于没有对用户输入进行充分检查,而SQL又是拼接而成,在用户输入参数时,在参数中添加一些SQL 关键字,达到改变SQL运行结果的目的,也可以完成恶意攻击。
示例:
在输入用户名时 tom' or '1'='1
这时就不会验证密码了。
解决方案:
PreparedStatement(重点)
它是一个预处理的Statement,它是java.sql.Statement接口的一个子接口。
总结PreparedStatement使用:
1.在sql语句中,使用"?"占位
String sql="select * from user where username=? and password=?";
2.得到PreparedStatement对象
PreparedStatement pst=con.prepareStatement(String sql);
3.对占位符赋值
pst.setXxx(int index,Xxx obj);
例如:
setInt()
setString();
参数index,代表的是"?"的序号.注意:从1开始。
4.执行sql
DML: pst.executeUpdate();
DQL: pst.executeQuery();
注意:这两方法无参数
关于PreparedStatement优点:
1.解决sql注入(具有预处理功能)
2.不需要在拼sql语句。
DAO模式简单示例
项目结构如下:
jdbc.properties
driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql:///mydb1
username=root
password=root
#driverClass=oracle.jdbc.driver.OracleDriver
#url=jdbc:oracle:thin:@localhost:1521:XE
#username=system
#password=system
UserDao.javapackage cn.itcast.dao;
import cn.itcast.domain.User;
public interface UserDao {
public User findUser(User user) throws Exception;
}
UserDaoImpl.javapackage cn.itcast.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import cn.itcast.domain.User;
import cn.itcast.exception.LoginException;
import cn.itcast.utils.JdbcUtils;
public class UserDaoImpl implements UserDao{
// 查找用户---使用Statement完成登录操作,存在风险(sql注入)
public User _findUser(User user) throws SQLException {
// 1.sql语句
String sql = "select * from user where username='" + user.getUsername()
+ "' and password='" + user.getPassword() + "'";
// 2.执行sql
Connection con = null;
Statement st = null;
ResultSet rs = null;
try {
con = JdbcUtils.getConnection();
st = con.createStatement();
rs = st.executeQuery(sql);
if (rs.next()) { // 如果可以next,代表查找到了这个用户的信息,就将结果集中的信息封装到User对象中.
User u = new User();
u.setId(rs.getInt("id"));
u.setUsername(rs.getString("username"));
u.setPassword(rs.getString("password"));
u.setEmail(rs.getString("email"));
return u;
}
} finally {
try {
JdbcUtils.closeResultSet(rs);
JdbcUtils.closeStatement(st);
JdbcUtils.closeConnection(con);
} catch (SQLException e) {
e.printStackTrace();
}
}
return null;
}
// 使用PreparedStatement来完成操作,它可以解决sql注入.
public User findUser(User user) throws SQLException {
// 1.sql语句
String sql = "select * from user where username=? and password=?";
// 2.执行sql
Connection con = null;
PreparedStatement pst = null;
ResultSet rs = null;
try {
con = JdbcUtils.getConnection();
pst = con.prepareStatement(sql);
pst.setString(1, user.getUsername());
pst.setString(2, user.getPassword());
rs = pst.executeQuery();// 无参数
if (rs.next()) { // 如果可以next,代表查找到了这个用户的信息,就将结果集中的信息封装到User对象中.
User u = new User();
u.setId(rs.getInt("id"));
u.setUsername(rs.getString("username"));
u.setPassword(rs.getString("password"));
u.setEmail(rs.getString("email"));
return u;
}
}finally {
try {
JdbcUtils.closeResultSet(rs);
JdbcUtils.closeStatement(pst);
JdbcUtils.closeConnection(con);
} catch (SQLException e) {
e.printStackTrace();
}
}
return null;
}
}
User.javapackage cn.itcast.domain;
public class User {
private int id;
private String username;
private String password;
private String email;
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 getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
LoginException.javapackage cn.itcast.exception;
public class LoginException extends Exception {
public LoginException() {
super();
}
public LoginException(String message, Throwable cause) {
super(message, cause);
}
public LoginException(String message) {
super(message);
}
public LoginException(Throwable cause) {
super(cause);
}
}
UserService.javapackage cn.itcast.service;
import java.sql.SQLException;
import cn.itcast.dao.UserDaoImpl;
import cn.itcast.domain.User;
import cn.itcast.exception.LoginException;
public class UserService {
// service层的登录方法
public User login(User user) throws LoginException {
User existUser = null;
try {
existUser = new UserDaoImpl().findUser(user);
} catch (SQLException e) {
e.printStackTrace();
throw new LoginException("登录失败");
}
return existUser;
}
}
JdbcUtils.javapackage cn.itcast.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;
//使用配置文件
public class JdbcUtils {
private static final String DRIVERCLASS;
private static final String URL;
private static final String USERNAME;
private static final String PASSWORD;
static {
DRIVERCLASS = ResourceBundle.getBundle("jdbc").getString("driverClass");
URL = ResourceBundle.getBundle("jdbc").getString("url");
USERNAME = ResourceBundle.getBundle("jdbc").getString("username");
PASSWORD = ResourceBundle.getBundle("jdbc").getString("password");
}
static {
try {
// 将加载驱动操作,放置在静态代码块中.这样就保证了只加载一次.
Class.forName(DRIVERCLASS);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection getConnection() throws SQLException {
// 2.获取连接
Connection con = DriverManager.getConnection(URL, USERNAME, PASSWORD);
return con;
}
//关闭操作
public static void closeConnection(Connection con) throws SQLException{
if(con!=null){
con.close();
}
}
public static void closeStatement(Statement st) throws SQLException{
if(st!=null){
st.close();
}
}
public static void closeResultSet(ResultSet rs) throws SQLException{
if(rs!=null){
rs.close();
}
}
}
LoginServlet.javapackage cn.itcast.web.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import cn.itcast.domain.User;
import cn.itcast.exception.LoginException;
import cn.itcast.service.UserService;
public class LoginServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 1.得到用户名与密码
String username = request.getParameter("username");
String password = request.getParameter("password");
// 2.封装属性到javaBean
User user = new User();
user.setUsername(username);
user.setPassword(password);
// 3.调用service中登录方法
UserService service = new UserService();
User existUser =
null;
try {
existUser=service.login(user);
if (existUser == null) { // 代表用户名或密码错误,存储错误信息在request域,请求转发到login.jsp
request.setAttribute("login.message", "用户名或密码错误");
request.getRequestDispatcher("/login.jsp").forward(request,
response);
return;
} else {
request.getSession().setAttribute("user", existUser);
response.sendRedirect(request.getContextPath() + "/success.jsp");
return;
}
} catch (LoginException e) {
request.setAttribute("login.message", e.getMessage());
request.getRequestDispatcher("/login.jsp").forward(request,
response);
return;
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
login.jsp<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'index.jsp' starting page</title>
</head>
<body>
${requestScope["login.message"]}<br>
<form action="${pageContext.request.contextPath}/login" method="post">
username:<input type="text" name="username"><br>
password:<input type="password" name="password"><br>
<input type="submit" value="登录">
</form>
</body>
</html>
success.jsp<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'index.jsp' starting page</title>
</head>
<body>登录成功:${user.username}
</body>
</html>
PreparedStatement
- PreparedStatement是Statement的子接口,它的实例对象可以通过调用Connection.preparedStatement(sql)方法获得,相对于Statement对象而言:
- PreperedStatement可以避免SQL注入的问题。
- Statement会使数据库频繁编译SQL,可能造成数据库缓冲区溢出。PreparedStatement 可对SQL进行预编译,从而提高数据库的执行效率。
- 并且PreperedStatement对于sql中的参数,允许使用占位符的形式进行替换,简化sql语句的编写
使用JDBC处理大数据
在实际开发中,程序需要把大文本 Text 或二进制数据 Blob保存到数据库。
Text是mysql叫法,Oracle中叫Clob
基本概念:大数据也称之为LOB(Large Objects),LOB又分为:
clob和blob
clob用于存储大文本。Text
blob用于存储二进制数据,例如图像、声音、二进制文等。
对MySQL而言只有blob,而没有clob,mysql存储大文本采用的是Text,Text和blob分别又分为:
TINYTEXT(255)、TEXT(64k)、MEDIUMTEXT(16M)和LONGTEXT(4G)
TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB
Text是mysql叫法,Oracle中叫Clob
基本概念:大数据也称之为LOB(Large Objects),LOB又分为:
clob和blob
clob用于存储大文本。Text
blob用于存储二进制数据,例如图像、声音、二进制文等。
对MySQL而言只有blob,而没有clob,mysql存储大文本采用的是Text,Text和blob分别又分为:
TINYTEXT(255)、TEXT(64k)、MEDIUMTEXT(16M)和LONGTEXT(4G)
TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB
对于大数据操作,我们一般只有两种insert、select
(一)使用JDBC处理大文本:
对于MySQL中的Text类型,可调用如下方法设置:
create table mytext(
id int primary key auto_increment,
content longtext
)
(1)存储
File file = new File("F:\\myEclipse_project\\day17_3\\a.txt");
FileReader fr = new FileReader(file);
pst.setCharacterStream(1, fr, (int) (file.length()));
(2)获取:
Reader r = rs.getCharacterStream("content");
id int primary key auto_increment,
content longtext
)
(1)存储
File file = new File("F:\\myEclipse_project\\day17_3\\a.txt");
FileReader fr = new FileReader(file);
pst.setCharacterStream(1, fr, (int) (file.length()));
(2)获取:
Reader r = rs.getCharacterStream("content");
package cn.itcast.lob;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.junit.Test;
import cn.itcast.utils.JdbcUtils;
public class MyTextTest {
// 存储
@Test
public void save() throws SQLException, FileNotFoundException {
String sql = "insert into mytext values(null,?)";
// 1.获取Connection
Connection con = JdbcUtils.getConnection();
// 2.获取PreparedStatement
PreparedStatement pst = con.prepareStatement(sql);
// 3.插入值
File file = new File("F:\\myEclipse_project\\day17_3\\a.txt");
FileReader fr = new FileReader(file);
pst.setCharacterStream(1, fr, (int) (file.length()));
pst.executeUpdate();
// 4.释放资源
pst.close();
con.close();
}
// 获取
@Test
public void get() throws SQLException, IOException {
String sql = "select * from mytext where id=?";
// 1.获取Connection
Connection con = JdbcUtils.getConnection();
// 2.获取PreparedStatement
PreparedStatement pst = con.prepareStatement(sql);
pst.setInt(1, 1);
// 3.得到结果集
ResultSet rs = pst.executeQuery();
// 4.遍历结果集
if (rs.next()) {
Reader r = rs.getCharacterStream("content");
FileWriter fw = new FileWriter("d:/笔记.txt");
int len = -1;
char[] ch = new char[1024 * 100];
while ((len = r.read(ch)) != -1) {
fw.write(ch, 0, len);
fw.flush();
}
fw.close();
r.close();
}
pst.close();
con.close();
}
}
从数据库读取 存入到d盘根目录
(二)使用JDBC处理大二进制
大二进制操作
create table myblob(
id int primary key auto_increment,
content longblob
)
向表中插入数据
问题1:java.lang.AbstractMethodError: com.mysql.jdbc.PreparedStatement.setBinaryStream(ILjava/io/InputStream;)V
原因:mysql驱动不支持setBinaryStream(int,InputStream);
修改成
pst.setBinaryStream(1, fis,file.length());
原因:因为mysql驱动不支持setBinaryStream(int,InputStream,long);
解决:
mysql驱动支持setBinaryStream(int,InputStream,int);
注意:如果文件比较大,那么需要在my.ini文件中配置
max_allowed_packet=64M
create table myblob(
id int primary key auto_increment,
content longblob
)
向表中插入数据
问题1:java.lang.AbstractMethodError: com.mysql.jdbc.PreparedStatement.setBinaryStream(ILjava/io/InputStream;)V
原因:mysql驱动不支持setBinaryStream(int,InputStream);
修改成
pst.setBinaryStream(1, fis,file.length());
原因:因为mysql驱动不支持setBinaryStream(int,InputStream,long);
解决:
mysql驱动支持setBinaryStream(int,InputStream,int);
注意:如果文件比较大,那么需要在my.ini文件中配置
max_allowed_packet=64M
总结:
存 pst.setBinaryStream(1, fis, (int) (file.length()));
取 InputStream is = rs.getBinaryStream("content");
代码如下:
package cn.itcast.lob;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.junit.Test;
import cn.itcast.utils.JdbcUtils;
public class MyBlobTest {
// 添加
@Test
public void save() throws SQLException, IOException {
String sql = "insert into myblob values(null,?)";
// 1.获取Connection
Connection con = JdbcUtils.getConnection();
// 2.获取PreparedStatement
PreparedStatement pst = con.prepareStatement(sql);
// 3.插入值
File file = new File("C:\\Users\\lx\\Desktop\\2.jdbc介绍.avi");
FileInputStream fis = new FileInputStream(file);
pst.setBinaryStream(1, fis, (int) (file.length()));
int row = pst.executeUpdate();
if (row != 0) {
System.out.println("插入成功");
}
// 4.释放资源
fis.close();
pst.close();
con.close();
}
// 获取
@Test
public void get() throws SQLException, IOException {
String sql = "select * from myblob where id=?";
// 1.获取Connection
Connection con = JdbcUtils.getConnection();
// 2.获取PreparedStatement
PreparedStatement pst = con.prepareStatement(sql);
pst.setInt(1, 1);
// 3.得到结果集
ResultSet rs = pst.executeQuery();
// 4.遍历结果集
if (rs.next()) {
// System.out.println(rs.getInt("id"));
InputStream is = rs.getBinaryStream("content");// 得到的这个输入流它的源可以理解成就是数据库中的大二进制信息
FileOutputStream fos = new FileOutputStream("d:/a.avi");
int len = -1;
byte[] b = new byte[1024 * 100];
while ((len = is.read(b)) != -1) {
fos.write(b, 0, len);
fos.flush();
}
fos.close();
is.close();
}
// 5.关闭
rs.close();
pst.close();
con.close();
}
}
存入视频:读取数据库中的视频 到d盘根目录
使用JDBC进行批处理
一次可以执行多条sql语句.
在jdbc中可以执行sql语句的对象有Statement,PreparedStatement,它们都提供批处理.
1.Statement执行批处理
addBatch(String sql); 将sql语句添加到批处理
executeBatch(); 执行批处理
clearBatch(); 清除批处理
2.PreparedStatement执行批处理
addBatch();
executeBatch();
clearBatch();
以上两个对象执行批处理区别?
(1)Statement它更适合执行不同sql的批处理。它没有提供预处理功能,性能比较低。
(2)PreparedStatement它适合执行相同sql的批处理,它提供了预处理功能,性能比较高。
注意;mysql默认情况下,批处理中的预处理功能没有开启,需要开启
(1)在 url下添加参数
url=jdbc:mysql:///day17?useServerPrepStmts=true&cachePrepStmts=true&rewriteBatchedStatements=true
(2)注意驱动版本
Mysql驱动要使用mysql-connector-java-5.1.13以上
在jdbc中可以执行sql语句的对象有Statement,PreparedStatement,它们都提供批处理.
1.Statement执行批处理
addBatch(String sql); 将sql语句添加到批处理
executeBatch(); 执行批处理
clearBatch(); 清除批处理
2.PreparedStatement执行批处理
addBatch();
executeBatch();
clearBatch();
以上两个对象执行批处理区别?
(1)Statement它更适合执行不同sql的批处理。它没有提供预处理功能,性能比较低。
(2)PreparedStatement它适合执行相同sql的批处理,它提供了预处理功能,性能比较高。
注意;mysql默认情况下,批处理中的预处理功能没有开启,需要开启
(1)在 url下添加参数
url=jdbc:mysql:///day17?useServerPrepStmts=true&cachePrepStmts=true&rewriteBatchedStatements=true
(2)注意驱动版本
Mysql驱动要使用mysql-connector-java-5.1.13以上
package cn.itcast.batch;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import cn.itcast.utils.JdbcUtils;
public class StatementBatchTest {
public static void main(String[] args) throws SQLException {
// 定义sql语句
String sql1 = "create table person(id int,name varchar(20))";
String sql2 = "insert into person values(1,'tom')";
String sql3 = "insert into person values(2,'fox')";
String sql4 = "insert into person values(3,'tony')";
String sql5 = "update person set name='张三' where id=1";
String sql6 = "delete from person where id=3";
Connection con = JdbcUtils.getConnection();
// 得到一个Statement对象
Statement st = con.createStatement();
// 使用批处理执行sql
st.addBatch(sql1);
st.addBatch(sql2);
st.addBatch(sql3);
st.addBatch(sql4);
st.addBatch(sql5);
st.addBatch(sql6);
// 执行批处理
st.executeBatch();
st.close();
con.close();
}
}
package cn.itcast.batch;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import cn.itcast.utils.JdbcUtils;
public class PreparedStatementBatchTest {
public static void main(String[] args) throws SQLException {
// 向person表中插入1000条数据
String sql = "insert into person values(?,?)";
Connection con = JdbcUtils.getConnection();
PreparedStatement pst = con.prepareStatement(sql);
// 批处理
long l=System.currentTimeMillis();
for (int i = 1; i <= 100000; i++) {
pst.setInt(1, i);
pst.setString(2, "name" + i);
pst.addBatch();
if(i%1000==0){
pst.executeBatch();
pst.clearBatch(); //清空缓存。
}
}
//执行批处理
pst.executeBatch();
pst.close();
con.close();
System.out.println(System.currentTimeMillis()-l);
}
}