JDBC是一種數據庫鏈接,它是一種可執行SQL語句的Java API。程序能夠經過JDBC API鏈接到關係型數據庫,並使用結構化查詢語言來完成對數據庫的查詢,更新。經過使用JDBC,就可使用同一種API訪問不一樣的數據庫系統,開發人員面向JDBC API編寫應用程序,而後根據不一樣的數據庫,安裝不一樣數據庫的驅動程序便可。數據庫驅動程序是JDBC程序和數據庫之間的轉換層,數據庫驅動程序負責將JDBC調用映射成特定的數據庫調用。當須要鏈接某個特定的數據庫時,必須有相應的數據庫驅動程序。JDBC驅動的常見類型:直接與數據庫實例交互。這種驅動是智能的,它知道數據庫使用的底層協議。這種驅動避開了本地代碼,減小了應用開發的複雜性,也減小了產生衝突和出錯的可能性。java
程序可使用JDBC API以統一的方式來鏈接不一樣的數據庫,而後經過Statement對象來執行標準的SQL語句,並能夠得到SQL語句訪問數據庫的結果。經過使用JDBC,java程序能夠很是方便的操做各類主流數據庫,因爲java語言的跨平臺性,可使得JDBC編寫的程序不只能夠實現跨數據庫,還能夠垮平臺,具備很好的移植性。node
SQL是一種結構化查詢語言,是操做和檢索關係數據庫的標準語言。DML指數據庫操做語言,主要由insert 、update 和delete三個關鍵字完成。DDL是指數據定義語言,操做數據庫對象的語句,主要由create、alter、drop和Truncate四個關鍵字完成,最基本的數據庫對象是數據表,數據表表示存儲數據的邏輯單元。DCL指數據控制語言,主要由grant和revoke兩個關鍵字完成,DCL語句爲數據庫用戶受權,或收回指定用戶權限。mysql
Mysql數據庫通常的約束類型:not null;UNIQUE約束(當創建惟一約束時,Mysql在惟一約束所在列或列組合上創建對應的惟一索引)。Primary key:主鍵約束至關於非空約束和惟一約束的結合,每個表中最多容許有一個主鍵,但這個主鍵約束可由多個數據列組合而成。sql
FOREIGN KEY約束:主要用於保證一個或者兩個數據表之間的參照完整性,外鍵是構建於一個表的兩個字段或者兩個表的兩個字段之間的參照關係。當主表的記錄被從表記錄參照時,主表記錄不容許被刪除。必須先把從表裏全部參照該記錄的全部記錄所有刪除後,才能夠刪除主表的記錄。創建外鍵約束時,Mysql也會爲該列創建索引。外建約束一般用於定義兩個實體之間的一對一和一對多的關係。若是要使MySql中的外鍵約束生效,則應該使用表級約束語法。若是須要顯示地指定外鍵約束的名字,則可使用constraint來指定名字。數據庫
若是想定義刪除主表記錄時,從表記錄也會隨之刪除,則須要創建外鍵約束後添加 on delete cascade 或添加on delete set null,第一種是指刪除主表記錄時,參照主表記錄的從表記錄所有級聯刪除。第二種是指定當刪除主表記錄時,把參照該主表記錄的從表記錄設爲null編程
值得指出的是,外鍵約束不只能夠參照其餘表,並且能夠參照自身,這種參照自身的狀況一般被稱爲自關聯。併發
索引:索引是存放在模式(schema)中的一個數據庫對象,雖然索引老是從屬於數據表,但它也和數據表同樣屬於數據庫對象。建立索引的惟一做用就是加快對錶的查詢,索引經過使用快速路徑訪問方法來快速定位數據,從而減小磁盤的I/O;oracle
建立索引的方法:函數
(1) 自動:當在表上定義主鍵約束,惟一約束和外檢約束時,自動建立索引;工具
(2 Create index…語句來建立索引。Create index index_name on
Table_name(column);
(3)Drop index來刪除索引;
數據庫維護索引須要必定的系統開銷,所以建立索引的時候要特別注意,通常對須要常常查詢的表字段建立索引。
注意:delete from語句能夠一次刪除多行,採用where子句來限定。
Select 查詢時,後面不只能夠是數據列,也能夠是表達式,還能夠是變量,常量等。對於Mysql而言,若是算術表達式中出現null,將會致使整個算術表達式的返回值爲null;所以可使用以下方法,將爲null的記錄設爲0,來進行算術運算:
Select avg(ifnull(java_teacher,0)) fromstudent_table;
注意:
若是須要對分組進行過濾,則應該使用having子句。Having子句和where有些區別:
不能在where子句中過濾組,where子句僅用於過濾行。過濾組必須用having子句;
不能在where子句中使用函數,having子句纔可使用函數。
以下語句:
Select* from student_table group by java_teacher having count(*)>2;
外鏈接: 所謂外鏈接就是在鏈接條件的列名後增長括號包起來的外鏈接符,當外鏈接符出如今左邊時稱爲左外鏈接,java培訓,出如今右邊時稱爲右外鏈接。外鏈接就是在外鏈接符所在的表中增長一個「萬能行」,這行記錄的全部數據都是null,並且該行能夠與另外一個表中不知足條件的記錄進行匹配,經過這種方式就能夠把另外一個表中的全部記錄選出來,無論這些記錄是否知足鏈接條件。
所謂自鏈接就是把一個表當成兩個表來用,這就須要爲一個表起兩個別名,並且查詢中用的全部數據列都要加表別名前綴,由於兩個表的數據列徹底同樣。
左,右,全外鏈接:這三種分別使用left join,right join和full join,這三種外鏈接的鏈接條件同樣經過on 子句來指定,既能夠是等值鏈接條件,也能夠是非等值鏈接條件。Sql99左外鏈接將會把左邊表中全部不知足鏈接條件的記錄所有列出,右外鏈接會把右邊不知足鏈接條件的記錄所有列出。全外鏈接會把兩個表中全部不知足鏈接條件的記錄所有列出。
JDBC的典型用法
DriverManager:用於管理JDBC的驅動服務類,經過使用該類來獲取Connection 對象。Connection :表明數據庫鏈接對象,每一個Connection表明一個物理連結會話。Statement:用於執行SQL語句的工具接口。該對象能夠執行DDL和DML語句。PreparedStatement :預編譯的Statement對象。該方法返回預編譯的Statement對象,即將SQL語句提交到數據庫進行預編譯。它容許數據庫預編譯SQL語句,之後每次改變SQL命定的參數,避免數據庫每次都要編譯SQL語句,所以性能更好。相對statement而言,它執行SQL語句時,無需再傳入sql語句,只要爲預編譯的SQL語句傳入參數便可。ResultSet:結果集對象。
JDBC編程的通常步驟:
(1) 加載數據庫驅動
Class.forName(driverClass)
Class.forName(「com.mysql.jdbc.Driver」);//加載mysql的驅動代碼:
Class.forName(「oracle.jdbc.driver.oracleDriver」);//加載oracle的驅動代碼
(2) 經過DriverManager獲取數據庫鏈接。
DriverManager.getConnection(String url,String user,String pass);//MySql的URL寫法以下:jdbc:mysql://hostname:port/databasename;
使用PreparedStatement相對於Statement來講,除了能提升執行效率外,還有一個優點,當SQL語句中要使用參數時,無需拼接sql字符串,使用PreparedStatement則只須要使用問號佔位符來替代這些參數便可,下降了編程的複雜度,另外還有一個好處---用於防止SQL注入,基本上北京java培訓機構裏面都會講這個東西。
好比以下validate()方法使用PreparedStatement來執行驗證:
Private Boolean validate(String username,String userpass){
try{
Connection conn=DriverManager.getConnection(url,user,pass);
PreparedStatement pstmt=conn.prepareStatement(
「select * from jdbc_test where jdbc_name=?and jdbc_desc=?」))
{
psmt.setString(1,username);
psmt.setString(2,password);
try(
ResultSet rs=pstmt.executeUpdate())
{
if(rs.next()){
return true;
}
}
Catch(Exceptione){
e.printStackTrace();
}
Returnfalse;
}
Blob:是二進制長對象的意思,一般用於存儲大文件。典型的Blob內容是一張圖片或者聲音文件。
可使用CachedRowSet實現分頁。
Mysql中的事物處理:
事物是由一步或幾步數據庫操做序列所組成的邏輯執行單元,這些系列操做要麼所有執行,要麼所有放棄,通常而言,一段程序中可能包含多個事務。對於任何數據庫而言,事物都是很是重要的,事務是保證底層數據完整的主要手段,沒有事物支持的數據庫應用,那將很是脆弱。
事物具有四個特性:
原子性:事物是程序中最小的執行單元,不可再分。
一致性:事物執行的結果,必須使數據庫從一個一致性狀態,變到另外一個一致性狀態。
隔離性:各個事物的執行互不干擾,任意一個事物的內部操做對其它併發的事務都是隔離的。
持續性:指事務一旦提交,對數據所作的任何改變都要記錄到永久存儲器中。一般就是保存進物理數據庫中;
這幾個特性簡稱爲ACID性。
Mysql默認關閉事務(即打開自動提交),爲了開啓Mysql事務,能夠顯示調用以下命定:set AUTOCOMMIT={0|1} ,0爲關閉自動提交。自動提交和開啓事務正好相反,若是開啓自動提交就是關閉事務,關閉自動提交就是開啓事務。
提交,不論是顯示提交仍是隱示提交,都會結束當前事務;回滾,不論是顯示回滾仍是隱式回滾,都會結束當前事務。
能夠調用Connection提供的setAutoCommit()方法來關閉自動提交,開啓事務。如:conn.setAutoCommit(false);
若是全部的sql語句都執行成功,程序能夠調用conn.commit()語法來提交事務。若是任意一條sql語句執行失敗,則經過 conn.rollback()方法來回滾事務。
大部分時候,只須要對指定的數據表進行插入(C),查詢(R),修改(U),刪除(D)等CRUD操做。在sql裏的模式字符串,用百分號(%)表示任意多個字符,使用下劃線(_)表明一個字符。
使用鏈接池管理鏈接:
數據庫的鏈接的創建和關閉是很消耗系統資源的操做,頻繁的打開關閉鏈接將致使系統性能低下。數據庫鏈接池的解決方案是:當應用程序啓動時,系統自動創建足夠的數據庫鏈接,並將這些鏈接組成一個鏈接池,每次應用程序請求數據庫鏈接時,無須從新打開鏈接,而是從鏈接池中取出已有的鏈接使用,使用完後再也不關閉數據庫鏈接,而是直接將鏈接歸還給鏈接池,這樣能夠極大的提升程序的運行效率。
在多個鏈接池程序裏,相比之下,C3P0的性能更好,它不只能夠自動清理再也不使用的Connection,還能夠自動清理Statement和ResultSet對象。
(1)C3P0鏈接池的操做實例以下:
publicclass C3P0Test{
public static void main(String[] args) {
Connection conn=null;
PreparedStatement pstm=null;
ResultSet rs=null;
ComboPooledDataSource cpds=new ComboPooledDataSource();
try{
conn=cpds.getConnection();
pstm=conn.prepareStatement("select * from account wherename=?");
pstm.setString(1, "a");
rs=pstm.executeQuery();
rs.next();
System.out.println(rs.getDouble("money"));
}catch(Exception e){
e.printStackTrace();
}finally{
JDBCUtils.close(conn, pstm,rs);
}
}
}
(2)JDBC還提供了一個批量更新的功能,使用批量更新時,多條sql語句將被做爲一批操做被同時收集,並同時提交。以下實例:
public class StatementBatchTest {
publicstaticvoid main(String[] args) {
Connection conn=null;
Statement stat=null;
ResultSet rs=null;
try{
conn=JDBCUtils.getConnection();
stat=conn.createStatement();
stat.addBatch("create databasedb_batch");
stat.addBatch("use db_batch");
stat.addBatch("create table tb_batch"+"(id int primary key auto_increment, name varchar(20))");
stat.addBatch("insert into tb_batchvalues(null,'a')");
stat.addBatch("insert into tb_batchvalues(null,'b')");
stat.addBatch("insert into tb_batchvalues(null,'c')");
stat.addBatch("insert into tb_batchvalues(null,'d')");
stat.executeBatch();
System.out.println("執行成功");
}catch(Exception e){
e.printStackTrace();
}finally{
JDBCUtils.close(conn, stat,rs);
}
}
}
(3)在preparedStatement中進行批量更新的例子以下:
publicclass PreparedStatementBatch {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
// conn =JDBCUtils.getConnection();
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql:///db_batch","root", "root");
ps = conn.prepareStatement("insert into tb_batch values(null, ?)");
for(int i=0; i<10000; i++){
ps.setString(1, "name"+i);
ps.addBatch();
}
ps.executeBatch();
System.out.println("執行成功~!");
} catch (Exception e) {
e.printStackTrace();
}finally{
if(rs != null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}finally{
rs = null;
}
}
if(ps != null){
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}finally{
ps = null;
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}finally{
conn = null;
}
}
}
}
}
(4)翻頁是JDBC中的經常使用技術,本代碼中利用執行計劃處理分頁,數據庫的鏈接和關閉用已經另一個類DBUtil實現,代碼以下:
public class PageDemo {
public static void main(String[] args) {
PageDemo demo = new PageDemo();
demo.printPage(5, 3);
}
public void printPage(int pageSize,int page){
int begin = (page - 1)*pageSize + 1;
int end = page*pageSize ;
String query = "select * from dept";
String sql = "select * from (select a.*, rownum rn from ("+query+")a where rownum<= ?) where rn>= ?";
System.out.println(sql);
Connection conn = null;
try {
conn = DBUtil.getConnection();
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1, end);
ps.setInt(2, begin);
ResultSet rs = ps.executeQuery();
while(rs.next()){
System.out.println(rs.getString("dname"));
}
rs.close();
ps.close();
}catch(Exception e){
e.printStackTrace();
}finally{
DBUtil.close(conn);
}
}
}