麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

實(shí)體對(duì)象的抽象以及一種基于數(shù)據(jù)庫的實(shí)現(xiàn)

2019-11-18 14:27:20
字體:
供稿:網(wǎng)友

  作者:sure160
email: [email protected]

簡(jiǎn)介:本文探討了關(guān)系數(shù)據(jù)庫中的實(shí)體對(duì)象在面向?qū)ο笳Z言中如何抽象、實(shí)現(xiàn),并提出一種實(shí)現(xiàn)方案。
一、為什么要使用實(shí)體對(duì)象的概念
實(shí)體對(duì)象指的是可永久存儲(chǔ)的數(shù)據(jù)對(duì)象,通常可以用關(guān)系數(shù)據(jù)庫的一張數(shù)據(jù)表或一張主表和與之連接的幾張子表來表示。為什么要引入實(shí)體對(duì)象的概念呢?我可以肯定您是看過關(guān)于面向?qū)ο髢?yōu)點(diǎn)的長(zhǎng)篇大論的,不過我覺得有必要再嘮叨兩句,因?yàn)椴皇撬杏肅++或java編程的人都是使用面向?qū)ο蟮姆绞较雴栴}的。

在現(xiàn)實(shí)世界中,對(duì)象比它的屬性要穩(wěn)定,所以數(shù)據(jù)要抽象成對(duì)象。比如由于需求的修改,一個(gè)圖書治理系統(tǒng)要顯示更多的書目具體信息,圖書的屬性發(fā)生了變化,而圖書這個(gè)對(duì)象并沒有變,和其他對(duì)象(例如書架、借閱者)之間的關(guān)系也沒有變。用一個(gè)數(shù)據(jù)對(duì)象來保存書目信息的程序修改起來要簡(jiǎn)單的多。
把實(shí)體對(duì)象如何永久儲(chǔ)存的方法封裝到對(duì)象中可以實(shí)現(xiàn)使用對(duì)象的外部程序的與數(shù)據(jù)庫無關(guān),便于程序的移植。
在程序設(shè)計(jì)中使用實(shí)體對(duì)象概念把面向?qū)ο蠓治觥⒚嫦驅(qū)ο笤O(shè)計(jì)、面向?qū)ο缶幋a著幾個(gè)步驟連貫和一致。
可以減少外部程序中復(fù)雜性,使用這些實(shí)體對(duì)象的程序只需要簡(jiǎn)單的調(diào)用insert()或update()的方法,而不用去寫討厭的SQL語句。

但是,由于歷史原因,即使象Java這樣的新興語言,也沒有在所有地方完全利用面向?qū)ο蟮乃枷搿W屛覀兛纯碕DBC吧,這是一個(gè)號(hào)稱用對(duì)象封裝的數(shù)據(jù)庫接口。可是它封裝的是什么呢?連接、語句、結(jié)果集和存儲(chǔ)過程。這其實(shí)并不是我們?cè)O(shè)計(jì)系統(tǒng)所關(guān)心的東西,我們關(guān)心的是數(shù)據(jù)對(duì)象本身,而不是它從數(shù)據(jù)庫中提取的方法。當(dāng)然,JDBC本身也不該受到太多的指責(zé),因?yàn)樗緛淼哪繕?biāo)就是封裝、屏蔽關(guān)系型數(shù)據(jù)庫之間的差異,而不是企圖實(shí)現(xiàn)一個(gè)面向?qū)ο蟮臄?shù)據(jù)庫。

EJB第一次引起我的注重就是因?yàn)樗岢龅腅ntity Bean,也就是實(shí)體對(duì)象。它對(duì)實(shí)體對(duì)象提供了一套完整的實(shí)現(xiàn)思路,但是我認(rèn)為它太復(fù)雜了,主要原因是EJB想要做的事太多了。大部分情況下我并不需要分布式處理,我也不需要把實(shí)體對(duì)象存儲(chǔ)到文件中去。我需要的僅僅是在一個(gè)本地運(yùn)行的基于數(shù)據(jù)庫的程序。

