文檔版本 | 開發工具 | 測試平台 | 工程名字 | 日期 | 作者 | 備注 |
---|---|---|---|---|---|---|
V1.0 | 2016.05.11 | lutianfei | none |
JDBC
JDBC介紹
- JDBC是什麼?
- JDBC(Java Data Base Connectivity,java資料庫連接配接)
- SUN公司為了簡化、統一對資料庫的操作,定義了一套Java操作資料庫的規範,稱之為JDBC。
- 簡單說,就是可以直接通過java語言去操作資料庫。
- jdbc是一套标準,它是由一些接口與類組成的。

組成JDBC的類和接口
- java.sql
- 類:DriverManger
- 接口
Connection
Statement
ResultSet
PreparedStatement
(它是用于調用存儲過程)CallableStatement
- javax.sql
- 接口 DataSource(資料源)
- 什麼是驅動?
- 兩個裝置要進行通信,滿足一定通信資料格式,資料格式由裝置提供商規定,裝置提供商為裝置提供驅動軟體,通過軟體可以與該裝置進行通信。
JDBC入門
第一個JDBC程式
- 程式設計從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中取出資料,列印到指令行視窗
- 六、斷開與資料庫的連接配接,并釋放相關資源
- 一、搭建實驗環境 :
create table user(
id int primary key auto_increment,
username varchar() unique not null,
password varchar() not null,
email varchar() not null
);
INSERT INTO USER VALUES(NULL,'tom','123','[email protected]');
INSERT INTO USER VALUES(NULL,'fox','123','[email protected]');
- 1.加載驅動
- 将驅動jar包複制到lib下.
- 2.建立一個JdbcDemo1類
public static void main(String[] args) throws SQLException {
// 注冊驅動
// DriverManager.registerDriver(new Driver()); //加載了兩個驅動
Class.forName("com.mysql.jdbc.Driver"); // 加載mysql驅動
// 擷取連接配接對象
Connection con = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/day17", "root", "abc");
// 通過連接配接對象擷取操作sql語句Statement
Statement st = con.createStatement();
// 操作sql語句
String sql = "select * from user";
// 操作sql語句(select語句),會得到一個ResultSet結果集
ResultSet rs = st.executeQuery(sql);
// 周遊結果集
// 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);
}
//釋放資源
rs.close();
st.close();
con.close();
}
JDBC操作詳解
1.注冊驅動
- JDBC程式中的
是DriverManager
包下的一個驅動管理的工具類,可以了解成是一個容器(Vector),可以裝入很多資料庫驅動,并建立與資料庫的連結,這個API的常用方法:java.sql
- DriverManager.registerDriver(new Driver())
- DriverManager.getConnection(url, user, password),
-
分析registDriver方法
- public static synchronized void registerDriver(java.sql.Driver driver)
- 參數:java.sql.Driver
- 我們傳遞的是 : com.mysql.jdbc.Driver;
- 在com.mysql.jdbc.Driver類中有一段靜态代碼塊:
- public static synchronized void registerDriver(java.sql.Driver driver)
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
- 上述代碼的問題:
- 1.在驅動管理器中會裝入兩個mysql驅動.
- 解決方案:使用反射
Class.forName("com.mysql.jdbc.Driver");
- 分析:使用反射的方式來加載驅動有什麼好處?
- 一、檢視Driver的源代碼可以看到,如果采用此種方式,會導緻驅動程式注冊兩次,也就是在記憶體中會有兩個Driver對象。
- 二、程式依賴mysql的api,脫離mysql的jar包,程式将無法編譯,将來程式切換底層資料庫将會非常麻煩。
- 解決方案:使用反射
- 2.可以通過DriverManager來擷取連接配接對象
-
Connection con=DriverManager.getConection(String url,String user,String password);
- url作用:就是用于确定使用哪一個驅動.
- mysql url:
jdbc: mysql ://localhsot:3306/資料庫名
- oralce url:
jdbc : oracle :thin :@ localhost :1521 :sid
- mysql url:
-
- 1.在驅動管理器中會裝入兩個mysql驅動.
- DriverManager作用總結:
- 1.注冊驅動
- 2.擷取連接配接Connection
資料庫URL
- URL用于辨別資料庫的位置,程式員通過URL位址告訴JDBC程式連接配接哪個資料庫,URL的寫法為:
-
jdbc : mysql : // localhost :3306/test ?key=value
-
- url格式
- 主協定 子協定 主機 端口 資料庫
-
jdbc : mysql ://localhost:3306/day17
- mysql的url可以簡寫
- 前提:主機是:localhost 端口是 :3306
-
jdbc : mysql : ///day17
- 在url後面可以帶參數
- eg: useUnicode=true&characterEncoding=UTF-8
2.Connection詳解
-
,它代表的是一個連接配接對象。簡單說,就是我們程式與資料庫連接配接。java.sql.Connection
- Connection作用:
- 1.可以通過Connection擷取操作SQL的Statement對象。
- Statement createStatement() throws SQLException
- 示例:
- Statement st=con.createStatement();
- 2.操作事務
- setAutoCommit(boolean flag);開啟事務,設定事務是否自動送出。
- rollback();事務復原,在此連結上復原事務。
- commit();事務送出,在連結上送出事務。 —與事務相關!!
- 了解:
- 1.可以擷取執行預處理的
.建立向資料庫發送預編譯sql的PrepareSatement對象PreparedStatement對象
- PreparedStatement prepareStatement(String sql) throws SQLException
- 2.可以擷取執行存儲過程的
,建立執行存儲過程的callableStatement對象。CallableStatement
- CallableStatement prepareCall(String sql) throws SQLException
- 1.可以擷取執行預處理的
- 1.可以通過Connection擷取操作SQL的Statement對象。
3.Statement詳解
-
用于向資料庫發送SQL語句,執行sql語句。java.sql.Statement
Statement作用
- 1.執行SQL
- DML :
insert
update
delete
- int executeUpdate(String sql) :用于向資料庫發送insert、update或delete語句
- 利用傳回值判斷非0來确定sql語句是否執行成功。
- int executeUpdate(String sql) :用于向資料庫發送insert、update或delete語句
- DQL :
select
- ResultSet executeQuery(String sql) : 用于向資料發送查詢語句。
- execute(String sql):用于向資料庫發送任意SQL語句
- DML :
- 2.批處理操作
- addBatch(String sql); 将SQL語句添加到批處理
- executeBatch(); 向資料庫發送一批SQl語句執行。
- clearBatch(); 清空批處理。
4.ResultSet詳解
-
它是用于封裝select語句執行後查詢的結果。Resultset封裝執行結果時,采用的類似于表格的方式。ResultSet 對象維護了一個指向表格資料行的java.sql.ResultSet
,初始的時候,遊标在第一行之前,調用遊标cursor
,可以使遊标指向具體的資料行,進而調用方法擷取該行的資料。ResultSet.next() 方法
ResultSet常用API
- 1.next()方法
- public boolean next();
- 用于判斷是否有下一條記錄。如果有傳回true,并且讓遊标向下移動一行。
- 如果沒有傳回false.
- 2.可以通過ResultSet提供的getXxx()方法來擷取目前遊标指向的這條記錄中的列資料。
- 常用:
- getInt()
- getString(int index)
- getString(String columnName):也可以獲得int,Data等類型
- getDate()
- getDouble()
- 參數有兩種
- 1.getInt(int columnIndex);
- 2.getInt(String columnName);
- 常用:
- 如果列的類型不知道,可以通過下面的方法來操作
- getObject(int columnIndex);
- getObject(String columnName);
- 常用資料類型轉換表
Java進階學習第十七天——JDBC入門學習
釋放資源
- JDBC程式運作完後,切記要釋放程式在運作過程中,建立的那些與資料庫進行互動的對象,這些對象通常是ResultSet, Statement和Connection對象。
- 特别是
,它是非常稀有的資源,用完後必須馬上釋放,如果Connection不能及時、正确的關閉,極易導緻系統當機。Connection對象
- Connection的使用原則是盡量晚建立,盡量早的釋放。
- 為確定資源釋放代碼能運作,資源釋放代碼也一定要放在
語句中。finally
- 完整版JDBC示例代碼:
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:///day17", "root",
"abc");
// 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對象的
,用于向資料庫發送增、删、改的sql語句,executeUpdate執行完後,将會傳回一個整數(即增删改語句導緻了資料庫幾行資料發生了變化)。executeUpdate方法
-
用于向資料庫發送查詢語句,executeQuery方法傳回代表查詢結果的ResultSet對象。Statement.executeQuery方法
- 1.查詢
- 1.查詢全部
- 2.條件查詢—根據id
- 2.修改
- 3.删除
- 4.添加
- 練習:編寫程式對User表進行增删改查操作。
- 練習:編寫工具類簡化CRUD操作。(異常暫不處理)
JdbcUtils工具類
- 隻抽取到Connection
//jdbc.properties
driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql:///day17
username=root
password=abc
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();
}
}
}
- JDBC CURD
//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:///day17", "root",
"abc");
// 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','[email protected]')";
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 != ) {
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 != ) {
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 != ) {
System.out.println("删除成功");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 關閉資源
try {
JdbcUtils.closeStatement(st);
JdbcUtils.closeConnection(con);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
ResultSet 滾動結果集
- 預設得到的ResultSet它隻能向下周遊(next()),對于ResultSet它可以設定成是滾動的,可以向上周遊,或者直接定位到一個指定的實體行号。
- 設定滾動結果集的方法
- 在建立Statement對象時,不使用
;而使用帶參數的createStatement()
createStatement(int,int)
- 在建立Statement對象時,不使用
Statement createStatement(int resultSetType,
int resultSetConcurrency)
throws SQLException
、
Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
- 第一個參數值,
resultSetType
- ResultSet.TYPE_FORWARD_ONLY 該常量訓示光标隻能向前移動的 ResultSet 對象的類型。
- ResultSet.TYPE_SCROLL_INSENSITIVE 該常量訓示可滾動但通常不受 ResultSet 底層資料更改影響的 ResultSet 對象的類型。
- ResultSet.TYPE_SCROLL_SENSITIVE 該常量訓示可滾動并且通常受 ResultSet 底層資料更改影響的 ResultSet 對象的類型。
- 第二個參數值,
resultSetConcurrency
- 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() :更新行資料
DAO模式——JavaEE模式
-
(Data Access Object 資料通路對象):在持久層通過DAO将資料源操作完全封裝起來,業務層通過操作Java對象,完成對資料源操作DAO模式
- 業務層無需知道資料源底層實作 ,通過java對象操作資料源
DAO模式結構
- 1、DataSource資料源(MySQL資料庫)
- 2、Business Object 業務層代碼,調用DAO完成 對資料源操作 (代表資料的使用者)
- 3、DataAccessObject 資料通路對象,持久層DAO程式,封裝對資料源增删改查,提供方法參數都是Java對象
- 4、TransferObject 傳輸對象(值對象) 業務層通過向資料層傳遞 TO對象,完成對資料源的增删改查(表示資料的Java Bean)
使用dao模式完成登入操作
- 需求:
- 1、把檔案換成資料庫
- 2、使用DAO模式
- 3、防範sql注入攻擊
- 1.web層
- login.jsp LoginServlet User
- 2.service層
- UserService(實際應是接口)
- 3.dao層
- UserDao(實際應是接口)
- 具體代碼見工程
。day17_2
- 使用者注冊流程
Java進階學習第十七天——JDBC入門學習
sql注入
- 由于沒有對使用者輸入進行充分檢查,而SQL又是拼接而成,在使用者輸入參數時,在參數中添加一些SQL 關鍵字,達到改變SQL運作結果的目的,也可以完成惡意攻擊。
- 1、statement存在sql注入攻擊問題
- 例如登陸使用者名采用
xxx’ or ‘1’=‘1
- 使用mysql注釋
- 例如登陸使用者名采用
- 2、對于防範 SQL 注入,可以采用
取代PreparedStatement
。Statement
- 它是一個預處理的Statement,它是java.sql.Statement接口的一個子接口。
- PreparedStatement是Statement的子接口,它的執行個體對象可以通過調
方法獲得Connection.preparedStatement(sql)
- Statement會使資料庫頻繁編譯SQL,可能造成資料庫緩沖區溢出。PreparedStatement 可對SQL進行預編譯,進而提高資料庫的執行效率。
- PreperedStatement對于sql中的參數,允許使用占位符的形式進行替換,簡化sql語句的編寫。
- 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();
- 注意:這兩方法無參數
- 1.在sql語句中,使用
- 關于PreparedStatement優點:
- 1.解決sql注入(具有預處理功能)
- 2.不需要再拼sql語句。
jdbc處理大資料
- 在實際開發中,程式需要把大文本
或二進制資料Text
儲存到資料庫。Blob
-
是mysql叫法,Oracle中叫Text
Clob
-
-
也稱之為大資料
(Large Objects),LOB又分為:LOB
- clob用于存儲大文本。Text
- blob用于存儲二進制資料,例如圖像、聲音、二進制文等。
- Text和blob分别又分為:
- Text(clob)
- TINYTEXT(255B)、TEXT(64kb)、MEDIUMTEXT(16M)和LONGTEXT(4G)
- blob
- TINYBLOB(255B)、BLOB(64kb)、MEDIUMBLOB(16M)和LONGBLOB(4G)
- Text(clob)
- 對于大資料操作,我們一般隻有兩種: insert select
- 示範1: 大二進制操作
create table myblob(
id int primary key auto_increment,
content longblob
)
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("D:\\java1110\\day17-jdbc\\視訊\\3.jdbc快速入門.avi");
FileInputStream fis = new FileInputStream(file);
pst.setBinaryStream(, fis, (int) (file.length())); //MySQL驅動隻支援最後一個參數為int類型的方法
int row = pst.executeUpdate();
if (row != ) {
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(, );
// 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 = -;
byte[] b = new byte[ * ];
while ((len = is.read(b)) != -) {
fos.write(b, , len);
fos.flush();
}
fos.close();
is.close();
}
// 5.關閉
rs.close();
pst.close();
con.close();
}
}
- 向表中插入資料可能出現的問題
- 問題1:java.lang.AbstractMethodError: com.mysql.jdbc.PreparedStatement.setBinaryStream(ILjava/io/InputStream;)
- 原因: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”);
使用JDBC處理大文本
- 對于MySQL中的Text類型,可調用如下方法
:設定
PreparedStatement.setCharacterStream(index, reader, length);
//注意length長度須設定,并且設定為int型
//當包過大時修改配置:[mysqld] max_allowed_packet=M
- 對MySQL中的Text類型,可調用如下方法
:擷取
reader = resultSet. getCharacterStream(i);
等價于
reader = resultSet.getClob(i).getCharacterStream();
- 示範:存儲大文本
create table mytext(
id int primary key auto_increment,
content longtext
)
//存儲
File file = new File("D:\\java1110\\workspace\\day17_3\\a.txt");
FileReader fr = new FileReader(file);
pst.setCharacterStream(, fr, (int) (file.length()));
//擷取:
Reader r = rs.getCharacterStream("content");
使用JDBC處理二進制資料
- 對于MySQL中的BLOB類型,可調用如下方法
:設定
-
PreparedStatement. setBinaryStream(i, inputStream, length);
-
- 對MySQL中的BLOB類型,可調用如下方法
:擷取
-
InputStream in = resultSet.getBinaryStream(i);
-
InputStream in = resultSet.getBlob(i).getBinaryStream();
-
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("D:\\java1110\\workspace\\day17_3\\a.txt");
FileReader fr = new FileReader(file);
pst.setCharacterStream(, 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(, );
// 3.得到結果集
ResultSet rs = pst.executeQuery();
// 4.周遊結果集
if (rs.next()) {
Reader r = rs.getCharacterStream("content");
FileWriter fw = new FileWriter("d:/筆記.txt");
int len = -;
char[] ch = new char[ * ];
while ((len = r.read(ch)) != -) {
fw.write(ch, , len);
fw.flush();
}
fw.close();
r.close();
}
pst.close();
con.close();
}
}
JDBC批處理
- 業務場景:當需要向資料庫發送一批SQL語句執行時,應避免向資料庫一條條的發送執行,而應采用JDBC的批處理機制,以提升執行效率。
- 實作批處理有兩種方式,第一種方式:
- Statement.addBatch(sql)
- executeBatch()方法:執行批處理指令
- clearBatch()方法:清除批處理指令
- 采用Statement.addBatch(sql)方式實作批處理:
- 優點:可以向資料庫發送多條不同的SQL語句。
- 缺點:
- SQL語句沒有預編譯。
- 當向資料庫發送多條語句相同,但僅參數不同的SQL語句時,需重複寫上很多條SQL語句。例如:
- Insert into user(name,password) values(‘aa’,’111’);
- Insert into user(name,password) values(‘bb’,’222’);
- Insert into user(name,password) values(‘cc’,’333’);
- Insert into user(name,password) values(‘dd’,’444’);
- 實作批處理的第二種方式
- PreparedStatement.addBatch()
- addBatch();
- executeBatch();
- clearBatch();
- PreparedStatement.addBatch()
- 采用PreparedStatement.addBatch()實作批處理
- 優點:發送的是預編譯後的SQL語句,執行效率高。
- 缺點:隻能應用在SQL語句相同,但參數不同的批進行中。是以此種形式的批處理經常用于在同一個表中批量插入資料,或批量更新表的資料。
- 兩個對象執行批處理差別?
- 1.Statement它更适合執行不同sql的批處理。它沒有提供預處理功能,性能比較低。
- 2.PreparedStatement它适合執行相同sql的批處理,它提供了預處理功能,性能比較高。
- eg:第一種方式
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
conn = JdbcUtil.getConnection();
String sql1 = "insert into person(name,password,email,birthday)
values('kkk','123','[email protected]','1978-08-08')";
String sql2 = "update user set password='123456' where id=";
st = conn.createStatement();
st.addBatch(sql1); //把SQL語句加入到批指令中
st.addBatch(sql2); //把SQL語句加入到批指令中
st.executeBatch();
} finally{
JdbcUtil.free(conn, st, rs);
}
- eg:第二種方式
conn = JdbcUtil.getConnection();
String sql = "insert into person(name,password,email,birthday) values(?,?,?,?)";
st = conn.prepareStatement(sql);
for(int i=;i<50000;i++){
st.setString(, "aaa" + i);
st.setString(, "123" + i);
st.setString(, "aaa" + i + "@sina.com");
st.setDate(,new Date(, , ));
st.addBatch();
if(i%==){
st.executeBatch();
st.clearBatch();
}
}
st.executeBatch();
- 注意;mysql預設情況下,批進行中的預處理功能沒有開啟,需要開啟
- 1.在 url下添加參數
- url=jdbc :mysql :///day17?
useServerPrepStmts=true&cachePrepStmts=true&rewriteBatchedStatements=true
- url=jdbc :mysql :///day17?
- 2.注意驅動版本
- Mysql驅動要使用mysql-connector-java-5.1.13以上
- 1.在 url下添加參數
- 作業:
- 1.注冊+登入案例
- 采用dao模式 使用PreparedStatement操作
- 2.使用PreparedStatement完成CRUD
- 客戶資訊表DAO編寫
- 創立如下資料庫表customer,并編寫DAO進行crud操作