批处理可以将多个SQL语句一次性发送给数据库,可以减少连接数据库的开销。
JDBC实现批处理有两种方式:Statement和PreparedStatement
一、使用Statement对象进行批处理操作
步骤:
①使用createStatement()方法创建Statement对象
②使用setAutoCommit()将auto-commit设置为false。(这是JDBC的自动提交,默认是true,即开启自动提交)
③使用addBatch()方法在创建的语句对象上添加SQL语句到批处理中
④在创建的语句上使用executeBatch()方法执行所有SQL语句
⑤使用commit()方法提交所有改动
先准备一个数据库students:
CREATE TABLE `students` (
`sid` varchar(8) NOT NULL,
`sname` varchar(255) DEFAULT NULL,
`gender` varchar(255) DEFAULT NULL,
`birthday` date DEFAULT NULL,
`address` varchar(255) DEFAULT NULL,
PRIMARY KEY (`sid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
下面使用代码来展示:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
public class StatementBatch {
public static void main(String[] args) {
Connection conn = null;
Statement st = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql:///test","root", "1234");
//创建Statement对象
st = conn.createStatement();
//设置自动提交为false
conn.setAutoCommit(false);
//SQL语句
String sql1 = "insert into students values('S0000004','赵六','女','2015-10-12','银川')";
String sql2 = "insert into students values('S0000005','小明','男','2016-10-12','呼和浩特')";
String sql3 = "insert into students values('S0000006','小红','女','2017-10-12','喀什')";
st.addBatch(sql1);
st.addBatch(sql2);
st.addBatch(sql3);
int[] array = st.executeBatch();
conn.commit();
if(array.length>0){
System.out.println("添加成功!");
}else{
System.out.println("添加失败!");
}
for (int i : array) {
System.out.println(i);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
try {
if(st != null){
st.close();
}
if(conn != null){
conn.close();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
注意我们在代码中定义的array,批量添加返回的是一个数组,成功一条返回一个1,失败一条返回一个0。
使用Statement.addBatch(sql)方式实现批处理:
优点:可以向数据库发送多条不同的SQL语句
缺点:SQL语句没有预编译,当发送多条语句相同,但仅参数不同的SQL语句的时候,需要重复写多条SQL语句。
二、使用PrepareStatement对象进行批处理
步骤:
①使用占位符创建SQL语句
②使用PrepareStatement()方法创建PrepareStatement对象
③使用setAutoCommit()将auto-commit设置为false
④使用addBatch()方法在创建的语句对象上添加SQL语句到批处理中
⑤在创建的语句对象上使用executeBatch()方法执行所有SQL语句
⑥使用commit()方法提交所有改动
下面是代码展示:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
public class PreparedStatementBatch {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement ps = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql:///test","root", "1234");
String sql = "insert into students values(?,?,?,?,?)";
ps = conn.prepareStatement(sql);
conn.setAutoCommit(false);
ps.setString(1, "S0000007");
ps.setString(2, "李雷");
ps.setString(3, "女");
ps.setString(4, "1980-01-01");
ps.setString(5, "拉萨");
ps.addBatch();
ps.setString(1, "S0000008");
ps.setString(2, "韩梅梅");
ps.setString(3, "男");
ps.setString(4, "1980-12-31");
ps.setString(5, "鸡西");
ps.addBatch();
int[] array = ps.executeBatch();
conn.commit();
if(array.length>0){
System.out.println("添加成功!");
}else{
System.out.println("添加失败!");
}
for (int i : array) {
System.out.println(i);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
try {
if(ps != null){
ps.close();
}
if(conn != null){
conn.close();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
还可以进行对象批处理,这里给出一个实例代码:
@Test
public void t1(){
List<Employees> list=new ArrayList<Employees>();
list.add(new Employees(206, "tom1", "123", 123));
list.add(new Employees(207, "tom2", "123", 123));
list.add(new Employees(208, "tom3", "123", 123));
list.add(new Employees(209, "tom4", "123", 123));
list.add(new Employees(210, "tom5", "123", 123));
list.add(new Employees(211, "tom6", "123", 123));
list.add(new Employees(212, "tom7", "123", 123));
Connection conn=JdbcUtils.openConn();
try {
conn.setAutoCommit(false); //关闭自动提交
String sql="INSERT INTO Employees (id, first, last, age) VALUES(?,?,?,?)";
PreparedStatement ps = conn.prepareStatement(sql);
for (Employees e : list) {
ps.setObject(1, e.getId());
ps.setObject(2, e.getFirst());
ps.setObject(3, e.getLast());
ps.setObject(4, e.getAge());
ps.addBatch();
}
int[] arrays = ps.executeBatch(); //执行批处理
conn.commit(); //手动提交
System.out.println("执行完毕:"+Arrays.toString(arrays));
} catch (SQLException e) {
e.printStackTrace();
}
}
}
三、处理二进制数据
PreparedStatement对象可以使用输入和输出流来提供参数数据。可以将整个文件放入可以保存大值的数据库列,例如BLOB数据类型
数据库表:
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`image` longblob,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
这里只展示代码,不做结果及演示:
存储
public static void main(String[] args) throws Exception {
Connection conn = null;
PreparedStatement st=null;
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://192.168.132.128:3306/employeesdb?useUnicode=true&characterEncoding=utf-8", "root", "123");
String sql = "insert into testblob(image) values(?)";
st = conn.prepareStatement(sql);
File file = new File("D:\\005.jpg");
FileInputStream fis = new FileInputStream(file);//生成的流
st.setBinaryStream(1, fis,(int) file.length());
int num = st.executeUpdate();
if(num>0){
System.out.println("插入成功!!");
}
fis.close();
}
读取:
public static void main(String[] args) throws Exception {
Connection conn = null;
PreparedStatement st = null;
ResultSet rs=null;
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://192.168.132.128:3306/employeesdb?useUnicode=true&characterEncoding=utf-8", "root", "123");
String sql = "select image from testblob where id=?";
st = conn.prepareStatement(sql);
st.setInt(1, 1);
rs = st.executeQuery();
if (rs.next()) {
// InputStream in = rs.getBlob("image").getBinaryStream();//这种方法也可以
InputStream in = rs.getBinaryStream("image");
int len = 0;
byte buffer[] = new byte[1024];
FileOutputStream out = new FileOutputStream("D:\\1.jpg");
while ((len = in.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
in.close();
out.close();
}
}