posts - 78, comments - 34, trackbacks - 0, articles - 1
            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          日歷

          <2009年12月>
          293012345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          搜索

          •  

          積分與排名

          • 積分 - 108716
          • 排名 - 540

          最新評(píng)論

                   今日是JDBC的最后一天了,繼續(xù)JDBC的高級(jí)應(yīng)用。說(shuō)是高級(jí)應(yīng)用,只是針對(duì)JDBC的再次封裝,使得使用JDBC變得更加簡(jiǎn)單。DBUtil就是這樣的庫(kù)!今日上午首先講解JDBC操作多個(gè)實(shí)體之多對(duì)多關(guān)系,Hibnate正是使用了這樣的手法,這一功能讓人感覺(jué)很好。然后方老師將以前使用的JDBC操作中,有重復(fù)的代碼提取出來(lái),形成一個(gè)單獨(dú)的類,大大簡(jiǎn)化了JDBC的操作。起初我還沒(méi)有想到這就是DBUtil,若不是老方說(shuō):我們是不是還有DBUtil沒(méi)講?我們現(xiàn)在就已經(jīng)做出來(lái)了!呵呵,就這么簡(jiǎn)單!

           

                   開(kāi)始復(fù)習(xí)、總結(jié)今日的主要內(nèi)容!

           

          一、JDBC操作多個(gè)實(shí)體——多對(duì)多

                   昨天有簡(jiǎn)單的介紹一對(duì)多的關(guān)系,使用的是部門表與員工表式之間的關(guān)系。下面舉例使用,老師表與學(xué)生表之間的關(guān)系。

           

                   首先讓我們?cè)O(shè)計(jì)一個(gè)老師表(老師能找到自己的學(xué)生):

          ID

          姓名

          學(xué)生ID(外鍵)

          1

          張三峰

          1

          2

          方世玉

          2

          1

          張三峰

          1

          2

          方世玉

          2

           

           

           

                   再設(shè)計(jì)一個(gè)學(xué)生表(學(xué)生能找到自己的老師):

                  

          ID

          姓名

          教師ID(外鍵)

          1

          AAA

          1

          2

          BBB

          2

          1

          AAA

          1

          2

          BBB

          2

           

           

           

                   顯而易見(jiàn)上邊的兩張表設(shè)計(jì)的有問(wèn)題,比較“臟”一點(diǎn)也不優(yōu)雅。我們得想一個(gè)辦法解決它!

                   創(chuàng)建一個(gè)中間表:

          教師_ID(外鍵)

          學(xué)生_ID(外鍵)

          1

          1

          2

          2

          1

          2

          2

          1

           

           

           

           

           

           

                  

           

           

          “教師_ID”字段是外鍵,指向教師表中的ID。“學(xué)生_ID”是個(gè)外鍵,指向?qū)W生表中的ID。在某些情況下中間表還定義一些其他字段。

           

                   去除教師表中的“學(xué)生ID”和學(xué)生表中的“教師ID”,這樣以后只要連表查詢即可。

           

                   上面只是舉個(gè)例子,在實(shí)際開(kāi)發(fā)中應(yīng)該先創(chuàng)建對(duì)象模型,然后再創(chuàng)建數(shù)據(jù)庫(kù)關(guān)系模型。使用對(duì)象反應(yīng)上邊的關(guān)系模型,依然是兩個(gè)對(duì)象。教師對(duì)象和學(xué)生對(duì)象,教師對(duì)象有一個(gè)SET成員,記錄他的所有學(xué)生。學(xué)生對(duì)象包含一個(gè)SET記錄他的所有教師。

           

                   創(chuàng)建多個(gè)學(xué)生對(duì)象(不需要設(shè)置SET成員),將他們添加到教師對(duì)象的SET中。將教師對(duì)象傳遞給DAO工具對(duì)象,DAO工具對(duì)象讀取教師,將教師信息保存到教師表中。然后遍歷所有學(xué)生,將學(xué)生信息保存到學(xué)生表中,同時(shí)將教師ID與學(xué)生ID保存到中間表中。OK,這樣就完成了!

           

                   這就是多對(duì)多關(guān)系——建立兩個(gè)一對(duì)多關(guān)系

           

                   再次注意:要盡量使用多對(duì)一關(guān)系,而避免使用一對(duì)多或多對(duì)多關(guān)系!

           

          二、簡(jiǎn)化JDBC操作——DBUtil實(shí)現(xiàn)原理和元數(shù)據(jù)

                   還記得我們以前寫(xiě)的操作數(shù)據(jù)庫(kù)記錄的DOMAIN類嗎?回想一下,插入記錄、修改記錄、查詢記錄、刪除記錄。在這些方法中,我們都需要獲取數(shù)據(jù)庫(kù)連接,對(duì)數(shù)據(jù)記錄操作完成后,還需要釋放這些記錄。沒(méi)感覺(jué)到什么不對(duì)嗎?當(dāng)然感覺(jué)到了,重復(fù)的代碼。既然有重復(fù)的代碼就應(yīng)該將它提取出來(lái),實(shí)現(xiàn)代碼的重用。OK,現(xiàn)在我們就把重復(fù)的代碼提取出來(lái)。為了減小篇章,我們只提取插入記錄(update)和查詢記錄。因?yàn)樾薷暮筒樵兣c插入一樣都是調(diào)用update語(yǔ)句。

           

          MyDBUtil.java

          /**

           * 封裝JDBC操作中重復(fù)的代碼,使JDBC操作變得簡(jiǎn)單。

           * @author Administrator

           *

           */

          public class MyDBUtil {

              // update可以執(zhí)行 添加、修改、刪除操作!

              public void update(String sql, Object[] args) {

                 Connection conn = null;

                 PreparedStatement ps = null;

                 ResultSet rs = null;

                 try {

                     conn = JdbcUtil.getDataSource().getConnection();

                     // 將參數(shù)填充到sql語(yǔ)句中

                     ps = conn.prepareStatement(sql);

                     for (int i = 0; args != null && i < args.length; i++) {

                        ps.setObject(i + 1, args[i]);

                     }

                     ps.executeUpdate();

           

                 } catch (SQLException e) {

                     e.printStackTrace();

                 } finally {

                     // 釋放連接

                     JdbcUtil.release(conn, ps, rs);

                 }

              }

           

              // 查詢操作

              public Object find(String sql, Object[] args, ResultSetHandler rsh) {

                 Connection conn = null;

                 PreparedStatement ps = null;

                 ResultSet rs = null;

                 Object obj = null;

                 try {

                     conn = JdbcUtil.getDataSource().getConnection();

                     // 將參數(shù)填充到sql語(yǔ)句中

                     ps = conn.prepareStatement(sql);

                     // 獲取查詢結(jié)果

                     rs = ps.executeQuery();

                     for (int i = 0; args != null && i < args.length; i++) {

                        ps.setObject(i + 1, args[i]);

                     }

                     // 調(diào)用Handler封裝數(shù)據(jù)

                     obj = rsh.handler(rs);

                 } catch (Exception e) {

                     e.printStackTrace();

                 } finally {

                     // 釋放連接

                     JdbcUtil.release(conn, ps, rs);

                 }

                 return obj;

              }

          }

           

          ResultSetHandler.java

          /**

           * Handler,使用策略模式封裝ResultSet中的數(shù)據(jù)到Bean中。

           * @author Administrator

           *

           */

          interface ResultSetHandler{

              Object handler(ResultSet rs);

          }

           

          BeanHandler.java

          /**

           * Handler,實(shí)現(xiàn)類

           * @author Administrator

           *

           */

          class BeanHandler implements ResultSetHandler{

              Class clazz;

             

              public BeanHandler(Class clazz){

                 this.clazz = clazz;

              }

             

              public Object handler(ResultSet rs) {    

                 Object obj = null;

                 try {

          // 注意此處使用的ResultSetMetaData,元數(shù)據(jù)

                     ResultSetMetaData rsd;

                     rsd = rs.getMetaData();

                     obj = this.clazz.newInstance();

                     // 將讀取的記錄設(shè)置到Bean對(duì)象中

                     for (int i = 1; i <= rsd.getColumnCount(); i++) {

                        // 獲取字段名

                        String cln = rsd.getColumnName(i);

                        // 獲取成員

                        Field field = this.clazz.getDeclaredField(cln);

                        // 設(shè)置成員值

                        field.setAccessible(true);

                        field.set(obj, rs.getObject(i));

                     }

                    

                 } catch (Exception e) {

                     e.printStackTrace();

                 }

                 return obj;

              }  

          }

           

                   上面只是簡(jiǎn)單的對(duì)JDBC的重復(fù)代碼進(jìn)行了封裝,并使用策略模式對(duì)find操作返回值進(jìn)行了與具體Bean的分離,十分優(yōu)雅。DBUtil工具包,就是使用上面的原理實(shí)現(xiàn)的!

           

                   注意:Handler實(shí)現(xiàn)類中的“ResultSetMetaData”,它被稱為元數(shù)據(jù)。JDBC的元數(shù)據(jù)有:

          1.        Connection.getDataBaseMetaData(),返回DataBaseMetaData,它包含的方法有:

          getURL():返回一個(gè)String類對(duì)象,代表數(shù)據(jù)庫(kù)的URL

          getUserName():返回連接當(dāng)前數(shù)據(jù)庫(kù)管理系統(tǒng)的用戶名。

          getDatabaseProductName():返回?cái)?shù)據(jù)庫(kù)的產(chǎn)品名稱。

          getDatabaseProductVersion():返回?cái)?shù)據(jù)庫(kù)的版本號(hào)。

          getDriverName():返回驅(qū)動(dòng)驅(qū)動(dòng)程序的名稱。

          getDriverVersion():返回驅(qū)動(dòng)程序的版本號(hào)。

          isReadOnly():返回一個(gè)boolean值,指示數(shù)據(jù)庫(kù)是否只允許讀操作。

           

          老方說(shuō)有的框架會(huì)使用到它,來(lái)獲取數(shù)據(jù)庫(kù)的連接等信息。具體在框架中如何應(yīng)用,等到學(xué)習(xí)框架時(shí)再深入吧!

           

          2.        PreparedStatement.getParameterMetaData(),返回ParameterMetaData,它包含的方法:

          getParameterCount():獲得指定參數(shù)的個(gè)數(shù)

          getParameterType(int param):獲得指定參數(shù)的sql類型

           

          在上面的例子中有用到過(guò),在DBUtil中有使用getParameterType獲取數(shù)據(jù)類型填充空的Statement參數(shù)。

           

          3.        ResultSet.getMetaData(),返回ResultSetMetaData,它包含的方法:

          getColumnCount():返回resultset對(duì)象的列數(shù)

          getColumnName(int column):獲得指定列的名稱

          getColumnTypeName(int column):獲得指定列的類型

           

                   在上面的例子中我們有使用ResultSetMetaData

           

                   O-R Mapping(Object – Relation Mapping)映射工具,對(duì)象模型與關(guān)系模型的映射:HibernateIbatisDBUtil

           

                   DBUtil在此就不多做介紹了,學(xué)了上邊的實(shí)現(xiàn)原理,自己也可以編寫(xiě)一個(gè)DBUtil出來(lái)。DBUtil的具體使用方式可以查看它的文檔! 

           

          三、XML Schema

                   今日的課程的補(bǔ)充,咱們的Servletweb.xml文件正是使用Schema描述的。以后的框架中也會(huì)使用它。Schema已經(jīng)成為w3c組織的標(biāo)準(zhǔn),并逐步取代DTDSchema要比DTD復(fù)雜的多,因?yàn)樗肓嗣臻g,多數(shù)據(jù)類型這些操作。Schema也是個(gè)XML文件!

           

                   今日就簡(jiǎn)單學(xué)習(xí)一下Schema,不深入介紹了,其實(shí)它也沒(méi)什么。

           

          1.        定義Schema約束文件:     

          <?xml version="1.0" encoding="UTF-8" ?>

          <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"

              targetNamespace="http://www.changcheng.org"

                 elementFormDefault="qualified">

          <xs:element>

              <xs:complexType>

                 <!-- 要求元素必須按照下邊的順序排列,沒(méi)有數(shù)量限制 -->

                 <xs:sequence maxOccurs='unbounded' >

                 <!-- 根元素 -->

                 <xs:element name='根元素名稱' >

                 <!-- 可添加多個(gè)子元素 -->

                     <xs:complexType>

                        <!-- 要求元素必須按照下邊的順序排列 -->

                        <xs:sequence>

                            <!-- 子元素可以定義自己的多個(gè)子元素 -->

                            <xs:element name='子元素名稱' type='xs:元素類型' />

                        </xs:sequence>

                     </xs:complexType>

                 </xs:element>

                 </xs:sequence>

              </xs:complexType>

          </xs:schema>

                  

                   其中“targetNamespace”定義自己編寫(xiě)的Schema的命名空間。

           

          2.        XML引入并使用Schema約束:

          <cc:根元素 xmlns:cc="http://www.changcheng.org"

                        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

                        xsi:schemaLocation="http://www.changcheng.org book.xsd">

                 <cc:子元素>元素值</cc:子元素>

          </cc:根元素>

           

                   其中“xsi:schemaLocation”指定引入的Schema文件所在的位置。一個(gè)XML文件中可以引入多個(gè)Schema約束文件。同樣在“xsi:schemaLocation”使用空格分隔,指定Schema約束文件的位置。“xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"”不需要指定位置,因?yàn)樗?/span>w3c組織定義的文件,Schema解析器,知道它的具體位置。

           

                   Schema文檔通常稱之為模式文檔(約束文檔),遵循這個(gè)文檔書(shū)寫(xiě)的xml文件稱之為實(shí)例文檔。Schema具體使用方式參見(jiàn)w3c的文檔吧!

           

                   OK,今天的課程內(nèi)容總結(jié)到此結(jié)束!老方剛上課時(shí)就提到大家一起合影,但課上一直很忙。今天本要合影的,但也沒(méi)抽出時(shí)間。大家一起定下后天中午合影。早就想跟大家一起合影了!

           

                   老方還有5天的課程就結(jié)束了JAVAWEB基礎(chǔ)部分,由此步入高級(jí)應(yīng)用的殿堂。大家學(xué)習(xí)興致勃勃,一定要多練習(xí)啊!到后來(lái)的項(xiàng)目,一天寫(xiě)上千行代碼都正常。高級(jí)應(yīng)用,使用上非常簡(jiǎn)單,其實(shí)我們學(xué)習(xí)的基礎(chǔ)部分,也為學(xué)習(xí)高級(jí)應(yīng)用打下了堅(jiān)實(shí)的基礎(chǔ)。因?yàn)楦呒?jí)應(yīng)用中那些框架正是使用這些基礎(chǔ)知識(shí)實(shí)現(xiàn)的。

           

                   我來(lái)此學(xué)習(xí)還有一個(gè)大的目標(biāo)就是,項(xiàng)目架構(gòu)、文檔的編寫(xiě)、項(xiàng)目的管理、UML…這些對(duì)我來(lái)說(shuō)太重要了,我可不是新手哦!我對(duì)此十分期待!

           

                   加油!


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


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 凤城市| 岑溪市| 墨江| 子洲县| 雅江县| 郯城县| 永清县| 睢宁县| 高密市| 精河县| 离岛区| 东阳市| 西峡县| 酉阳| 廊坊市| 金塔县| 衡水市| 岚皋县| 古丈县| 双峰县| 泰宁县| 武山县| 连山| 普定县| 宜黄县| 浦东新区| 专栏| 邵武市| 博乐市| 柳河县| 富平县| 井研县| 务川| 屯留县| 安远县| 宁化县| 肥城市| 新营市| 瓦房店市| 无棣县| 来安县|