二、EJB如何實(shí)現(xiàn)的實(shí)體對(duì)象
剛才提到了EJB已經(jīng)實(shí)現(xiàn)了實(shí)體對(duì)象,那么讓我們看看它是如何實(shí)現(xiàn)的。EJB中Entity Bean的對(duì)象實(shí)際上是對(duì)數(shù)據(jù)對(duì)象的一種完美的抽象,在這里我們幾乎看不到數(shù)據(jù)庫治理系統(tǒng)的作用。一個(gè)實(shí)體對(duì)象有幾種狀態(tài),在內(nèi)存中、在磁盤緩存中、或者在數(shù)據(jù)庫中,實(shí)體對(duì)象的這些狀態(tài)通常我們是不關(guān)心的,EJB的容器在必要的情況下會(huì)自動(dòng)轉(zhuǎn)換對(duì)象的狀態(tài),也就是說自動(dòng)把它存到數(shù)據(jù)庫中,或從數(shù)據(jù)庫中取出。我們要訪問一個(gè)數(shù)據(jù)對(duì)象,要向一個(gè)對(duì)象容器提出申請(qǐng),由它返回一個(gè)對(duì)象實(shí)例供我們使用。一個(gè)Entity Bean對(duì)應(yīng)于數(shù)據(jù)表中的一行。假如我們?cè)L問的是同一行數(shù)據(jù),對(duì)象容器返回的是不同的對(duì)象,但都指向同一個(gè)Entity Bean,并把我們所有的方法請(qǐng)求都發(fā)送給這個(gè)Entity Bean。實(shí)際上EntityBean的容器基本實(shí)現(xiàn)了一個(gè)面向?qū)ο蟮臄?shù)據(jù)庫。它這種實(shí)現(xiàn)方法帶來幾個(gè)顯著的問題:

運(yùn)行效率非常低。JAVA的速度慢是個(gè)老問題了,EJB的速度慢不光是因?yàn)榇罅看a用JAVA實(shí)現(xiàn),而且由于它的結(jié)構(gòu),要根據(jù)數(shù)據(jù)表中的某一個(gè)屬性查出一行數(shù)據(jù),必須首先用SQL查詢查找到這一行的主鍵(PRimary Key),然后通過主鍵來找到這個(gè)Bean,假如這個(gè)Bean不在內(nèi)存中--很不幸,這種情況經(jīng)常發(fā)生,那么實(shí)際上是執(zhí)行了兩次SQL查詢才找到一行數(shù)據(jù)。
容器本身要治理事務(wù),以防數(shù)據(jù)的污讀、污寫、死鎖等等一系列問題。本來DBMS治理這類問題已經(jīng)有很多年經(jīng)驗(yàn)了,已經(jīng)相當(dāng)完美的解決了這些問題,可是EJB不得不通過一個(gè)Transcation Server來治理這些問題。這使得容器的代碼變得極其復(fù)雜,另外編程人員也不得不重新熟悉這些接口。
由于bean 中的數(shù)據(jù)是否存儲(chǔ)在數(shù)據(jù)庫里是由容器治理的,那么其他程序訪問數(shù)據(jù)庫會(huì)帶來數(shù)據(jù)同步的問題。因此,在EJB架構(gòu)中,外部程序不能直接訪問數(shù)據(jù)庫,只能通過EJB訪問。

三、我們實(shí)現(xiàn)的目標(biāo)
我們只想把數(shù)據(jù)庫對(duì)象更好的封裝起來,為什么要購買別人昂貴的代碼?為什么要為我們不會(huì)用到的分布式去犧牲大量的性能。我們想要盡量使用DBMS的功能,以實(shí)現(xiàn)最佳的性能和最簡(jiǎn)化的代碼。

事務(wù)處理最好還是用DBMS來治理,因?yàn)樗幌蚬艿煤芎茫沂聞?wù)處理的代碼很復(fù)雜,我不打算自己來完成。

