一、JDBC
創(chuàng)新互聯(lián)公司從2013年創(chuàng)立,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站制作網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個(gè)夢(mèng)想脫穎而出為使命,1280元華池做網(wǎng)站,已為上家服務(wù),為華池各地企業(yè)和個(gè)人服務(wù),聯(lián)系電話:18980820575
一、JDBC概述
JDBC和ODBC都基于一個(gè)思想:根據(jù)API編寫的程序都可以與驅(qū)動(dòng)管理器進(jìn)行通信,而驅(qū)動(dòng)管理器則通過驅(qū)動(dòng)程序和實(shí)際的數(shù)據(jù)庫(kù)進(jìn)行通信。
在三層應(yīng)用模式中,客戶端不直接調(diào)用數(shù)據(jù)庫(kù),而是調(diào)用 二、執(zhí)行SQL語句 創(chuàng)建Statement對(duì)象 Statement st = conn.createStatement(); 調(diào)用Statement接口executeUpdate方法st.executeUpdate(sql); 1】此方法返回受SQL命令影響的行數(shù),或者如果沒影響即返回0. 2】此方法可以執(zhí)行INSERT、UPDATE、DELETE、CREATE、TABLE、DROP.但是不可以執(zhí)行SELECT查詢 execute方法可以執(zhí)行任意的SQL語句。 executeQuery方法可以執(zhí)行查詢操作,返回一個(gè)ResultSet類型的對(duì)象。 ResultSet rs = st.executeQuery("SELECT * from table"); while(re.next()){ System.out.println("ID:"+rs.getInt("ID")+"name :"+rs.getString(2)); } rs代表一行,通過數(shù)字型參數(shù)和字符串參數(shù)可以獲得到數(shù)據(jù)。索引是從1開始 5.每個(gè)Connection對(duì)象都可以創(chuàng)建一個(gè)或多個(gè)Statement對(duì)象。同一個(gè)Statement對(duì)象可以用于多個(gè)不相干的命令和查詢,但是一個(gè)Statement對(duì)象最多只能有一個(gè)打開的結(jié)果集。 三、執(zhí)行查詢操作 預(yù)備語句 變量用?來表示,通過setXXX來對(duì)變量賦值。如果是查詢那就調(diào)用pstmt.executeQuery();得到一個(gè)ResultSet 2.讀寫LOB: 數(shù)據(jù)庫(kù)還可以存儲(chǔ)大對(duì)象,二進(jìn)制大對(duì)象成為BLOB,字符型大對(duì)象成為CLOB。 四、可滾動(dòng)和可更新的結(jié)果集 1.設(shè)置 要讓ResultSet可以滾動(dòng)個(gè)和更新,必須在創(chuàng)建Statement對(duì)象的時(shí)候使用下面的方式指定對(duì)應(yīng)的參數(shù): Statement stmt = conn.createStatement(type, concurrency); 對(duì)于PreparedStatement,使用下面的方式指定參數(shù): PreparedStatement pstmt = conn.prepareStatement(sql, type, concurrency); 其中,type表示ResuleSet的類型,而concurrency表示是否可以使用ResuleSet來更新數(shù)據(jù)庫(kù)。 type和concurrency的取值以及含義: ResultSet.TYPE_FORWARD_ONLY - 結(jié)果集不能滾動(dòng),這事默認(rèn)值; ResultSet.TYPE_SCROLL_INSENSITIVE - 結(jié)果集可以滾動(dòng),但ResuleSet對(duì)數(shù)據(jù)庫(kù)中發(fā)送的數(shù)據(jù)改變不敏感; ResultSet.TYPE_SCROLL_SENSITIVE - 結(jié)果集可以滾動(dòng),并且ResuleSet對(duì)數(shù)據(jù)庫(kù)中發(fā)生的改變敏感 ResultSet.CONCUR_READ_ONLY - 只讀結(jié)果集,不能用于更新數(shù)據(jù)庫(kù); ResultSet.CONCUR_UPDATABLE - 可更新結(jié)果集,可以用于更新數(shù)據(jù)庫(kù); 當(dāng)使用TYPE_SCROLL_INSENSITIVE或者TYPE_SCROLL_SENSITIVE來創(chuàng)建Statement對(duì)象時(shí),可以使用ResultSet 的 first()/last()/beforeFirst()/afterLast()/relative()/absolute()等方法在結(jié)果集中隨意前后移動(dòng)。 提示:即使使用了CONCUR_UPDATABLE參數(shù)來創(chuàng)建Statement,得到的記錄集也并非一定是“可更新的”,如果你的記錄集來自于合并查詢,即該查詢的結(jié)果來自多個(gè)表格,那么這樣的結(jié)果集就可能不是可更新的結(jié)果集??梢允褂肦esuleSet類的getConcurrency()方法來確定是否為可更新的的結(jié)果集。 如果結(jié)果集是可更新的,那么可使用ResultSet的updateRow(),insertRow(),moveToCurrentRow(),deleteRow(),cancelRowUpdates() 等方法來對(duì)數(shù)據(jù)庫(kù)進(jìn)行更新。 如果沒有設(shè)置可更新結(jié)果集 那將抱com.microsoft.sqlserver.jdbc.SQLServerException: 結(jié)果集不可更新 【方法】 next(),使游標(biāo)向下一條記錄移動(dòng)。 previous() ,使游標(biāo)上一條記錄移動(dòng),前提前面還有記錄。 absolute(int row),可以使用此方法跳到指定的記錄位置。定位成功返回true, 不成功返回false,返回值為false,則游標(biāo)不會(huì)移動(dòng)。 afterLast() ,游標(biāo)跳到最后一條記錄之后。 beforeFirst() ,游標(biāo)跳到第一條記錄之前。(跳到游標(biāo)初始位) first(),游標(biāo)指向第一條記錄。 last(),游標(biāo)指向最后一條記錄。 relative(int rows) ,相對(duì)定位方法,參數(shù)值可正可負(fù),參數(shù)為正,游標(biāo)從當(dāng)前位置向下移動(dòng)指定值,參數(shù)為負(fù), 游標(biāo)從當(dāng)前位置向上移動(dòng)指定值。 2.更新 【1】Statement stm = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE); 這樣調(diào)用executeQuery得到的結(jié)果集就是可更新的結(jié)果集 【2】插入新行: ResultSet結(jié)果集中,1.先使用moveToInsertRow(),將游標(biāo)移到和結(jié)果集結(jié)構(gòu)類似的緩沖區(qū)中 2.然后可以使用updateXxx(int column,columnType value)方法來更新指定列數(shù)據(jù), 3.再使用insertRow() 方法插入記錄, 4.最后將游標(biāo)指回原位,moveToCurrentRow() 。 rs.first(); //將光標(biāo)移動(dòng)到插入行上 rs.moveToInsertRow(); //構(gòu)建行數(shù)據(jù) rs.updateString(2, "xxxx"); rs.updateInt(3, "x"); //插入一行 rs.insertRow(); 五、行集 1)行集是從表格式數(shù)據(jù)源中檢索出來的一行或多行數(shù)據(jù): 與結(jié)果集(ResultSet)類似(RowSet接口繼承了ResultSet接口) 但是使用結(jié)果集時(shí)與數(shù)據(jù)庫(kù)的連接不能斷開,而行集是可以在關(guān)閉連接的情況下存在的,行集一般在關(guān)閉連接的情況下使用,只有在進(jìn)行一些特殊操作時(shí)需要才建立連接。 2)行集中的數(shù)據(jù)來源: 使用JDBC驅(qū)動(dòng)程序從數(shù)據(jù)庫(kù)檢索的數(shù)據(jù)、從其他數(shù)據(jù)源獲得的數(shù)據(jù),如文件數(shù)據(jù) 行集(Row Set)的優(yōu)點(diǎn): 1)可以斷開數(shù)據(jù)庫(kù)連接操作數(shù)據(jù) 2)可以在分布式系統(tǒng)中的不同組件之間傳遞 3)默認(rèn)可更新,可滾動(dòng),可序列化,可以方便的在網(wǎng)絡(luò)間傳輸 4)可以方便的使數(shù)據(jù)在行集與JavaBean對(duì)象之間進(jìn)行轉(zhuǎn)換 行集中的一行數(shù)據(jù)可以封裝為一個(gè)JavaBean對(duì)象 JavaBean是一個(gè)類,類中有若干私有屬性,然后有與屬性相關(guān)的公有的get和set方法。這樣,我們可以將一行數(shù)據(jù)存入一個(gè)JavaBean對(duì)象中 行集相關(guān)接口: javax.sql.RowSet:所有行集的父接口 行集的填充: 1)傳統(tǒng)JDBC方式 2)設(shè)置行集屬性連接數(shù)據(jù)庫(kù)并檢索數(shù)據(jù) ------------------------------------------------------------------------------------------------------------------------------- RowSet的使用: 1、以下行集類使用Java的默認(rèn)實(shí)現(xiàn)類 2、更新CachedRow數(shù)據(jù)(conn.setAutoCommit(false);) 使用行集修改數(shù)據(jù)與行集中的數(shù)據(jù)填充方式無關(guān)。但是要保證acceptChanges()方法執(zhí)行時(shí)有可用的連接對(duì)象,如果行集中有可用的連接對(duì)象可以調(diào)用acceptChanges(),如果行集中沒有可用的連接對(duì)象,需要調(diào)用acceptChanges(Connection)方法。 使用行集對(duì)數(shù)據(jù)進(jìn)行添加、修改、刪除時(shí),必須保證事務(wù)提交為非自動(dòng)提交(acceptChanges()方法會(huì)調(diào)用commit()方法)。 3、添加數(shù)據(jù) //刪除數(shù)據(jù) 4、分頁1:使用結(jié)果集填充行集 此時(shí)resultset,statement(preparedstatement),connection不能關(guān)閉,否則行集無法取得后續(xù)頁數(shù)據(jù) 5、分頁2:行集建立連接從數(shù)據(jù)庫(kù)讀取數(shù)據(jù) 六、事務(wù)和元數(shù)據(jù) 事務(wù)是指一個(gè)工作單元,它包含了一組添加,刪除,修改等數(shù)據(jù)操作命令,這組命令作為一個(gè)整體向系統(tǒng)提交執(zhí)行,要么都執(zhí)行成功,要么全部恢復(fù) 在JDBC中使用事務(wù) 1)con.setAutoCommit(false),取消自動(dòng)提交 2)對(duì)數(shù)據(jù)庫(kù)執(zhí)行一個(gè)或多個(gè)操作(一個(gè)或多個(gè)SQL語句) 3)con.commit(),提交事務(wù)(上面的第二部的多個(gè)操作就作為一個(gè)整體提交執(zhí)行) 4)如果某個(gè)操作失敗,通過con.rollback()回滾所有操作(撤銷以上的操作,將數(shù)據(jù)恢復(fù)為執(zhí)行前狀態(tài)) 事務(wù)處理依賴于底層的數(shù)據(jù)庫(kù)實(shí)現(xiàn),不同的驅(qū)動(dòng)程序?qū)κ聞?wù)處理的支持程度可能不同 【事務(wù)特性】 1.事務(wù)(Transaction)的四個(gè)屬性(ACID) 2.事務(wù)并發(fā)處理可能引起的問題 JDBC的事務(wù)支持 JDBC提供了5種不同的事務(wù)隔離級(jí)別,在Connection中進(jìn)行了定義。 2.事務(wù)隔離級(jí)別(Transaction Isolation Levels) 3.保存點(diǎn)(SavePoint) JDBC規(guī)范雖然定義了事務(wù)的以上支持行為,但是各個(gè)JDBC驅(qū)動(dòng),數(shù)據(jù)庫(kù)廠商對(duì)事務(wù)的支持程度可能各不相同。如果在程序中任意設(shè)置,可能得不到想要的效果。為此,JDBC提供了DatabaseMetaData接口,提供了一系列JDBC特性支持情況的獲取方法。比如,通過DatabaseMetaData.supportsTransactionIsolationLevel方法可以判斷對(duì)事務(wù)隔離級(jí)別的支持情況,通過DatabaseMetaData.supportsSavepoints方法可以判斷對(duì)保存點(diǎn)的支持情況。 語法 示例: String sql = "insert into students (Name,Sex,Age) values(?,?,?)";
PreparedStatement pstmt;
pstmt = (PreparedStatement)conn.prepareStatement(sql);//使用預(yù)處理的方式創(chuàng)建對(duì)象
pstmt.setString(1, student.getName());//第一個(gè)?號(hào)的內(nèi)容
pstmt.setInt(2, student.getSex());
pstmt.setDate(3, student.getAge());
int r = pstmt.executeUpdate();//執(zhí)行SQL 語句,更新數(shù)據(jù)庫(kù)
Java.sql.rowset.CachedRowSet:數(shù)據(jù)行容器,可以在內(nèi)存中緩存各行數(shù)據(jù),在對(duì)數(shù)據(jù)進(jìn)行操作時(shí)不需要連接到數(shù)據(jù)源??梢孕薷腃achedRowSet對(duì)象中的數(shù)據(jù),這些修改隨后可以被更新到數(shù)據(jù)庫(kù)。同時(shí),也是一個(gè)JavaBean組件,可滾動(dòng),可更新,可序列化。
java.sql.rowset.JDBCRowSet:數(shù)據(jù)行容器,可滾動(dòng),可更新。始終連接到數(shù)據(jù)庫(kù)。
java.sql.rowset.WebRowSet:被緩存的行集,該行集數(shù)據(jù)可以保存為xml文件。
java.sql.rowset.JoinRowSet:數(shù)據(jù)行容器,這些數(shù)據(jù)取自那些形成SQL JOIN關(guān)系的RowSet對(duì)象,有連接和無連接的RowSet對(duì)象都可成為JOIN的一部分。
java.sql.rowset.FilteredRowSet:數(shù)據(jù)行容器,可以對(duì)數(shù)據(jù)進(jìn)行條件過濾。
Class.forName(“com.mysql.jdbc.Driver”);
String connectionUrl = “jdbc:mysql://localhost:3306/test?user=root&password=root ";
Connection connection = DriverManager.getConnection(connectionUrl);
Statement statement = connection.createStatement();
ResultSet rs = statement.executeQuery(sql);
CachedRowSetImpl rowset = new CachedRowSetImpl();//得到行集
rowset.populate(rs);
rs.close(); statement.close();connection.close();
CachedRowSetImpl rowset = new CachedRowSetImpl();
rowset.setUrl(“jdbc:mysql://127.0.0.1:3306/test”);
rowset.setUsername(“root”);
rowset.setPassword(“test”);
rowset.setCommand(“select * from student”);
rowset.execute();
CachedRowSetImpl rowset = new CachedRowSetImpl();
//CachedRowSetImpl是SUN定義的CachedRow接口默認(rèn)實(shí)現(xiàn)類
Statement statement = connection.createStatement();
ResultSet rs = statement.executeQuery(“select * from table1”);
rowset.populate(rs); //填充行集
rs.close(); statement.close();connection.close(); //關(guān)閉連接
//顯示CachedRow數(shù)據(jù),使用從結(jié)果集繼承的方法
while (rowset.next()) {
System.out.print(rowset.getString(1) + " : "); System.out.println(rowset.getString("CompanyName"));
}
crs.last();
crs.updateShort(3, 58);
crs.updateInt(4, 150000);
crs.updateRow(); //更新行集
crs.acceptChanges(conn); //更新數(shù)據(jù)庫(kù)
注意事項(xiàng):
crs.setTableName(“student”); //添加數(shù)據(jù)必須指定
crs.moveToInsertRow(); //標(biāo)識(shí)指針的位置
crs.updateInt(“id”,33); //添加數(shù)據(jù)時(shí)主鍵必須指定
crs.updateString(“name", "Shakespeare");
crs.updateShort(“age", 58);
crs.insertRow(); //更新行集
crs.moveToCurrentRow(); //讓指針回到標(biāo)識(shí)的位置
crs.acceptChanges(conn); //更新數(shù)據(jù)庫(kù)
crs.first();
crs.deleteRow(); //刪除行集數(shù)據(jù)
crs.acceptChanges(conn); //更新數(shù)據(jù)庫(kù)
rs = stm.executeQuery(“select * from student”);
crs.setPageSize(4); //設(shè)置每頁行數(shù)
crs.populate(rs, 10); //從結(jié)果集的第十行開始取4行數(shù)據(jù)填充行集
…
crs.nextPage(); //獲得后續(xù)頁數(shù)據(jù),如果有數(shù)據(jù)返回true
…
注意:
CachedRowSetImpl crs= new CachedRowSetImpl();
crs.setUrl(“jdbc:mysql://127.0.0.1:3306/test”);
crs.setUsername(“root”);
crs.setPassword(“root”);
crs.setCommand(“select * from student”);
crs.setPageSize(4); //每頁行數(shù),一定要在execute()方法執(zhí)行前設(shè)置,否則無效
crs.execute();
……
crs.nextPage(); //獲得下一頁的數(shù)據(jù),與結(jié)果集,連接對(duì)象無關(guān)public class JDBC3 {
public static void main(String[] args) {
Connection conn=null;
PreparedStatement pst=null;
ResultSet rs=null;
DBUtil util=new DBUtil();
String sql="select*from score";
try {
conn=util.getConn();
pst=conn.prepareStatement(sql);
//必須設(shè)置非自動(dòng)提交
conn.setAutoCommit(false);
rs=pst.executeQuery();
//創(chuàng)建行集實(shí)例
CachedRowSetImpl rowset=new CachedRowSetImpl();
//填充
rowset.populate(rs);
rs.close();
pst.close();
rowset.absolute(5);
//rowset.updateInt("id", 5);
rowset.updateInt("English", 55);
//更新
rowset.updateRow();
//提交
rowset.acceptChanges(conn);
//輸出結(jié)果集之前,關(guān)閉連接
conn.close();
//輸出行集數(shù)據(jù)
System.out.println("id\tChinese\tEnglish\thistory");
while(rowset.next()){
System.out.print(rowset.getInt("id")+"\t");
System.out.print(rowset.getInt("Chinese")+"\t");
System.out.print(rowset.getInt("English")+"\t");
System.out.println(rowset.getInt("history"));
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public class JDBC4 {
public static void main(String[] args) {
try {
CachedRowSetImpl rowset=new CachedRowSetImpl();
rowset.setUrl("jdbc:mysql://localhost:3308/test");
rowset.setUsername("root");
rowset.setPassword("123456");
rowset.setCommand("select*from score;");
rowset.execute();
//輸出行集數(shù)據(jù)
System.out.println("id\tChinese\tEnglish\thistory");
while(rowset.next()){
System.out.print(rowset.getInt("id")+"\t");
System.out.print(rowset.getInt("Chinese")+"\t");
System.out.print(rowset.getInt("English")+"\t");
System.out.println(rowset.getInt("history"));
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public class JDBC6 {
public static void main(String[] args) {
try {
CachedRowSetImpl rowset=new CachedRowSetImpl();
rowset.setUrl("jdbc:mysql://localhost:3308/test");
rowset.setUsername("root");
rowset.setPassword("123456");
rowset.setCommand("select*from score;");
//設(shè)置每頁顯示的數(shù)據(jù)條數(shù)
rowset.setPageSize(3);
rowset.execute();
int i=2;
System.out.println("第1頁");
System.out.println("id\tChinese\tEnglish\thistory");
while(rowset.next()){
System.out.print(rowset.getInt("id")+"\t");
System.out.print(rowset.getInt("Chinese")+"\t");
System.out.print(rowset.getInt("English")+"\t");
System.out.println(rowset.getInt("history"));
}
while(rowset.nextPage()){
System.out.println("第"+i+"頁");
i++;
System.out.println("id\tChinese\tEnglish\thistory");
while(rowset.next()){
System.out.print(rowset.getInt("id")+"\t");
System.out.print(rowset.getInt("Chinese")+"\t");
System.out.print(rowset.getInt("English")+"\t");
System.out.println(rowset.getInt("history"));
}
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
原子性(Atomic) 對(duì)數(shù)據(jù)的修改要么全部執(zhí)行,要么全部不執(zhí)行。
一致性(Consistent) 在事務(wù)執(zhí)行前后,數(shù)據(jù)狀態(tài)保持一致性。
隔離性(Isolated) 一個(gè)事務(wù)的處理不能影響另一個(gè)事務(wù)的處理。
持續(xù)性(Durable) 事務(wù)處理結(jié)束,其效果在數(shù)據(jù)庫(kù)中持久化。
臟讀(dirty read) 一個(gè)事務(wù)讀取了另一個(gè)事務(wù)尚未提交的數(shù)據(jù),
不可重復(fù)讀(non-repeatable read) 一個(gè)事務(wù)的操作導(dǎo)致另一個(gè)事務(wù)前后兩次讀取到不同的數(shù)據(jù)
幻讀(phantom read) 一個(gè)事務(wù)的操作導(dǎo)致另一個(gè)事務(wù)前后兩次查詢的結(jié)果數(shù)據(jù)量不同。
舉例:
事務(wù)A、B并發(fā)執(zhí)行時(shí),
當(dāng)A事務(wù)update后,B事務(wù)select讀取到A尚未提交的數(shù)據(jù),此時(shí)A事務(wù)rollback,則B讀到的數(shù)據(jù)是無效的"臟"數(shù)據(jù)。
當(dāng)B事務(wù)select讀取數(shù)據(jù)后,A事務(wù)update操作更改B事務(wù)select到的數(shù)據(jù),此時(shí)B事務(wù)再次讀去該數(shù)據(jù),發(fā)現(xiàn)前后兩次的數(shù)據(jù)不一樣。
當(dāng)B事務(wù)select讀取數(shù)據(jù)后,A事務(wù)insert或delete了一條滿足A事務(wù)的select條件的記錄,此時(shí)B事務(wù)再次select,發(fā)現(xiàn)查詢到前次不存在的記錄("幻影"),或者前次的某個(gè)記錄不見了。
JDBC對(duì)事務(wù)的支持體現(xiàn)在三個(gè)方面:
1.自動(dòng)提交模式(Auto-commit mode)
Connection提供了一個(gè)auto-commit的屬性來指定事務(wù)何時(shí)結(jié)束。
a.當(dāng)auto-commit為true時(shí),當(dāng)每個(gè)獨(dú)立SQL操作的執(zhí)行完畢,事務(wù)立即自動(dòng)提交,也就是說每個(gè)SQL操作都是一個(gè)事務(wù)。
一個(gè)獨(dú)立SQL操作什么時(shí)候算執(zhí)行完畢,JDBC規(guī)范是這樣規(guī)定的:
對(duì)數(shù)據(jù)操作語言(DML,如insert,update,delete)和數(shù)據(jù)定義語言(如create,drop),語句一執(zhí)行完就視為執(zhí)行完畢。
對(duì)select語句,當(dāng)與它關(guān)聯(lián)的ResultSet對(duì)象關(guān)閉時(shí),視為執(zhí)行完畢。
對(duì)存儲(chǔ)過程或其他返回多個(gè)結(jié)果的語句,當(dāng)與它關(guān)聯(lián)的所有ResultSet對(duì)象全部關(guān)閉,所有update count(update,delete等語句操作影響的行數(shù))和output parameter(存儲(chǔ)過程的輸出參數(shù))都已經(jīng)獲取之后,視為執(zhí)行完畢。
b. 當(dāng)auto-commit為false時(shí),每個(gè)事務(wù)都必須顯示調(diào)用commit方法進(jìn)行提交,或者顯示調(diào)用rollback方法進(jìn)行回滾。auto-commit默認(rèn)為true。
JDBC定義了五種事務(wù)隔離級(jí)別:
TRANSACTION_NONE JDBC驅(qū)動(dòng)不支持事務(wù)
TRANSACTION_READ_UNCOMMITTED 允許臟讀、不可重復(fù)讀和幻讀。
TRANSACTION_READ_COMMITTED 禁止臟讀,但允許不可重復(fù)讀和幻讀。
TRANSACTION_REPEATABLE_READ 禁止臟讀和不可重復(fù)讀,單運(yùn)行幻讀。
TRANSACTION_SERIALIZABLE 禁止臟讀、不可重復(fù)讀和幻讀。
JDBC定義了SavePoint接口,提供在一個(gè)更細(xì)粒度的事務(wù)控制機(jī)制。當(dāng)設(shè)置了一個(gè)保存點(diǎn)后,可以rollback到該保存點(diǎn)處的狀態(tài),而不是rollback整個(gè)事務(wù)。
Connection接口的setSavepoint和releaseSavepoint方法可以設(shè)置和釋放保存點(diǎn)。Connection con = DriverManger.getConnection(urlString);
con.setAutoCommit(false);//取消自動(dòng)提交
Statement stm = con.createStatement();
stm.executeUpdate(sqlString);
con.transactionEndMethod; //事務(wù)方法成功則提交、失敗則回滾con.commit() or con.rollback();
try{
Class.forName(drv).newInstance();//加載驅(qū)動(dòng)
conn = DriverManager.getConnection(url,user,pwd);
conn.setAutoCommit(false);//禁止自動(dòng)提交
stmt = conn.createStatement();
//插入數(shù)據(jù)操作
stmt.executeUpdate("insert into(username,password,email) user values('admin','admin','admin@123.com')");
//更新數(shù)據(jù)操作
stmt.executeUpdate("update user set email='admin@163.com'");
//事務(wù)提交
conn.commit();
}catch(Exception ex){
try{
//如果失敗則事務(wù)回滾
conn.rollback();
}catch(Exception e){
e.printStackTrace();
}
}finally{
//關(guān)閉連接
if(conn != null){
try{
conn.close();
}catch(Exception e){
e.printStackTrace();
}
}
}
當(dāng)前名稱:JAVA基礎(chǔ)--JDBC
分享URL:http://weahome.cn/article/jigiog.html