一、JDBC簡介
JDBC(Java Data Base Connectivity)java數據庫連接
SUN公司為了簡化、統一對數據庫的操作,定義了一套Java操作數據庫的規范,稱之為JDBC。這套接口由數據庫廠商去實現,這樣,開發人員只需要學習JDBC接口,並通過JDBC加載具體的驅動,就可以操作數據庫。
可以為多種數據庫提供統一的訪問,如Oracle,Mysql,SQL Server
體現了java“一次編譯,到處運行”的思想
MVC結構: View ,Control, Model, DB
二、代碼步驟
需要的包:java.sql.*,
javax.sql.*
以及相應的數據庫驅動的支持
1、加載數據庫驅動:
SUN公司只是定義了JDBC的一些接口,如果想要操作數據庫,需要先把數據庫的驅動,也就是JDBC的實現類拿到程序里來,這個操作稱之為注冊驅動,使用DriverManager類
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
2、創建數據庫連接:
JDBC提供了三種連接方式:一個參數,兩個參數、三個參數
方式一:
DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb?username=root&password=aaa");
方式二:
Properties p = new Properties();
p.setProperty("username", "root");
p.setProperty("password", "aaa");
DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", p);
方式三:
DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "aaa");
3、創建用於向數據庫發送sql的Statement對象
Statement st = connection.createStatement();
String sql = "select * from table users;";
ResultSet rs = st.executeQuery(sql);
4、從代表結果集的ResultSet 中取出數據,進行操作
while(rs.next()){
rs.getString(columnIndex);
}
5、釋放資源
在finally中釋放資源
三、JDBC使用詳解
1、DriverManager類常用API:
DriverManager.registerDriver(new Driver());
DriverManager.getConnection(url,user,password);
url的寫法:
jdbc:mysql:[]//localhost:3306/test?參數名=參數值
常用數據庫URL地址的寫法:
Oracle寫法:jdbc:oracle:thin:@localhost:1521:sid
SqlServer—jdbc:microsoft:sqlserver://localhost:1433; DatabaseName=sid
MySql—jdbc:mysql://localhost:3306/sid
Mysql的url地址的簡寫形式: jdbc:mysql:///sid
如果你的主機地址默認是localhost 端口是3306
2、Connection類常用API:
Connection是數據庫編程中最重要的一個對象,客戶端與數據庫所有交互都是通過該對象完成的。
createStatement(): 創建向數據庫放松sql的statement對象
prepareStatment(sql):創建向數據庫發送預編譯sql的PrepareStatement對象
setAutoCommit(boolean autoCommit):設置事務是否自動提交。
commit() :在鏈接上提交事務。
rollback() :在此鏈接上回滾事務。
3、Statement類常用API:
Jdbc程序中的Statement對象用於向數據庫發送SQL語句。
executeQuery(String sql) :用於向數據發送查詢語句。
executeUpdate(String sql):用於向數據庫發送insert、update或delete語句
execute(String sql):用於向數據庫發送任意sql語句
4、ResultSet類常用API:
Jdbc程序中的ResultSet用於代表Sql語句的執行結果。Resultset封裝執行結果時,采用的類似於表格的方式。ResultSet 對象維護了一個指向表格數據行的游標,初始的時候,游標在第一行之前,調用ResultSet.next() 方法,可以使游標指向具體的數據行,進行調用方法獲取該行的數據。
獲取任意類型的數據:(列號從 1 開始)
getObject(int index)
getObject(string columnName)
獲取指定類型的數據,(封裝數據時方便)例如:
getString(int index)
getString(String columnName)
ResultSet還提供了對結果集進行滾動的方法:
next():移動到下一行
Previous():移動到前一行
absolute(int row):移動到指定行
beforeFirst():移動resultSet的最前面。
afterLast() :移動到resultSet的最后面。
5、釋放資源:
Jdbc程序運行完后,切記要釋放程序在運行過程中,創建的那些與數據庫進行交互的對象,這些對象通常是ResultSet, Statement和Connection對象。
特別是Connection對象,它是非常稀有的資源,用完后必須馬上釋放,如果Connection不能及時、正確的關閉,極易導致系統宕機。
Connection的使用原則是盡量晚創建,盡量早的釋放。
為確保資源釋放代碼能運行,資源釋放代碼也一定要放在finally語句中。
6、使用JDBC對數據庫進行CRUD:
Statement.executeQuery方法用於向數據庫發送查詢語句,executeQuery方法返回代表查詢結果的ResultSet對象。
Statement對象的executeUpdate方法,用於向數據庫發送增、刪、改的sql語句,executeUpdate執行完后,將會返回一個整數(即增刪改語句導致了數據庫幾行數據發生了變化)。
1 //查詢操作 2 Statement st = conn.createStatement(); 3 String sql = “select * from user where id=1; 4 ResultSet rs = st.executeQuery(sql); 5 while(rs.next()){ 6 //根據獲取列的數據類型,分別調用rs的相應方法 7 //映射到java對象中 8 } 9 10 //插入操作 11 String sql = "insert into user(….) values(…..) "; 12 int num = st.executeUpdate(sql); 13 if(num>0){ 14 System.out.println("插入成功!!!"); 15 } 16 //修改操作 17 String sql = “update user set name=‘’ where name=‘’"; 18 int num = st.executeUpdate(sql); 19 if(num>0){ 20 System.out.println("修改成功!!!"); 21 } 22 //刪除操作 23 String sql = “delete from user where id=1; 24 int num = st.executeUpdate(sql); 25 if(num>0){ 26 System.out.println("刪除成功!!!"); 27 }
7、PreparedSatement類詳解:
PreperedStatement是Statement的孩子,它的實例對象可以通過調用Connection.preparedStatement()方法獲得,相對於Statement對象而言:
Statement會使數據庫頻繁編譯SQL,可能造成數據庫緩沖區溢出。
PreparedStatement 可對SQL進行預編譯,從而提高數據庫的執行效率。
並且PreperedStatement對於sql中的參數,允許使用占位符的形式進行替換,簡化sql語句的編寫。
1 String insertString = "insert into users values(?,?,?,?);"; 2 //id, name, password, email 3 4 PreparedStatement preparedStatement= connection.prepareStatement(insertString); 5 preparedStatement.setInt(1, 1); 6 preparedStatement.setString(2, "zhangsan"); 7 preparedStatement.setString(3, "123456"); 8 preparedStatement.setString(4, "zhansan@sina.com"); 9 preparedStatement.execute();
8、使用JDBC處理大文本和大二進制數據:
在實際開發中,程序一般不需要把大文本或二進制數據保存到數據庫。
mysql存儲大文本采用的是Text,Text和blob分別又分為:
TINYTEXT、TEXT、MEDIUMTEXT和LONGTEXT
TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB
-
1 //把一個文件里的內容保存到 text 列中 2 File file = new File("1.txt"); 3 FileReader fileReader = new FileReader(file); 4 String insertsString ="insert into lobtest values(?,?)"; 5 PreparedStatement ps = connection.prepareStatement(insertsString); 6 7 /* void setCharacterStream(int parameterIndex, Reader reader) 8 將指定參數設置為給定 Reader 對象。 9 //mysql 僅支持這個方法 10 void setCharacterStream(int parameterIndex, Reader reader, int length) 11 將給定參數設置為給定 Reader 對象,該對象具有給定字符數長度。 12 void setCharacterStream(int parameterIndex, Reader reader, long length) 13 將指定參數設置為給定 Reader 對象,該對象具有給定字符數長度。 14 15 */ 16 ps.setInt(1, 1); 17 ps.setCharacterStream(2,fileReader,(int)file.length()); 18 ps.execute(); 19 //把一個text列中的內容存儲到一個文件中 20 File file = new File("2.txt"); 21 FileWriter fileWriter = new FileWriter(file); 22 String queryString ="select content from lobtest where id = ?"; 23 PreparedStatement ps = connection.prepareStatement(queryString); 24 ps.setInt(1, 1); 25 ps.execute(); 26 rs=ps.getResultSet(); 27 rs.next(); 28 Reader reader = rs.getCharacterStream(1); 29 30 char[] ch = new char[1024]; 31 int len = 0; 32 while ((len=reader.read(ch, 0, 1024))!=-1) { 33 fileWriter.write(ch, 0, len); 34 } 35 reader.close(); 36 fileWriter.close();
//先將一張圖片放入到數據庫中 String insertString = "insert into lobtest2 values(?,?);"; PreparedStatement prepareStatement = connection.prepareStatement(insertString) File file = new File("zixia.jpg"); FileInputStream fis= new FileInputStream(file); prepareStatement.setInt(1, 2); prepareStatement.setBinaryStream(2, fis,(int)file.length()); prepareStatement.execute(); //在從數據庫中讀出一張照片到文件中 String qureyString ="select context from lobtest2 where id = ?"; PreparedStatement prepareStatement = connection.prepareStatement(qureyString); prepareStatement.setInt(1, 2); prepareStatement.execute(); ResultSet resultSet = prepareStatement.getResultSet(); resultSet.next(); InputStream stream = resultSet.getBinaryStream(1); FileOutputStream fos = new FileOutputStream("mm.jpg"); byte[] b=new byte[1024]; int len=0; while ((len=stream.read(b, 0, 1024))!=-1) { fos.write(b, 0, len); } fos.close(); stream.close();
9、使用JDBC進行批處理:
業務場景:當需要向數據庫發送一批SQL語句執行時,應避免向數據庫一條條的發送執行,而應采用JDBC的批處理機制,以提升執行效率。要注意內存溢出問題。
1 conn = JdbcUtil.getConnection(); 2 String sql = "insert into user(name,password,email,birthday) values(?,?,?,?)"; 3 st = conn.prepareStatement(sql); 4 for(int i=0;i<50000;i++){ 5 st.setString(1, "aaa" + i); 6 st.setString(2, "123" + i); 7 st.setString(3, "aaa" + i + "@sina.com"); 8 st.setDate(4,new Date(1980, 10, 10)); 9 st.addBatch(); 10 if(i%1000==0){ 11 st.executeBatch(); 12 st.clearBatch(); 13 } 14 } 15 st.executeBatch();
優點:發送的是預編譯后的SQL語句,執行效率高。
缺點:只能應用在SQL語句相同,但參數不同的批處理中。因此此種形式的批處理經常用於在同一個表中批量插入數據,或批量更新表的數據
10、使用JDBC調用存儲過程:
1 CallableStatement cStmt = conn.prepareCall("{call demoSp(?, ?)}"); 2 cStmt.setString(1, "abcdefg"); 3 cStmt.registerOutParameter(2, Types.VARCHAR); 4 cStmt.execute(); 5 System.out.println(cStmt.getString(2));