我不打算用同一個(gè)對(duì)象來指向數(shù)據(jù)庫的一行。數(shù)據(jù)庫的一行數(shù)據(jù)在程序中可能有多個(gè)對(duì)象,這些對(duì)象都應(yīng)該是臨時(shí)對(duì)象,而不是永久對(duì)象。他們的共享問題由DBMS本身加鎖來解決。

由于我們只是為訪問DBMS提供了一個(gè)接口,外部程序完全可以不通過這個(gè)接口來訪問數(shù)據(jù)庫。

實(shí)現(xiàn)后,使用實(shí)體對(duì)象的代碼要簡(jiǎn)單。例如,數(shù)據(jù)庫里有一個(gè)表account,它只有兩個(gè)字段accountid和name,我們把它作為一個(gè)實(shí)體對(duì)象Account,假設(shè)我們要完成從數(shù)據(jù)庫查詢、修改、插入,使用它的代碼片段如下:
Connection conn=ConnectionPool.getConn(); //也可以通過標(biāo)準(zhǔn)的DriverManager得到數(shù)據(jù)庫連接,這是完全一樣的

Conn.setAutoCommit(false); //假如不使用事務(wù),這一行可以省去

Account a1=new Account(conn);

a1.getByAccountId(1); //查找到相應(yīng)記錄

System.out.println(a1.name);

a1.getByAccountIdForUpdate(1); //假如企圖修改一個(gè)對(duì)象,必須通過forUpdate系列的方法得到這個(gè)對(duì)象

a1.name="new name";

a1.update(); //修改原有記錄

Account a2=new Account(conn);

a2.accountId=3;

a2.name="姚大";

a2.insert(); //插入一條新記錄

conn.commit();



實(shí)體對(duì)象的屬性通過方法修改是比較理想的方式,如用getName(),setName()兩個(gè)方法訪問Name屬性。這還可以解決屬性之間相互關(guān)聯(lián)的問題。例如,表中有一個(gè)地區(qū)代碼和地區(qū)名稱兩個(gè)域,必須保持一致,這就可以考慮在屬性設(shè)置方法中實(shí)現(xiàn)。在這里我們?yōu)榱撕?jiǎn)單,直接通過屬性修改,在一般情況下,我覺得也是可以接受到。

有一點(diǎn)必須注重的就是多線程程序所帶來的數(shù)據(jù)完整性問題。對(duì)于我們常使用的從數(shù)據(jù)庫讀取數(shù)據(jù)到對(duì)象中->修改對(duì)象屬性->更新到數(shù)據(jù)庫這個(gè)流程,非常輕易出現(xiàn)數(shù)據(jù)完整性破壞問題。比如一個(gè)進(jìn)程中甲對(duì)象讀取數(shù)據(jù)后,另一個(gè)進(jìn)程中乙對(duì)象又修改了同一數(shù)據(jù),這時(shí)甲對(duì)象再次更新數(shù)據(jù)庫會(huì)帶來污寫。解決的辦法是對(duì)象增加一個(gè)方法給數(shù)據(jù)庫的這條記錄加鎖。例如Account.getByAccountId函數(shù)改為Account.getByAccountIdForUpdate,這個(gè)函數(shù)中相應(yīng)的sql語句(Oracle數(shù)據(jù)庫)改為"select AccountId,name from account where accountId=? for update",這樣數(shù)據(jù)取出后就自動(dòng)加鎖,這個(gè)鎖將會(huì)在事務(wù)提交或回滾時(shí)釋放。for update在SQLServer相應(yīng)的語法為holdlock。

說到數(shù)據(jù)庫加鎖的問題就不能不考慮到數(shù)據(jù)庫死鎖的可能。想完全避免死鎖是很困難的,只有盡量降低這種可能性。方法是:1、盡量少使用forUpdate這種函數(shù),只有在更改數(shù)據(jù)庫數(shù)據(jù)時(shí)才使用。查詢的時(shí)候不要用,假如查詢后根據(jù)某個(gè)條件有可能修改,那么在查詢時(shí)不加鎖,在修改前重新調(diào)用forUpdate函數(shù)加鎖。2、盡量以某個(gè)特定的順序加鎖。例如有表A和表B,兩個(gè)程序都要同時(shí)更新這兩個(gè)表,最好都是先訪問表A,再訪問表B。

