隨筆 - 115  文章 - 481  trackbacks - 0
          <2006年4月>
          2627282930311
          2345678
          9101112131415
          16171819202122
          23242526272829
          30123456

          常用鏈接

          留言簿(19)

          隨筆檔案(115)

          文章檔案(4)

          新聞檔案(1)

          成員連接

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          作者:蔡世友  來源:www.easyjf.com

          一、什么是對象-關(guān)系映射(ORM)?  

            對象-關(guān)系映射(Object/Relation Mapping,簡稱ORM),是隨著面向?qū)ο蟮能浖_發(fā)方法發(fā)展而產(chǎn)生的。面向?qū)ο蟮拈_發(fā)方法是當(dāng)今企業(yè)級應(yīng)用開發(fā)環(huán)境中的主流開發(fā)方法,關(guān)系數(shù)據(jù)庫是企業(yè)級應(yīng)用環(huán)境中永久存放數(shù)據(jù)的主流數(shù)據(jù)存儲(chǔ)系統(tǒng)。對象和關(guān)系數(shù)據(jù)是業(yè)務(wù)實(shí)體的兩種表現(xiàn)形式,業(yè)務(wù)實(shí)體在內(nèi)存中表現(xiàn)為對象,在數(shù)據(jù)庫中表現(xiàn)為關(guān)系數(shù)據(jù)。內(nèi)存中的對象之間存在關(guān)聯(lián)和繼承關(guān)系,而在數(shù)據(jù)庫中,關(guān)系數(shù)據(jù)無法直接表達(dá)多對多關(guān)聯(lián)和繼承關(guān)系。因此,對象-關(guān)系映射(ORM)系統(tǒng)一般以中間件的形式存在,主要實(shí)現(xiàn)程序?qū)ο蟮疥P(guān)系數(shù)據(jù)庫數(shù)據(jù)的映射。
              
          二、為什么要引入對象-關(guān)系映射中間件?
             在開發(fā)關(guān)系數(shù)據(jù)庫的系統(tǒng)時(shí),可以通過SQL語句讀取及操作關(guān)系數(shù)據(jù)庫數(shù)據(jù)。在Java領(lǐng)域,可以直接通過JDBC編程來訪問數(shù)據(jù)庫。JDBC可以說是JAVA訪問關(guān)系數(shù)據(jù)庫的最原始、最直接的方法。這種方式的優(yōu)點(diǎn)是運(yùn)行效率高,缺點(diǎn)是在Java程序代碼中嵌入大量SQL語句,冗余是不可避免的,開發(fā)人員常常發(fā)現(xiàn)自己在一次又一次地編寫相同的普通代碼,如獲得連接、準(zhǔn)備語句、循環(huán)結(jié)果集以及其他一些 JDBC 特定元素,使得項(xiàng)目難以維護(hù)。特別是當(dāng)涉及到非常多的關(guān)系數(shù)據(jù)表、需要在多個(gè)不同類型的關(guān)系數(shù)據(jù)庫系統(tǒng)中使用時(shí),通過在程序中使用JDBC開發(fā)實(shí)施起來更加困難。
             在開發(fā)基于數(shù)據(jù)應(yīng)用為主的軟件系統(tǒng)時(shí),引入對象-關(guān)系映射中間件是提高開發(fā)效率、提升軟件產(chǎn)品的可維護(hù)、擴(kuò)展性的現(xiàn)實(shí)需要。實(shí)踐表明,在基于數(shù)據(jù)處理為主的企業(yè)級應(yīng)程序開發(fā)中,通過引入對象-關(guān)系映射中間件,可以節(jié)省與對象持久化有關(guān)的差不多35%的編程工作量,同時(shí)提升軟件產(chǎn)品可維護(hù)及易擴(kuò)展性,提升軟件產(chǎn)品質(zhì)量。
             因此,在開發(fā)企業(yè)級應(yīng)用時(shí),有必要通過引入對象-關(guān)系映射系統(tǒng)中間件,實(shí)現(xiàn)數(shù)據(jù)庫的快速開發(fā)。企業(yè)可以通過JDBC編程來開發(fā)單獨(dú)的持久化層,把數(shù)據(jù)庫訪問操作封裝起來,提供簡潔的API,供業(yè)務(wù)層統(tǒng)一調(diào)用,實(shí)現(xiàn)自己的ORM系統(tǒng)中間件。
             當(dāng)然,一個(gè)成熟的對象-關(guān)系映射中間件產(chǎn)品,不只是簡單的把內(nèi)存中的對象持久化到數(shù)據(jù)庫、把數(shù)據(jù)庫中的關(guān)系數(shù)據(jù)加載到內(nèi)存中,還要保證系統(tǒng)頻繁地訪問數(shù)據(jù)庫的性能,降低訪問數(shù)據(jù)庫的頻率,需要引入多線程、緩存、事務(wù)管理等很多細(xì)節(jié),涉及到的技術(shù)比較復(fù)雜,因此,我們更多是使用市場上優(yōu)秀的ORM系統(tǒng)中間件產(chǎn)品。
            
          三、當(dāng)前JAVA主流的對象-關(guān)系映射中間件產(chǎn)品?
             對象關(guān)系映射程序(Object Relational Mappers,ORM)有多種形式。在 Java領(lǐng)域,大多數(shù)流行的 ORM 都可以實(shí)現(xiàn)完整的域模型映射,它的目標(biāo)是將整層的對象和行為映射到數(shù)據(jù)庫表。當(dāng)前主流的 ORM 中間件產(chǎn)品主要有:
             Hibernate(重點(diǎn)推薦)
             JDO
          iBatis
             EJB Entities 3
             EJB Entity Beans 2.x
             TopLink
             在眾多的ORM中間件產(chǎn)品中,Hibernate是筆者重點(diǎn)推薦的。Hibernate是一個(gè)基于Java的開放源代碼的持久化中間件,它對JDBC做了輕量級封裝,不僅提供ORM映射服務(wù),還提供數(shù)據(jù)查詢和數(shù)據(jù)緩存功能,Java開發(fā)人員可以方便地通過Hibernate API來操縱數(shù)據(jù)庫。現(xiàn)在,越來越多的Java開發(fā)人員把Hibernate作為企業(yè)應(yīng)用和關(guān)系數(shù)據(jù)庫之間的中間件。

          四、使用EasyDBO實(shí)現(xiàn)簡單的對象-關(guān)系映射
             EasyDBO是由簡易java框架網(wǎng)(www.easyjf.com)開發(fā)的一個(gè)適合中小型軟件數(shù)據(jù)庫開發(fā)的java數(shù)據(jù)持久層框架,系統(tǒng)參考hibernate、JDO等,結(jié)合中小項(xiàng)目軟件的開發(fā)實(shí)際,實(shí)現(xiàn)簡單的Java對象到關(guān)系數(shù)據(jù)的映射。EasyDBO由于比較簡單,比較適合于中小企業(yè)及個(gè)人開發(fā)使用,EasyDBO當(dāng)前還處于測試階段、是一個(gè)簡易但不太成熟的對象-關(guān)系映射開源中間件。
            EasyDBO的源代碼非常簡單,有一點(diǎn)Java知識(shí)的人基本上都能讀懂,因此,選擇EasyDBO作本文的示例主要目的在于讓讀者快速進(jìn)入ORM系統(tǒng)的世界,理解對象-關(guān)系數(shù)據(jù)庫實(shí)質(zhì)及實(shí)現(xiàn)原理。
             EasyDBO考慮的是最簡單的對象-關(guān)系映射,簡單到可以不使用任何配置文件就實(shí)現(xiàn)對象-關(guān)系的映射。EasyDBO源碼主要包括com.easyjf.dbo、com.easyjf.dbo.config、com.easyjf.dbo.sql三個(gè)包。其中com.easyjf.dbo是框架的核心、實(shí)現(xiàn)了對象-關(guān)系的轉(zhuǎn)換、JDBC API的封裝以及用戶接口支持等,com.easyjf.dbo.config實(shí)現(xiàn)配置文件的管理,com.easyjf.dbo.sql實(shí)現(xiàn)數(shù)據(jù)庫的簡單Sql語句的生成及多數(shù)據(jù)庫支持的擴(kuò)展。
             在當(dāng)前推出的測試版本中,程序員使用EasyDBO操作數(shù)據(jù)庫主要關(guān)注EasyJDO類提供的方法及原數(shù)據(jù)對象DBObject類、IObject接口即可。

          五、使用EasyDBO的開發(fā)數(shù)據(jù)庫應(yīng)用程序示例
             下面我們看看使用EasyDBO是怎么樣實(shí)現(xiàn)數(shù)據(jù)庫的開發(fā)。
             假設(shè)一個(gè)留言版系統(tǒng)存放留言信息關(guān)系數(shù)據(jù)表(message)的結(jié)構(gòu)為:
             cid: varchar 16 主鍵
             title: varchar 50
             content: text
             inputUser: varchar 16
             inputTime: datetime
             status: int
            
          相應(yīng)java中的類Message定義為
             import java.util.Date;
             import java.util.List;
             import com.easyjf.dbo.EasyJDB;
             import com.easyjf.dbo.IObject;
             //實(shí)現(xiàn)com.easyjf.dbo.IObject接口從而使得你的對象無需要配置文件即可與關(guān)系數(shù)據(jù)表映射
             public class Message implements IObject {
             private String cid;
             private String title;
             private String content;
             private String inputUser;
             private Date inputTime;
             private Integer status;
             public String getTableName() {
             return "message";
             }
             public String getKeyField() {

             return "cid";
             }
             public String getKeyGenerator() {
             return "com.easyjf.dbo.IdGenerator";
             }
             public String getCid() {
             return cid;
             }
             public void setCid(String cid) {
             this.cid = cid;
             }
             public String getContent() {
             return content;
             }
             public void setContent(String content) {
             this.content = content;
             }
             public java.util.Date getInputTime() {
             return inputTime;
             }
             public void setInputTime(java.util.Date inputTime) {
             this.inputTime = inputTime;
             }
             public String getInputUser() {
             return inputUser;
             }
             public void setInputUser(String inputUser) {
             this.inputUser = inputUser;
             }
             public Integer getStatus() {
             return status;
             }
             public void setStatus(Integer status) {
             this.status = status;
             }
             public String getTitle() {
             return title;
             }
             public void setTitle(String title) {
             this.title = title;
             }

             //把對象持久化(保存)到關(guān)系數(shù)據(jù)庫中
             public boolean save()
             {
             EasyJDB db=new EasyJDB();
             return db.saveOrUpdate(this);
             }
             //從持久化存儲(chǔ)設(shè)備數(shù)據(jù)庫系統(tǒng)中永久刪除對象
             public boolean del()
             {
             EasyJDB db=EasyJDB.getInstance();
             return db.del(this);
             }
             //通過主鍵id從數(shù)據(jù)庫系統(tǒng)中讀取數(shù)據(jù),返回一個(gè)對象
             public static Message read(String cid)
             {
             EasyJDB db=EasyJDB.getInstance();
             return (Message)db.get(Message.class,cid);
             }
             //通過sql從數(shù)據(jù)庫中查詢符合條件的數(shù)據(jù),返回對象列表
             public static List query(String sql)
             {
             EasyJDB db=EasyJDB.getInstance();
             return db.query(Message.class,sql);
             }
             //應(yīng)用演示代碼
             public static void main(String[] args) {
             Message m=new Message();
             m.setTitle("標(biāo)題");
             m.setContent("內(nèi)容");
             m.setInputTime(new Date());
             m.setInputUser("test");
             m.setStatus(new Integer(1));
             if(m.save())
             {
             System.out.print("成功把對象保存到關(guān)系數(shù)據(jù)庫中");
             }
             else
             {
             System.out.println("保存數(shù)據(jù)出錯(cuò)!");
             }
             //查詢數(shù)據(jù)
             List list=Message.query("1=1");
             if(list!=null){
             for(int i=0;i<list.size();i++)
             {
             Message message=(Message)list.get(i);
             System.out.println("--------");
             System.out.println("cid:"+message.getCid());
             System.out.println("title:"+message.getTitle());
             System.out.println("inputUser:"+message.getInputUser());
             System.out.println("inputTime:"+message.getInputTime());
             System.out.println("status:"+message.getStatus());
             }
             }
             }
             }

             如上面的代碼所示,程序只需要通過EasyJDB的getInstance()方法得到一個(gè)實(shí)例,然后就可以通過EasyJDB對象的save、update、del、get、query等類似的方法進(jìn)行數(shù)據(jù)庫的操作了。而程序員不用管具體的數(shù)據(jù)庫系統(tǒng)類型、不用管數(shù)據(jù)庫連接的獲取、數(shù)據(jù)庫資源的釋放、不用構(gòu)造煩瑣無味的Sql添、刪、改、查語句。
             關(guān)于數(shù)據(jù)源及配置文件:用戶可以通過EasyDBO的配置文件easyjf-dbo.xml文件配置數(shù)據(jù)庫連接數(shù)據(jù)源,也可以程序中設(shè)置數(shù)據(jù)源,還可通過IOC容器設(shè)置數(shù)據(jù)源。下面我們看看EasyDBO的數(shù)據(jù)源配置文件easyjf-dbo.xml的內(nèi)容。
             <easyjf-dbo>
             <datasource id="bbs" type="org.apache.commons.dbcp.BasicDataSource">
             <property name="easydbo.connection.driver_class">org.gjt.mm.mysql.Driver</property>
             <property name="easydbo.connection.password">yourpassword</property>
             <property name="easydbo.connection.url">jdbc:mysql://127.0.0.1:3306/easyjf</property>
             <property name="easydbo.connection.username">root</property>
             <property name="easydbo.dialect">com.easyjf.dbo.sql.MySqlQuery</property>
             <property name="easydbo.optimize">true</property>
             <property name="esyydbo.show_sql">true</property>
             </datasource>
             <tables>
             <class>
             </class>
             </tables>
             </easyjf-dbo>

            假如用戶使用的是MS Sql Server數(shù)據(jù)為,把上面的的配置文件修改成如下的內(nèi)容即可:
             <easyjf-dbo>
             <datasource id="bbs" type="org.apache.commons.dbcp.BasicDataSource">
             <property name="easydbo.connection.driver_class">com.microsoft.jdbc.sqlserver.SQLServerDriver</property>
             <property name="easydbo.connection.password">sa</property>
             <property name="easydbo.connection.url">jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=easyjf;SelectMethod=cursor</property>
             <property name="easydbo.connection.username">yourpassword</property>
             <property name="easydbo.dialect">com.easyjf.dbo.sql.MSSqlServerQuery</property>
             </datasource>
             <tables>
             <class>
             </class>
             </tables>
             </easyjf-dbo>

          六、選擇適合你的對象-關(guān)系映射中間件
             不是功能最全,用得最多的中間件就一定適合您,當(dāng)前流行的各種ORM中間件產(chǎn)品中,hibernate無疑是最為出色的產(chǎn)品,從系統(tǒng)的構(gòu)架、性能及功能上都非常好。在大型分布市群集服務(wù)器運(yùn)用領(lǐng)域,EJB Entity Beans是首選,因?yàn)槠溆袕V泛的市場及運(yùn)用基礎(chǔ)。當(dāng)然,在小型的數(shù)據(jù)庫應(yīng)用軟件領(lǐng)域,如一個(gè)新聞網(wǎng)站、一個(gè)簡單的網(wǎng)上商店、論壇系統(tǒng)等,筆者也推薦大家不防試試EasyDBO。作為初學(xué)者,筆者推薦大家使用EasyDBO,閱讀EasyDBO的源代碼,可以讓你快速掌握及了解ORM中間件的實(shí)質(zhì)及工作原理,從而為學(xué)習(xí)及使用功能更加強(qiáng)大對象-關(guān)系映射中間件產(chǎn)品打下基礎(chǔ)。
             更多完整的有關(guān)EasyDBO應(yīng)用實(shí)例代碼,請通過官方網(wǎng)站www.easyjf.com下載。

          (轉(zhuǎn)載請保留作者及來源信息)

          posted on 2006-04-17 21:23 簡易java框架 閱讀(1042) 評論(1)  編輯  收藏

          FeedBack:
          # re: 使用對象-關(guān)系映射(ORM)系統(tǒng)中間件提升軟件開發(fā)效率及質(zhì)量  2006-05-19 01:47 Jerry Tian
          起初是做過一個(gè)PHP粗糙的項(xiàng)目,手工遷移到JAVA平臺(tái)后確實(shí)發(fā)現(xiàn)RMDBS系統(tǒng)和JAVA的OO的失配問題。最初在指導(dǎo)下接觸了Hibernate并且一些項(xiàng)目中加以應(yīng)用,確實(shí)給我耳目一新的感覺。

          現(xiàn)在接觸Spring的JDBC的Template后,中途還看過iBatis的框架和簡單的應(yīng)用(其實(shí)都是Spring的插接ORM的例程),更加理解了ORM技術(shù)在OO應(yīng)用中對于代碼復(fù)用和結(jié)構(gòu)分層的巨大價(jià)值。PHP中連接的獲取和釋放是相當(dāng)自動(dòng)話的,但是前提就是你的查詢非常快;JAVA中如果完全自己管理JDBC連接,也確實(shí)相當(dāng)?shù)耐纯啵艺娴倪@么做了也就意味著同良好的OO和代碼復(fù)用的告別。對于快速的原型項(xiàng)目,而且不想考慮太多的數(shù)據(jù)庫細(xì)節(jié)或者需要頻繁的遷移數(shù)據(jù)庫平臺(tái),成熟的高層ORM產(chǎn)品像Hibernate絕對是不二選擇;但是當(dāng)項(xiàng)目的數(shù)據(jù)量增大,數(shù)據(jù)庫平臺(tái)趨于穩(wěn)定于一種產(chǎn)品,此時(shí)良好的SQL技巧加上JDBC模板技術(shù)就應(yīng)該是項(xiàng)目的選擇了。此時(shí)iBatis或者Spring的JDBC封裝都是非常不錯(cuò)的選擇,而我更偏向于Spring的JDBC封裝,實(shí)現(xiàn)的相當(dāng)優(yōu)雅。  回復(fù)  更多評論
            

          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 宽城| 瑞安市| 乐安县| 吐鲁番市| 通城县| 土默特右旗| 甘泉县| 两当县| 赣榆县| 吉林省| 平阳县| 阜新| 昌黎县| 贵阳市| 寿光市| 彰化市| 东山县| 吴忠市| 光泽县| 德钦县| 台东县| 台山市| 仁布县| 阜新市| 灵宝市| 荔浦县| 盐津县| 黔南| 微博| 福海县| 朝阳区| 和硕县| 高台县| 方山县| 海兴县| 苗栗市| 双柏县| 淄博市| 奉化市| 栾城县| 南充市|