JDBC全稱爲:Java Data Base Connectivity(java數據庫鏈接),它主要由接口組成java
JDBC原理:其實就是一組規範(就是對類的規範,也就是接口),各大數據庫廠商對其實現
這些所說的驅動類也就是JDBC的實現
可是官方的實現並非特別完整(畢竟免費),存在第三方的實現mysql
查看鏈接的幾句代碼,彷佛並無什麼緊密聯繫。第一句的Class.forName() 註冊驅動
看下面的另外的相同效果的代碼
com.mysql.jdbc.Driver driver = new com.mysql.jdbc.Driver()
DriverManager.registerDriver(driver);sql
看源碼能夠清晰發現原理再去源碼裏面的靜態塊(在類加載的時候執行)
JDBC4.0以後DriverManager.getCoonection()會自動加載驅動類,
但爲了兼容老版本,建議寫Class.forName();數據庫
對於鏈接JDBC我也只是略懂而已,如下是我寫的代碼,順便告訴你一個小竅門:apache
「賈璉欲執事」,數組
意思就是加載驅動,鏈接數據庫,建立須要的SQL語句,執行語句,釋放連接。服務器
package com.mysql.test; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import org.junit.Test; public class Demo01 { @Test public void test1() throws SQLException, ClassNotFoundException{ //加載驅動類,新特性已經免去此特性 //Class.forName("com.mysql.jdbc.Driver");嚴重不建議使用registerDriver
String url = "jdbc:mysql://localhost:3306/mydb"; String username = "root"; String password = "root"; Connection con = DriverManager.getConnection(url,username,password); Statement stmt =con.createStatement(); String sql = "INSERT INTO ab VALUES(6,'測試JDBC')";//語句不要加分號
int i =stmt.executeUpdate(sql);//完成DML,即增刪改操做
System.out.println(i); } @Test public void test2() throws SQLException, ClassNotFoundException{ //加載驅動類,新特性已經免去此特性,固然不建議省略 //Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/mydb"; String username = "root"; String password = "root"; Connection con = DriverManager.getConnection(url,username,password); Statement stmt =con.createStatement(); String sql = "SELECT * FROM stu";//語句不要加分號
ResultSet rs = stmt.executeQuery(sql); int count = rs.getMetaData().getColumnCount(); while(rs.next()){ for(int i=1;i<=count;i++){ System.out.print(rs.getString(i)); } System.out.println(); } //不關各類軟病(時好時壞)
rs.close(); stmt.close(); con.close(); } }
結果集的操做:
默認的結果集是不可滾動的,不能執行上一行,下N行等操做,即forward_only(小卒只能向前拱)
光標有第0行和結果集最後一行後一行的位置。
【!】默認返回的結果集的光標在beforeFirst上,須要用next()方法來進行移動
相關滾動的方法查看SE的ResultSet()裏的滾動方法
獲取結果集元數據
re.getMetaData(),返回ResultMetaData(),使用相關get方法,獲得多少行,多少列等
int count = rs.getMetaData().getColumnCount();
while(rs.next()){
for(int i = 1;i<=count;i++){
syso(rs.getString(i));//均可以轉爲String ,固然這裏寫getObject()也是能夠得
}
}函數
ResultSet還提供了對結果集進行滾動的方法:(更詳盡的方法請查閱API)工具
結果集的特性:【瞭解】 平時用的多的都是相似於照片,拿完就走
*是否可滾動
*是否敏感[通常不敏感]
*是否可更新測試
在createStatement獲得Statement的時候就已經決定
默認空參數(整型參數)時三特性爲否,詳細看SE文檔,
!固然【MySQL特性有可滾動】,正常都是forward_only
最後,咱們提取出一個工具類 JdbcUtils:
前提工具是驅動包以及配置文件:
配置文件信息較簡單:
而後就能夠提取出這個類:
package com.jdbc.utils; import java.io.IOException; import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Properties; /** * 鏈接數據庫工具類 * 考慮到換別的數據庫,使用四大參數進行傳遞 * 注意在配置文件中更改參數再加載便可鏈接其它數據庫 * @author jiangbei01 * */
public class JdbcUtils { //有錯,待改進 //改進後配置文件只加載一次
private static Properties props = null; static { try{ //加載配置文件中的四大參數
InputStream in = JdbcUtils.class.getClassLoader() .getResourceAsStream("dbconfig.properties"); props = new Properties(); props.load(in); }catch(IOException e){ throw new RuntimeException(e); } try { //加載驅動類,經過鍵獲得值得方式
Class.forName(props.getProperty("driverClassName")); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } } public static Connection getConnection() throws SQLException{ /* String url = "jdbc:mysql://localhost:3306/mydb"; String username = "root"; String password = "root";*/
//獲得conn
return DriverManager.getConnection(props.getProperty("url"), props.getProperty("username"), props.getProperty("password")); } }
是Statement的子接口。
前提是都支持PreparedStatement:固然主流數據庫都支持
使用方法:
1.給出SQL模板(參數有?給出,?只能做爲參數不參與SQL語句的構成)
2.使用con的preparedStatement()方法
3.使用pstmt.setXXX方法爲參數幅值
更增強大:
1.防SQL攻擊
' a' or 'a'='a'等SQL語句(打出來便可知道,能夠知道)
固然,這不是PreparedStatement的主要功能,能夠簡單簡單校驗等便可防止非法語句
2.提升代碼的可讀性,可維護性
3.效率更高
(加``避開關鍵字)
原理:
服務器的工做: 校驗SQL語句的語法(工做量大!吃魚的時候挑刺的時間多)
編譯:一個與函數類似的東西
執行:相似調用函數
每一個pstmt都與一個SQL模板校驗,先校驗,把SQL模板給服務器,編譯,執行時把參數給他
二次執行時直接給參數就行
【注意】MySQL預編譯默認是關閉的
給出一個連接的小例子:
package com.mysql.test; import java.io.IOException; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import org.junit.Test; import com.jdbc.utils.JdbcUtils; /** * 測試PreparedStatement * @author jiangbei01 * */
public class Demo02 { @Test public void fun1(){ //準備四大參數
String driverclassName = "com.mysql.jdbc.Driver"; String url = "jdbc:mysql://localhost:3306/mydb"; String username = "root"; String password = "root"; Connection con = null; PreparedStatement pstmt = null; ResultSet rs = null; try { //加載驅動,(能夠省略,可是不建議省略)
Class.forName(driverclassName); //獲得鏈接
con = DriverManager.getConnection(url, username, password); //給出SQL模板,得到preparedStatement
String sql = "SELECT * FROM ab WHERE aid=?"; pstmt = con.prepareStatement(sql); //調用方法,執行查詢語句
pstmt.setInt(1, 1); rs = pstmt.executeQuery();//方法都無參,前面都給過了
System.out.println(sql); if(rs.next()){ System.out.println(rs.getString(2));} } catch (SQLException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } finally{ //關閉資源
if(rs != null) try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } if(pstmt != null) try { pstmt.close(); } catch (SQLException e) { e.printStackTrace(); } if(con != null) try { con.close(); } catch (SQLException e) { e.printStackTrace(); } } } /** * 測試本身寫的工具類JdbcUtils * @throws SQLException * @throws IOException * @throws ClassNotFoundException */ @Test public void fun2() throws SQLException{ Connection con = JdbcUtils.getConnection(); System.out.println(con); } }
大數據也稱之爲LOB(Large Objects),LOB又分爲:clob和blob,clob用於存儲大文本,blob用於存儲二進制數據,例如圖像、聲音、二進制文等。
在實際開發中,有時是須要用程序把大文本或二進制數據直接保存到數據庫中進行儲存的。
對MySQL而言只有blob,而沒有clob,mysql存儲大文本採用的是Text,Text和blob分別又分爲:
TINYTEXT、TEXT、MEDIUMTEXT和LONGTEXT
TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB
給出一個小例子:
package com.mysql.test; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.sql.Blob; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import javax.sql.rowset.serial.SerialBlob; import org.apache.commons.io.IOUtils; import org.junit.Test; import com.jdbc.utils.JdbcUtils; public class Demo03 { /** * 測試存儲大數據 * @throws SQLException * @throws IOException * @throws FileNotFoundException */ @Test public void fun1() throws Exception{ //獲得鏈接
Connection con = JdbcUtils.getConnection(); //準備模板
String sql = "INSERT INTO file VALUES(?,?,?)"; //獲得pstmt
PreparedStatement pstmt = con.prepareStatement(sql); //設置模板中的參數,進行執行
pstmt.setInt(1, 1); pstmt.setString(2, "晴天.mp3"); //問題是變blob,思路是文件變字節數組bytes[] 注意使用IO包
byte[] bytes = IOUtils.toByteArray(new FileInputStream("F:/晴天.mp3")); Blob blob = new SerialBlob(bytes); pstmt.setBlob(3, blob); pstmt.executeUpdate(); } /** * 從數據庫中讀取mp3 * @throws Exception */ @Test public void fun2() throws Exception{ //獲得鏈接
Connection con = JdbcUtils.getConnection(); //給出模板
String sql = "SELECT * FROM file"; //獲得pstmt
PreparedStatement pstmt = con.prepareStatement(sql); //無參數,不設置
ResultSet rs = pstmt.executeQuery(); //移動光標,查詢數據
if(rs.next()){ Blob blob = rs.getBlob(3); //轉爲輸入流,再利用文件複製
InputStream in = blob.getBinaryStream(); OutputStream out = new FileOutputStream("F:/1.mp3"); IOUtils.copy(in, out); } } }