Oracle有個(gè)很好的功能就是自動(dòng)檢測(cè)死鎖。假如發(fā)生死鎖,會(huì)回滾一個(gè)事務(wù),并返回一個(gè)SQL錯(cuò)誤,我們的程序要檢測(cè)這個(gè)異常,處理程序中可能的錯(cuò)誤。

上面說到的對(duì)象中,只有g(shù)etByXXX()這樣的方法,這種方法只會(huì)返回唯一的對(duì)象,假如想要返回一組對(duì)象,這時(shí)需要一個(gè)輔助類來實(shí)現(xiàn)。這個(gè)輔助類稱為對(duì)象瀏覽器EntityBrowser。再實(shí)體對(duì)象中返回一個(gè)對(duì)象瀏覽器的方法一般命名為getAllByXXX()

使用對(duì)象瀏覽器EntityBrowser要列出所有account表中的id和name的代碼如下,其實(shí)這個(gè)對(duì)象瀏覽器和Java定義的Enumeration接口的最大區(qū)別就是它有一個(gè)close方法。請(qǐng)看下面的代碼片斷,它輸出所有的Accout對(duì)象。


Connection conn=ConnectionPool.getConn();

Account a1=new Account(conn);

EntityBrowser browser=a1.getAll();

System.out.println("==Account List==");

While (browser.hasMoreElement()) {

Account a=(Account)browser.nextElement();

System.out.print(a.accountId);

System.out.print("--");

System.out.println(a.name);

}

browser.close();



以上就是我們要實(shí)現(xiàn)的實(shí)體對(duì)象,下面介紹如何編寫一個(gè)實(shí)體對(duì)象。

四、實(shí)現(xiàn)的代碼解釋
首先,下面的代碼定義一個(gè)所有實(shí)體對(duì)象的基礎(chǔ)類EntityObject,這是一個(gè)抽象類,不能直接使用,但為其它實(shí)體對(duì)象定出了一個(gè)結(jié)構(gòu)。
Import java.sql.*;
/**所有實(shí)體對(duì)象基礎(chǔ)類*/
abstract public class EntityObject {
protected java.sql.Connection _conn;
private boolean _dbStored;
/**實(shí)體對(duì)象需要用一個(gè)數(shù)據(jù)庫連接初始化,這樣可以利用這個(gè)連接做事務(wù)提交或回滾*/
public EntityObject(Connection conn) {_conn=conn;_dbStored=false;}

/**這個(gè)方法用來插入新記錄,子類必須重定義這個(gè)方法*/
public void insert() throws SQLException{ _dbStored=true;}

/**這個(gè)方法用來修改數(shù)據(jù)庫原有記錄,子類必須重定義這個(gè)方法*/
public void update() throws SQLException {_dbStored=true; }

/**這個(gè)方法用來刪除數(shù)據(jù)庫原有記錄,子類必須重定義這個(gè)方法*/
public void delete() throws SQLException {_dbStored=false; }

/**這個(gè)方法用來把數(shù)據(jù)庫select語句得出的結(jié)果映射到對(duì)象的屬性中去,子類必須重定義這個(gè)方法*/
public void _setAttribute(ResultSet rs) throws SQLException {_dbStored=true; }

/**這個(gè)方法可以判定這個(gè)對(duì)象是否已存在數(shù)據(jù)庫中*/
public boolean isDbStored() {return _dbStored;}
/**這個(gè)方法將實(shí)體對(duì)象設(shè)為不存在數(shù)據(jù)庫中,所有的getByxxx()方法首先要調(diào)用這個(gè)方法,使本對(duì)象無效,才能用select語句得到符合條件的對(duì)象*/
public void clearDbStored() {_dbStored=false;}
}





