JDBC编程–加强版
jdbc获取自增长的值
在数据库中建立一个表student,学生表中的id字段是主键,设置为自增长;
下面是给学生表中添加一条数据,获取这条数据的id:
package com.wy.increment;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import com.wy.util.DBUtil;
public class IncreamentTest {
public static void main(String[] args) {
//这里是创建了一个类,用来获取数据库连接,这里代码不再提供
Connection conn = DBUtil.getConnection();
String sql = "INSERT INTO student(name,age) VALUES(?,?);";
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
//设置返回自动生成的id
//设置预编译语句返回自动生成的主键值,RETURN_GENERATED_KEYS
pstmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
pstmt.setString(1, "cc");
pstmt.setInt(2, 12);
pstmt.executeUpdate();
rs = pstmt.getGeneratedKeys();
while(rs.next()){
//结果返回自动生成的id值
System.out.println(rs.getInt(1));
}
} catch (SQLException e) {
e.printStackTrace();
}finally{
DBUtil.closeConn(conn, pstmt);
}
}
}
JDBC的批处理
之前:一次操作只能发送一条sql语句到数据库服务器,效率并不高!
如果要插入2000条记录,那么必须发送2000条sql语句。
如果IO流的话,一次写出一个字节,显然效率效率并不高,所以可以使用缓存字节数组提高每次写出的效率。
现在:插入2000条记录,但现在使用sql缓存区,一次发送多条sql到数据库服务器执行。这种做法就叫做批处理。
JDBC批处理的API
Statement批处理:
void addBatch(String sql) 添加sql到缓存区(暂时不发送)
int[] executeBatch() 执行批处理命令。 发送所有缓存区的sql
void clearBatch() 清空sql缓存区
PreparedStatement批处理:
void addBatch() 添加参数到缓存区
int[] executeBatch() 执行批处理命令。 发送所有缓存区的sql
void clearBatch() 清空sql缓存区
下面使用statement和preparedstatement使用和不使用批处理向学生表插入2000条数据的效率。
package com.wy.statementbatch;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import com.wy.util.DBUtil;
public class StatementBatchTest {
public static void main(String[] args) {
long start = System.currentTimeMillis();
//这里输出每一种方法执行插入2000条数据需要多长时间
//statementTest();//60305
//batchTest();//57021
//preparedTest();//57725
preparedBatchTest();//58703
long end = System.currentTimeMillis();
System.out.println(end - start);
}
private static void preparedBatchTest() {
Connection conn = null;
PreparedStatement stmt = null;
try{
/*
* 这里是创建了一个工具类,DBUtil,里面有两个静态方法,一个是getConnection(),
* 一个是closeConn(Connection conn,Statement stmt);
*/
conn = DBUtil.getConnection();
//创建一个动态的sql语句
String sql = "insert into student values(?,?,?);";
stmt = conn.prepareStatement(sql);
//型数据库插入2000条数据,一次插入一条
for (int i = 1; i <=2000; i++) {
stmt.setInt(1, i);
stmt.setString(2, "cc");
stmt.setInt(3, 14);
stmt.addBatch();
//判断每20条发送一次
if (i%20==0) {
stmt.executeBatch();
//清空缓存区
stmt.clearBatch();
}
}
}catch(Exception e){
e.printStackTrace();
}finally{
//释放资源
DBUtil.closeConn(conn, stmt);
}
}
private static void preparedTest() {
Connection conn = DBUtil.getConnection();
PreparedStatement pstmt=null;
try {
for (int i = 1; i <= 2000; i++) {
String sql = "INSERT INTO student VALUES(?,?,?);";
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, i);
pstmt.setString(2, "cc");
pstmt.setInt(3, 12);
pstmt.executeUpdate();
}
} catch (SQLException e) {
e.printStackTrace();
}finally{
DBUtil.closeConn(conn, pstmt);
}
}
private static void statementTest() {
Connection conn = DBUtil.getConnection();
Statement stmt=null;
try {
stmt = conn.createStatement();
for (int i = 1; i <= 2000; i++) {
String sql = "INSERT INTO student VALUES("+i+",'cc',23);";
stmt.executeUpdate(sql);
}
} catch (SQLException e) {
e.printStackTrace();
}finally{
DBUtil.closeConn(conn, stmt);
}
}
private static void batchTest() {
Connection conn = DBUtil.getConnection();
Statement stmt=null;
try {
stmt = conn.createStatement();
for (int i = 1; i <= 2000; i++) {
String sql = "INSERT INTO student VALUES("+i+",'cc',23);";
stmt.addBatch(sql);
if(i%20 == 0){
stmt.executeBatch();
stmt.clearBatch();
}
}
} catch (SQLException e) {
e.printStackTrace();
}finally{
DBUtil.closeConn(conn, stmt);
}
}
}
jdbc处理大数据文件
大容量的字符字段:
mysql: text(64K) longtext(4G字符内容)
oracle : clob longclob
大容量的字节字段:
mysql: blob(65kb) mediumblob(16mb) longblog(4GB)
oracle: blob
jdbc处理大容量的字符字段示例:
package com.wy.clob;
/*
*这个是在数据库中创建一个表,两个字段
CREATE TABLE news(
title VARCHAR(100),
content LONGTEXT
);
*/
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.Statement;
import com.wy.util.DBUtil;
public class ClobTest {
/*
* 将一篇文章存入数据库
*/
public static void main(String[] args) throws IOException {
// saveToDB();
writerTest();
}
private static void writerTest() throws IOException {
Connection conn = DBUtil.getConnection();
String sql = "select * from news;";
Statement stmt = null;
FileWriter fw = new FileWriter("result.txt");
try {
stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql);
while(rs.next()){
Reader reader = rs.getCharacterStream(2);
char[] chs = new char[1024];
int len;
while((len = reader.read(chs))!= -1){
fw.write(chs, 0, len);
fw.flush();
}
reader.close();
}
fw.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
DBUtil.closeConn(conn, stmt);
}
}
private static void saveToDB() {
Connection conn = DBUtil.getConnection();
String sql = "insert into news values(?,?);";
PreparedStatement pstmt = null;
try {
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "studyyyyyy");
// void setClob(int parameterIndex,Reader reader)throws SQLException
pstmt.setClob(2, new FileReader("d://xuexi.docx"));
int count = pstmt.executeUpdate();
System.out.println(count);
} catch (Exception e) {
e.printStackTrace();
} finally {
DBUtil.closeConn(conn, pstmt);
}
}
}
jdbc处理大容量的字符字段示例:
package com.wy.blob;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import com.wy.util.DBUtil;
public class BlobTest {
public static void main(String[] args) {
// 从数据库中读取数据
// readTest();
// 把mp3文件保存如数据库
writerTest();
}
private static void writerTest() {
Connection conn = DBUtil.getConnection();
String sql = "insert into news values(?,?);";
PreparedStatement pstmt = null;
try {
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "video_yueyu");
// void setClob(int parameterIndex,Reader reader)throws SQLException
pstmt.setClob(2, new FileReader("E://joy.mp4"));
int count = pstmt.executeUpdate();
System.out.println(count);
} catch (Exception e) {
e.printStackTrace();
} finally {
DBUtil.closeConn(conn, pstmt);
}
}
private static void readTest() throws Exception {
Connection conn = DBUtil.getConnection();
String sql = "select * from news;";
Statement stmt = null;
FileOutputStream fos;
fos = new FileOutputStream("videoresult.mp4");
try {
stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql);
while(rs.next()){
InputStream is = rs.getBinaryStream(2);
byte[] bys = new byte[1024];
int len;
while((len = is.read(bys))!= -1){
fos.write(bys,0,len);
}
fos.close();
is.close();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
DBUtil.closeConn(conn, stmt);
}
}
}
数据库中的事务以及在JDBC中的体现
所谓的事务,如果把多条sql语句看做一个事务,那么这个事务要么一起成功,要么一起失败!!
数据库事务的四大特性(简称ACID,acid是英文酸,醋的意思)是:
1. 原子性(Atomicity)
要么一起成功过,要么一起失败
2. 一致性(Consistency)
数据库应该从一个一致性的状态到另一个一致性的状态,保持不变。
3. 分离性(亦称独立性Isolation)
多个并发事务直接应该可以相互隔离
- 持久性(Durability)
事务一旦提交,应该永久保持下来。
mysql事务操作命令
set autocommit =0 / 1;
设置是否自动提交事务
1: 表示自动提交事务,每执行一条sql语句,自动提交事务。
0: 表示关闭自动提交事务。
commit;
提交事务,一旦提交事务不能回滚
rollback;
回滚事务。回滚到事务的起始点。
CREATE DATABASE testdb;
USE testdb;
CREATE TABLE account(
NAME VARCHAR(20),
balance INT
);
INSERT INTO account VALUES('tom',5000);
INSERT INTO account VALUES('kite',5000);
1.创建一个account表,然后进行存取操作,如果不设置自动提交,则为自动提交;
即下面的操作会直接更新数据库:
UPDATE account SET balance=balance-2000 WHERE NAME='kite';
UPDATE account SET balance=balance+2000 WHERE NAME='tom';
2.如果设置为手动提交,则更新不写入数据库:
SET autocommit=0;
UPDATE account SET balance=balance-2000 WHERE NAME='kite';
UPDATE account SET balance=balance+2000 WHERE NAME='tom';
只有提交了,才会写入数据库:
commit;
3.如果设置为手动提交,在更新之后进行了回滚,则操作不更新到数据库:
SET autocommit=0;
UPDATE account SET balance=balance-2000 WHERE NAME='kite';
UPDATE account SET balance=balance+2000 WHERE NAME='tom';
ROLLBACK;
4.如果设置为手动提交,在更新之后提交,再进行回滚,则回不到初始状态:
SET autocommit=0;
UPDATE account SET balance=balance-2000 WHERE NAME='kite';
UPDATE account SET balance=balance+2000 WHERE NAME='tom';
COMMIT;
commit表示事务的结束;
jdbc事务操作
Connection.setAutoCommit(false) 开启事务
Connection.commit(); 成功执行,最后提交事务
Connection.rollback(); 一旦遇到错误,回滚事务
package com.wy.db;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/*
* CREATE DATABASE testdb;
USE testdb;
CREATE TABLE account(
NAME VARCHAR(20),
balance INT
);
INSERT INTO account VALUES('tom',5000);
INSERT INTO account VALUES('kite',5000);
SET autocommit=0;
SET autocommit=1;
UPDATE account SET balance=balance-2000 WHERE NAME='kite';
UPDATE account SET balance=balance+2000 WHERE NAME='tom';
ROLLBACK;
COMMIT;
SELECT * FROM account;
DELETE FROM account;
DROP TABLE acount;
*/
//在Java中数据库的事务体现
public class TransactionTest {
public static void main(String[] args) {
Connection conn = getConnection();
String sqlMinus = "UPDATE account SET balance=balance-2000 WHERE NAME=?;";
String sqlAdd = " UPDATE account SET balance=balance+2000 WHERE NAME=?;";
try {
conn.setAutoCommit(false);
PreparedStatement pstmt = conn.prepareStatement(sqlMinus);
pstmt.setString(1, "kite");
pstmt.executeUpdate();
pstmt = conn.prepareStatement(sqlAdd);
pstmt.setString(1, "tom");
pstmt.executeUpdate();
//只有都成功执行才进行提交,在数据库进行更改
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
System.out.println("转账出现异常");
try {
//如果转账出现异常,则进行回滚
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
}finally{
//释放资源
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
private static Connection getConnection() {
//进行数据库连接
String url = "jdbc:mysql://localhost:3306/testdb";
String user = "root";
String password = "root";
try {
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection(url, user, password);
return conn;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}