下面我們就可以定義一個(gè)實(shí)際的實(shí)體類。考慮一種簡(jiǎn)單情況,實(shí)體對(duì)象在關(guān)系數(shù)據(jù)庫中只用一張表表示。這樣的實(shí)體對(duì)象定義最簡(jiǎn)單。例如,數(shù)據(jù)庫里有一個(gè)表account,它只有兩個(gè)字段accountid和name,下面定義它的實(shí)體類。實(shí)體類必須重載insert,update,_setAttribute方法,然后根據(jù)需要增加getByXXX()方法,根據(jù)某個(gè)屬性從數(shù)據(jù)庫查找一個(gè)對(duì)象。


Import java.sql.*;
public class Account extends EntityObject {
/*這里定義實(shí)體對(duì)象類所有的屬性*/
public int accountId;
public String name;
//最好將實(shí)體對(duì)象中的屬性全部定義成私有,然后定義getXXX(), setXXX()兩個(gè)方法來訪問這個(gè)屬性,這樣的封裝性最好,但略過于麻煩。假如數(shù)據(jù)結(jié)構(gòu)預(yù)料會(huì)經(jīng)常修改,最好用這個(gè)辦法。否則,定義成公有屬性也可。
Public Account(Connection conn){ super(conn); }
//重定義這個(gè)方法,執(zhí)行實(shí)際的sql命令
public void insert() throws SQLException {
PreparedStatement ps=_conn.prepareStatement ("insert into account(accountid,name) values(?,?)");
ps.setInt (1,accountId);
ps.setString (2,name);
ps.execute();
ps.close();
super.insert(); //注重,重載insert方法必須要有這一句
}
//重定義這個(gè)方法,執(zhí)行實(shí)際的sql命令
public void update() throws SQLException {
PreparedStatement ps=_conn.prepareStatement ("update account set accountid=?, name=? Where accountid=?");
ps.setInt(1,accountId);
ps.setString(2,name);
ps.setInt(3,accountId);
ps.execute();
ps.close();
super.update(); //注重,重載update方法必須要有這一句
}
//重定義這個(gè)方法,執(zhí)行實(shí)際的sql命令
public void delete() throws SQLException {
if (isDbStored()) {
PreparedStatement ps=_conn.prepareStatement("delete account where accountid = ? ");
ps.setInt(1,accountId);
ps.execute();
ps.close();
}
super.delete();
}
//下面這個(gè)方法把一個(gè)ResultSet轉(zhuǎn)換成對(duì)象中的屬性,下面所有的getByXXX方法都會(huì)用到這個(gè)方法。
public void _setAttribute(java.sql.ResultSet rs) throws SQLException {
accountId=rs.getInt(1);
name=rs.getString(2);
super._setAttribute(rs); //注重,重載_setAttribute方法必須要有這一句
}
//根據(jù)條件取得對(duì)象
public boolean getByAccountId(int id) throws SQLException {
clearDbStored();
PreparedStatement ps=_conn.prepareStatement ("select AccountId,Name from account where AccountId=?");
//這里的select語句得到的結(jié)果集必須與上面的_setAttribute方法假定的結(jié)果集一致
ps.setInt(1,id);
ResultSet rs=ps.executeQuery();
if (rs.next())
_setAttribute(rs);
rs.close();
ps.close();
return (isDbStored());
}
//根據(jù)條件取得對(duì)象并企圖修改
public boolean getByAccountIdForUpdate(int id) throws SQLException {
clearDbStored();
PreparedStatement ps=_conn.prepareStatement ("select AccountId,Name from account where AccountId=? for update");
ps.setInt(1,id);
ResultSet rs=ps.executeQuery();
if (rs.next())
_setAttribute(rs);
rs.close();
ps.close();
return (isDbStored());
}
}




上面說到的對(duì)象中,只有g(shù)etByXXX()這樣的方法,這種方法只會(huì)返回唯一的對(duì)象,這時(shí),也不用保存數(shù)據(jù)庫結(jié)果集,假如出現(xiàn)返回一組對(duì)象的情況,就不能不保存結(jié)果集了,這時(shí)需要一個(gè)輔助類來實(shí)現(xiàn)。這個(gè)輔助類稱為對(duì)象瀏覽器,下面定義對(duì)象瀏覽器。


import java.sql.*;
/**所有實(shí)體對(duì)象的瀏覽器的父類*/
abstract class EntityBrowser {
protected ResultSet _rs;
protected Connection _conn;
protected boolean _hasMoreElement;
/**瀏覽器是否還有下一個(gè)記錄*/
public boolean hasMoreElement() throws SQLException{
return _hasMoreElement;
}
/**返回下一個(gè)記錄,子類必須重載這個(gè)函數(shù)*/
abstract public Object nextElement() throws SQLException;
/**關(guān)閉這個(gè)瀏覽器*/
public void close () throws SQLException{
_rs.getStatement().close();
}
/**瀏覽器構(gòu)造函數(shù),指定一個(gè)數(shù)據(jù)庫連接*/
public EntityBrowser(ResultSet rs) throws SQLException {
_rs=rs;
_conn=_rs.getStatement().getConnection();
_hasMoreElement=_rs.next();
}
//子類重載nextElement()時(shí)調(diào)用這個(gè)方法
protected Object _nextEntityObj(EntityObject eo) throws SQLException {
if (_hasMoreElement) {
eo._setAttribute(_rs);
} else eo=null;
_hasMoreElement=_rs.next();
return (eo);
}
}




有了EntityBrowser類后,我們來修改剛才定義的Account類。第一步是要在Account類里定義一個(gè)私有的EntityBrowser子類,這個(gè)子類只要定義一個(gè)構(gòu)造函數(shù)并重載nextElement()方法即可。這里使用了在一個(gè)類里定義另一個(gè)類的技巧,這個(gè)技巧在java的容器類庫中經(jīng)常使用。第二步是在Account類中增加一個(gè)方法getAllByXX(),返回一組實(shí)體對(duì)象的方法名常用getAll打頭。請(qǐng)看以下修改的代碼片段。


import java.sql.*;
public class Account extends EntityObject {
。。。
/*以下是新修改的代碼*/
//定義一個(gè)子類
private class AccountBrowser extends EntityBrowser {
AccountBrowser (ResultSet rs) throws SQLException { super(rs); }
Public Object nextElement() throws SQLException{
Account ac=new Account(_conn);
return (_nextEntityObj(ac));
}
}
//下面是實(shí)體對(duì)象的方法
public EntityBrowser getAll() throws SQLException {
PreparedStatement ps=_conn.prepareStatement("select AccountId,Name from account ");
ResultSet rs=ps.executeQuery();
return (new AccountBrowser(rs));
}
public EntityBrowser getAllByName(String name) throws SQLException {
PreparedStatement ps=_conn.prepareStatement(“select AccountId,Name from account where name like ?”;
ps.setString(1,name);
ResultSet rs=ps.executeQuery();
return (new AccountBrowser(rs));
}




接下來,討論一下數(shù)據(jù)表的連接關(guān)系,關(guān)系數(shù)據(jù)庫主要有一對(duì)一,一對(duì)多,多對(duì)多,多對(duì)一的關(guān)系。比如教師和學(xué)生之間的教課關(guān)系,這是一種多對(duì)多的關(guān)系。有的關(guān)系是有自己的屬性,比如教課時(shí)間,我們可以把所有的關(guān)系都看作一個(gè)實(shí)體對(duì)象。但是為了簡(jiǎn)化程序,對(duì)于那些沒有自己屬性的一對(duì)一,一對(duì)多關(guān)系我們可以把它簡(jiǎn)化成父、子表的關(guān)系。表示數(shù)據(jù)庫中的主表和子表有兩種方法。

一種方法把子表和主表看作一個(gè)實(shí)體對(duì)象,子表用Vector或HashTable這樣的Collection定義成主表的一個(gè)屬性,在_setAttribute方法中,再執(zhí)行一次sql查詢,把查詢出的子表數(shù)據(jù)放入collection中。同時(shí)還要修改insert,update方法,使得主表的實(shí)體對(duì)象每次數(shù)據(jù)插入或修改時(shí)都要?jiǎng)h除并重新插入子表的數(shù)據(jù)。這里實(shí)際上把子表看作主表的一種附屬數(shù)據(jù)結(jié)構(gòu),而不是獨(dú)立的對(duì)象,子表的數(shù)據(jù)庫操作全部由主表來完成。

另一種方法是把子表看作一個(gè)單獨(dú)的實(shí)體類,實(shí)際上這時(shí)不存在主表和子表的概念了。只有兩個(gè)實(shí)體對(duì)象,他們之間是一種關(guān)聯(lián)的關(guān)系。主表通過getXXByXX()的方法來返回一個(gè)子表類的Browser。可以通過定義主表的一個(gè)方法insertXX(), 調(diào)用子表的insert()來插入一個(gè)新的子表項(xiàng)目;定義deleteXXX()來刪除子表項(xiàng)目。至于更新子表數(shù)據(jù),可以直接調(diào)用子表實(shí)體類的update()方法,不需要使用主表類的任何方法。

對(duì)于一個(gè)視圖,也可以參照定義實(shí)體類的方法定義一個(gè)視圖類,不過要盡量少用視圖類,因?yàn)橐晥D類和其他實(shí)體對(duì)象雖然語法上看不出關(guān)聯(lián),但語義上實(shí)際上是有關(guān)聯(lián)的。一個(gè)實(shí)體類的修改經(jīng)常要修改所有相關(guān)的視圖類,這對(duì)于數(shù)據(jù)封裝是很不利的。只有出于性能的考慮我們才使用它。

最后,探討一下數(shù)據(jù)庫事務(wù)的概念。事務(wù)是建立在數(shù)據(jù)庫連接的基礎(chǔ)上的,可以一次提交或回滾一系列操作。要實(shí)現(xiàn)事務(wù),必須把數(shù)據(jù)庫連接的自動(dòng)提交屬性設(shè)為false。java缺省的連接都是自動(dòng)提交的,實(shí)現(xiàn)事務(wù)必須強(qiáng)制執(zhí)行一個(gè)conn.setAutoCommit(false)。假如連接不是自動(dòng)提交的,那么要注重,每當(dāng)一個(gè)事務(wù)完成時(shí)必須執(zhí)行commit或rollback,就算是select語句也必須提交事務(wù)。而且事務(wù)最好能盡早提交,比如每次select后提交,這樣可以減少數(shù)據(jù)庫資源的占用。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 国产午夜免费视频 | 亚洲一区二区三区高清 | 毛片免费视频网站 | 黄色片网站免费观看 | 国产精品成人亚洲一区二区 | 羞羞视频免费入口网站 | 亚洲综合视频网 | 精品久久久久久成人av | www.三区 | www视频免费在线观看 | 国产一区二区三区四 | 欧美aⅴ视频| 精品久久久久久亚洲精品 | 天天草夜夜 | 性欧美暴力猛交69hd | 中国女警察一级毛片视频 | 国产毛片毛片 | 永久av在线免费观看 | 国产精品亚洲欧美一级在线 | 免费午夜网站 | 一本一本久久a久久精品综合小说 | a黄在线观看 | 麻豆自拍偷拍视频 | xxxxhdvideosex| 国产精品爱久久久久久久 | 羞羞视频免费视频欧美 | 久久久久亚洲国产精品 | 欧美人xx| 亚洲视频黄 | 久久久久久久久久久久久久久久久久 | 成人午夜免费在线视频 | 免费看污视频在线观看 | 中文字幕一二三区芒果 | 91看片在线观看视频 | 萌白酱福利视频在线网站 | 欧美女同hd| 在线影院av| 夜夜夜精品视频 | 亚洲免费视| 天海翼四虎精品正在播放 | 一本色道久久久888 国产一国产精品一级毛片 国产精品高潮视频 |