Sung in Blog

                     一些技術(shù)文章 & 一些生活雜碎
          JDO(Java Data Object)是JCP中較早開發(fā)出來并形成規(guī)范的JSR12,該規(guī)范對數(shù)據(jù)的持久化存儲進(jìn)行了一系列規(guī)范,并已有眾多的商業(yè)產(chǎn)品和開源項目是基于該規(guī)范。作為一種需要引起重視的技術(shù),研究并探討其企業(yè)應(yīng)用可行性是十分重要的。

          前言

          在企業(yè)級的應(yīng)用開發(fā)中,常需要有良好的持久化技術(shù)來支持?jǐn)?shù)據(jù)存儲。通過良好的規(guī)范或API,將企業(yè)的領(lǐng)域業(yè)務(wù)對象進(jìn)行持久化存儲,大多采用O/R映射技術(shù)來進(jìn)行模式化的數(shù)據(jù)轉(zhuǎn)換及自動映射工作。

          JDO(Java Data Object)是JCP中較早開發(fā)出來并形成規(guī)范的JSR12,該規(guī)范對數(shù)據(jù)的持久化存儲進(jìn)行了一系列規(guī)范,并已有眾多的商業(yè)產(chǎn)品和開源項目是基于該規(guī)范。作為一種需要引起重視的技術(shù),研究并探討其企業(yè)應(yīng)用可行性是十分重要的。

          以下主要對JDO(JDO 1.0規(guī)范)的應(yīng)用開發(fā)技術(shù)作扼要介紹,通過該文,可以由淺入深、并較為全面地了解JDO,掌握主要的技術(shù)細(xì)節(jié)及過程,理解其運(yùn)行機(jī)制,并對企業(yè)級應(yīng)用有個總體的把握,這將有助于企業(yè)應(yīng)用軟件的技術(shù)選型、體系架構(gòu)及分析設(shè)計活動。

          該文適合企業(yè)應(yīng)用架構(gòu)師、及關(guān)心數(shù)據(jù)持久層設(shè)計開發(fā)人員。

          JDO基本思想及特點(diǎn)

          企業(yè)信息系統(tǒng)的一個重要問題是解決數(shù)據(jù)的存儲,即持久化。在軟件開發(fā)過程中,分析員分析領(lǐng)域業(yè)務(wù),提取出領(lǐng)域業(yè)務(wù)模型,并對應(yīng)設(shè)計出數(shù)據(jù)庫中需要進(jìn)行存儲業(yè)務(wù)數(shù)據(jù)的數(shù)據(jù)庫表及相應(yīng)字段。

          并根據(jù)業(yè)務(wù)流程,設(shè)計業(yè)務(wù)處理邏輯單元,進(jìn)行數(shù)據(jù)的加工、處理及存儲、查詢等業(yè)務(wù)。其中一個較為繁煩、枯燥的工作,就是處理大量的數(shù)據(jù)持久化代碼。

          為了解決數(shù)據(jù)從業(yè)務(wù)對象層向數(shù)據(jù)存儲層之間的轉(zhuǎn)換工作,JDO提供了相應(yīng)的開發(fā)規(guī)范及API,解決了由Java對象直接存儲為數(shù)據(jù)庫相應(yīng)表的底層處理過程,有助于設(shè)計人員更加專注于面向業(yè)務(wù)流程、面向業(yè)務(wù)對象等較高層次的應(yīng)用。

          由于采用JDO的映射機(jī)制,能降低了業(yè)務(wù)系統(tǒng)與數(shù)據(jù)存儲系統(tǒng)的耦合,使得業(yè)務(wù)系統(tǒng)相對于關(guān)系數(shù)據(jù)庫或?qū)ο笮蛿?shù)據(jù)庫,具有可移植性,同時,由于采用面向?qū)ο螅ǘ莻鹘y(tǒng)的面向記錄)的持久化技術(shù),系統(tǒng)更為輕便、簡潔,增強(qiáng)了可維護(hù)性。

          JDO應(yīng)用示例及分析

          以下將通過一些示例,由淺及深地講解JDO技術(shù)。

          臨時對象與持久對象

          這是一個普通的業(yè)務(wù)對象的代碼。









          package business.model; 
          public class Book 
          { 
            private String isbn; 
            private String name; 
            private Date publishDate; 
            public void setISBN(String isbn)
            { 
              this.isbn = isbn; 
            } 
            public String getISBN()
            { 
              return this.isbn; 
            } 
            public void setName(String name)
            { 
              this.name = name; 
            } 
            public String getName()
            { 
              return this.name; 
            } 
            public void 
            setPublishDate(Date pubDate)
            { 
              this.publishDate = pubDate; 
            } 
            public Date getPublishDate()
            { 
              return this.publishDate; 
            } 
          }


          現(xiàn)在將它作為一個JDO中對象保存到數(shù)據(jù)庫中。代碼如下:

          Book book = new Book(); 
          book.setISBN(“isbn-1234567”); 
          book.setName(“Java設(shè)計模式”); 
          
          PersistenceManager 
          manager = persistenceManagerFactory.
          getPersistenceManager(); 
          manager.currentTransaction().begin(); 
          manager.makePersistence(book); 
          manager.currentTransaction().commit();


          Book類的實(shí)例book對JDO的API而言,就是一個持久對象。類Book是可持久類。那任何一個普通java類都是JDO的可持久類嗎?不是的。只有具備以下的條件,一個對象才可以被JDO持久到數(shù)據(jù)庫中。

          它所屬類應(yīng)標(biāo)記為可持久的類,有以下兩種方法:

          顯式:實(shí)現(xiàn)接口,javax.jdo.PersistenceCapable即可;

          隱式:以Sun的JDO參考實(shí)現(xiàn)為例,Book.java類的相同路徑下還須有Book.jdo文件。

          <?xml version=“1.0” 
          encoding = “UTF-8”?> 
          <!DOCTYPE jdo SYSTEM “jdo.dtd”> 
          <jdo> 
            <package name = “business.model”> 
               <class name = “Book”/> 
            </package> 
          </jdo>


          并通過字節(jié)碼增強(qiáng)工具(本例采用Sun的字節(jié)碼增強(qiáng)工具)處理:

          javac Book.java 
          java com.sun.jdori.enhancer.Main 
          Book.class Book.jdo


          通過上述兩種方法,獲得的Book.class才是一個可持久的類。

          字節(jié)碼增強(qiáng)的有如下功能:當(dāng)應(yīng)用程序通過set方法修改某個字段1時,由于通過增強(qiáng)過程,在其內(nèi)部插入了某些代碼,JDO會獲得數(shù)據(jù)狀態(tài)變化的信息,從而在持久過程中,進(jìn)行有選擇性的處理。

          按照J(rèn)DO規(guī)范,增強(qiáng)后的類可以在不同的JDO實(shí)現(xiàn)上使用,而無需重新編譯或增強(qiáng)。

          并不是所有Book對象都是持久對象,只有當(dāng)makePersistence后,該對象才是持久對象,并會通過JDO實(shí)現(xiàn)存儲到數(shù)據(jù)庫中。通過JDO的供應(yīng)商擴(kuò)展標(biāo)記符(vendor-extension),可詳細(xì)描述Book類的存儲特性,如為該可持久類指定數(shù)據(jù)庫表和對應(yīng)字段。

          持久對象查詢

          JDO查詢主要有以下兩種方式。

          使用Extend查詢

          Extend可以查詢指定類及子類的持久對象。

          PersistenceManager
          manager = persistenceManagerFactory.
          getPersistenceManager(); 
          manager.currentTransaction().begin(); 
          Extend extend =
          manager.getExtend(Book.class,true);
          //true表明同時查詢子類 
          Iterator it = extend.iterator(); 
          while(it.hasNext())
          { 
            Book book = (Book)it.next(); 
            System.out.println(book.getISBN()); 
          } 
          extend.closeAll(); 
          manager.currentTransaction().commit();


          Extend查詢方法,提供了一種基于類的查詢途徑,它可以與下面的Query構(gòu)成更為強(qiáng)大的查詢。

          使用Query查詢

          Query可以指定過濾條件,是一種常用的查詢方式。

          下例是查找條件為“書名以‘Java設(shè)計模式’開頭且出版日期小于今天”的書籍。

          String filter = 
          “((String)name).startsWith(\”Java設(shè)計模式\”)
          && publishDate < today”; 
          Query query = 
          pm.getQuery(Book.class,filter); 
          query.declareImports(“import java.util.Date”); 
          query.declareParameters(“Date today); 
          
          Date today = new Date(); 
          results = (Collection)
          query.execute(today);
          //傳入?yún)?shù)值today 
          if (results.isEmpty())
          { 
            System.out.println(“No data!”); 
          }else{ 
            Iterator it = results.iterator(); 
            while(it.hasNext())
            { 
              Book book = (Book)it.next(); 
              System.out.println
          	(“Book Name:” + book.getName()
          	+ “, ISBN:” + book.getISBN()); 
            } 
          }


          注:該條件使用了一個變元‘today’,通過“declareParameters”來聲明該變量,并在“execute”方法中傳入該變量的實(shí)例。這種帶參數(shù)的查詢,很類似于我們以前采用JDBC的帶?的查詢方式。

          其中startsWith(String s)是JDO提供的標(biāo)準(zhǔn)字符方法,類似的方法還有endsWith(String s)。

          JDOQL:上述使用的就是一個JDOQL樣例,JDOQL是JDO規(guī)范一個組成部分。使用JDOQL可以使用應(yīng)用在不同的JDO實(shí)現(xiàn)上運(yùn)行。為了解決JDOQL的某些不足,JDO規(guī)范提供了支持特定JDO供應(yīng)商查詢語句接口。

          查詢排序

          下例是將查詢結(jié)果按“出版日期降序、書名升序”進(jìn)行排序。

          Query query = 
          pm.newQuery(Book.class, filter); 
          
          String orderStr = 
          “publishDate decending, name ascending”; 
          query.setOrdering(orderStr); 
          
          results = query.execute(today);
          對象更新

          當(dāng)客戶端對業(yè)務(wù)數(shù)據(jù)進(jìn)行了更新后,需要通過業(yè)務(wù)過程將其更新到持久層中。這有兩個過程,首先根據(jù)主鍵找到該實(shí)例,接著更新字段及提交。如下例,將指定書目編號的書本的出版日期進(jìn)行更改。











          public void updateBookPublishDate
          (String isbn, Date newDate)
          { 
            PersistenceManager pm = null; 
            try{ 
          pm = pmf.getPersistenceManager(); 
          Object obj = 
          pm.newObjectIdInstance(Book.class,isbn); 
          Book book = 
          (Book)pm.getObjectById(obj,true); 
          book.setPublishDate(newDate); 
            }catch(Exception e)
            { 
          xxxContext.setRollbackOnly(); 
          throw new Exception(e); 
            }finally{ 
              try{ 
          if (pm != null && !pm.isClosed())
          { 
              pm.close(); 
          } 
          }catch(Exception ex)
          { 
            System.out.println(ex); 
            } 
          }


          注,在PersistenceManager使用newObjectIdInstance()方法時,JDO是如何知道通過書目編號ISBN來找到該對象呢?其實(shí)在本可持久類Book的jdo描述文件中,還需提供如下信息:

          <?xml version=“1.0” 
          encoding = “UTF-8”?> 
          <!DOCTYPE jdo SYSTEM “jdo.dtd”> 
          <jdo> 
            <package name = “business.model”> 
               <class name = “Book”
          	 identity-type=“application”
          	 objectid-class=“BookKey” > 
                    <field name=“isbn”
          		  primary-key=“true”/> 
               </class> 
            </package> 
          </jdo>


          其中“identity-type=“application””聲明可持久類Book采用程序標(biāo)識方式,即應(yīng)用程序傳入ID(字段isbn為“primary-key”)信息,JDO實(shí)現(xiàn)構(gòu)造出指定的“objectid-class”的實(shí)例(即newObjectIdInstance過程),并由JDO來檢索出指定的持久化對象(即getObjectById)。

          BookKey類源碼如下:

          package businesss.model; 
          public class BookKey implements
          java.io.Serializable
          { 
                public String isbn; 
                public BookKey()
          	  { 
                } 
                public BookKey(String oid)
          	  { 
              isbn = oid; 
              } 
              public String toString()
          	{ 
                    return isbn; 
              } 
              public Boolean equals(Object obj)
          	{ 
                return isbn.equals
          	  ((BookKey)obj).isbn); 
              } 
              public int hashCode()
          	{ 
                    return isbn.hashCode(); 
              } 
          }


          符合 JDO 的“objectid-class”類,如“BookKey”,須具備以下條件:

          類聲明為 public,并實(shí)現(xiàn) java.io.Serializable;

          帶有一個公有且不帶參數(shù)的構(gòu)造方法;

          當(dāng)字段作為主鍵時,須有公有的,且名稱和類型與持久類的字段一致,如:public String isbn;

          equals 和 hashCode 須使用全部(特指多字段的聯(lián)合主鍵)的主鍵字段值;

          類必須有一個構(gòu)造方法,與 toString 方法的處理過程是逆向過程;即將 toString 的輸出值,作為該構(gòu)造方法的輸入值,又可以重新生成該實(shí)例(如構(gòu)造方法“public BookKey(String oid)”)。

          綜上所述,如果Book由兩個字段作為主鍵,如isbn和name,則可能的代碼是pm.newObjectIdInstance(Book.class,isbn+“#”+name),且BookKey的構(gòu)造方法作相應(yīng)更改,并有兩個公有字段“isbn”和“name”。

          對象刪除

          對象刪除采用方法deletePersistence。示例如下:







          pm.currentTransaction().begin(); 
          Object obj = 
          pm.newObjectIdInstance
          (Book.class,isbn); 
          Book book = 
          (Book)pm.getObjectById(obj,true); 
          pm.deletePersistence(book); 
          pm.currentTransaction().commit();


          獲得PersistenceManager實(shí)例

          上述的所有操作與需要PersistenceManager實(shí)例,它可以在兩種環(huán)境方法下獲得:非受管環(huán)境和受管環(huán)境。

          非受管環(huán)境

          非受管環(huán)境是多指兩層開發(fā)模式,應(yīng)用程序直接獲得資源對象,進(jìn)行業(yè)務(wù)操作。一般事務(wù)管理、安全管理或資源管理都需要應(yīng)用程序自行維護(hù)。

          Properties properties =
          new Properties(); 
          properties.put(“javax.jdo.
          PersistenceManagerFactoryClass”,
          “com.xxx.jdo.xxxPMFClass”); 
          properties.put(“javax.jdo.
          option.ConnectionURL”, “xxx”); 
          properties.put(“javax.jdo.
          option.ConnectionUserName”, “xxx”); 
          properties.put(“javax.jdo.
          option.ConnectionPassword”, “xxx”); 
          PersistenceManagerFactory pmf = 
          JDOHelper.getPersistence
          ManagerFactory(properties); 
          PersistenceManager pm = 
          pmf.getPersistenceManager();


          與JDBC獲取類似。

          受管環(huán)境

          受管環(huán)境一般是多層開發(fā)模式,尤其是處于J2EE應(yīng)用環(huán)境中,程序通過容器獲得資源對象,進(jìn)行業(yè)務(wù)操作,由于在容器環(huán)境下,事務(wù)、安全及資源管理都由容器進(jìn)行統(tǒng)一集中管理,從而簡化了代碼結(jié)構(gòu)。

          以下是EJB(EntityBean、SessionBean、MessageDrivenBean)中的setXXXContext中的代碼示例。

          private PersistenceManagerFactory pmf; 
          public void setXXXContext
          (XXXContext context)
          { 
            try{ 
              InitialContext ctx =
          	new InitialContext(); 
              Object obj = ctx.lookup
          	(“java:compenvjdofactory”); 
              pmf = (PersistenceManagerFactory)
          	PortableRemoteObject.narrow
          	(o,PersistenceManagerFactory.class); 
            }catch(NamingException e)
            { 
              throw new Exception(e); 
            } 
          }


          PMF是如何綁定到J2EE環(huán)境下的JNDI上,有興趣可參考JCA相關(guān)的技術(shù)文檔。

          事務(wù)管理

          事務(wù)管理及使用,主要有以下三種情形。

          使用JDO事務(wù)的Bean管理情形

          一般在非J2EE環(huán)境下,使用該事務(wù)管理模式。

          PersistenceManager pm = 
          pmf.getPersistenceManager(); 
          pm.currentTransaction().begin(); 
          //do some business with jdo 
          pm.currentTransaction().commit(); 
          pm.close();


          使用JTA事務(wù)的Bean管理情形

          一般在J2EE環(huán)境下,采用Bean管理的事務(wù)情形下,使用以下方式。

          該方式可用在EJB的事務(wù)環(huán)境下。

          xxxContext.getUser
          Transaction().begin(); 
          PersistenceManager pm =
          pmf.getPersistenceManager(); 
          //do some business with jdo 
          xxxContext.getUserTransaction().commit(); 
          pm.close();
          使用JTA事務(wù)的容器管理情形

          一般在J2EE環(huán)境下,采用容器管理的事務(wù)情形下,使用如下方式。

          如下是某個會話Bean的業(yè)務(wù)方法。









          public void doBusiness(){ 
            PersistenceManager pm ; 
            try{ 
              pm = pmf.getPersistenceManager(); 
              //do some business with jdo 
            }catch(Exception e){ 
              xxxContext.setRollbackOnly(); 
              System.out.println(e); 
            }finally{ 
              try{ 
                if (pm != null && !pm.isClosed()) 
                  pm.close(); 
              }catch(Exception ex){ 
                System.out.println(ex); 
              } 
            } 
          }


          綜上,可以得出結(jié)論,JDO的操作完全與JDBC的操作相差無幾。

          JDO高級應(yīng)用

          復(fù)雜對象的持久化

          在實(shí)際的應(yīng)用中,一個可持久化類要遠(yuǎn)比Book類復(fù)雜很多。它可能會引用其它的Java類型、類、集合或數(shù)組,及可能復(fù)雜的繼承關(guān)系。當(dāng)這些對象的狀態(tài)發(fā)生變化時,JDO是如何感知及跟蹤狀態(tài)變化?

          JDO提供了相應(yīng)的API及規(guī)范來實(shí)現(xiàn)該功能。

          基本類型及引用

          可持久化類的字段能被JDO實(shí)現(xiàn)進(jìn)行持久化的原則。原始類型、java.util.Date等被支持(其它較為復(fù)雜或可選特性,詳見JDO規(guī)范);如果引用是一個可持久類,則JDO進(jìn)行持久化處理;通過元數(shù)據(jù)(如jdo文件)聲明的字段,一般是非可持久化類的引用,JDO進(jìn)行持久化;

          前面兩種情形,當(dāng)狀態(tài)發(fā)生變化時,JDO會自動感知,但如果引用是非可持久化類,則需要代碼進(jìn)行顯式通知,否則JDO不會將變化進(jìn)行存儲。如下例:

          public class Book 
          { 
            …… 
              private Object picture; 
              public void setPicture(Object pic)
          	{ 
                    picture = pic; 
              } 
              public Object getPicture()
          	{ 
                    Return picture; 
              } 
          }


          該類字段picture需要持久化,但java.lang.Object不是一個可持久類,故聲明如下:

          <?xml version=“1.0” encoding = “UTF-8”?> 
          <!DOCTYPE jdo SYSTEM “jdo.dtd”> 
          <jdo> 
            <package name = “business.model”> 
               <class name = “Book” > 
                    <field name=“picture” 
          		  persistence-modifier=“persistent”/> 
               </class> 
            </package> 
          </jdo>


          如果其它模塊通過getPicture獲得對象,并在JDO不可感知的外部,修改對象,則變化不會存儲,較好的辦法是修改setPicture方法,如下:

          public void setPicture(Object pic)
          { 
            JDOHelper.makeDirty(this, “picture”); 
            picture = pic; 
          }


          并通過setPicture方法來更新數(shù)據(jù)。JDO的“makeDirty”方法,主要負(fù)責(zé)通知JDO實(shí)現(xiàn),可持久化類Book某個實(shí)例(this)的“picture”字段發(fā)生了變化。

          集合

          可持久類的字段引用為集合時,按照J(rèn)DO規(guī)范,強(qiáng)制支持java.util.HashSet,對HashMap、HashTable、TreeMap、TreeSet、LinkedList、ArrayList及Vector的支持對JDO實(shí)現(xiàn)而言是可選的,通過PersistenceManagerFactory的supportedOptions方法獲得實(shí)現(xiàn)特性。

          數(shù)組

          如果可持久類的引用是數(shù)組類型,當(dāng)數(shù)組單元發(fā)生變化時,需要調(diào)用“makeDirty”來通知JDO實(shí)現(xiàn),該實(shí)例的數(shù)組引用內(nèi)容發(fā)生了變化。與引用是非可持久類實(shí)例不同,不需要進(jìn)行JDO的元數(shù)據(jù)聲明。

          繼承

          如果使用可持久性,一般繼承的子類與父類都為可持久類,以減少系統(tǒng)復(fù)雜性,這時需要在子類的元數(shù)據(jù)中指出其可持久超類,如下:

          <
          class name=“TechBook” 
          persistence-capable-superclass=“Book”/>


          可為非持久類擴(kuò)展持久類,或可為持久類擴(kuò)展非可持久類;這兩種情形JDO實(shí)現(xiàn)都將忽略非

          可持久類的字段部分,而不保存到數(shù)據(jù)庫。

          JDO的一些不足之處

          JDO對數(shù)據(jù)的持久化技術(shù)相比于成熟的SQL,還有不足之處,這些不足在某些情況下將可能會影響數(shù)據(jù)處理部分的設(shè)計實(shí)現(xiàn)。以下列舉了常用數(shù)據(jù)訪問的必要功能

          查詢增強(qiáng)

          如字符串不支持通配符、大小寫比較;

          不支持聚合操作,無法實(shí)現(xiàn)MIN、MAX、SUM和AVG;

          不支持投影操作,JDO查詢返回為對象,而不像SQL那樣返回字段;

          不支持聯(lián)合、交叉(UNION/INTERSECT);

          不支持JOIN、IN和EXISTS;

          企業(yè)應(yīng)用探究

          由于JDO采用面向?qū)ο蟮某志没幚砑夹g(shù),從而為解決企業(yè)業(yè)務(wù)系統(tǒng)的持久化問題提供了一個新技術(shù)解決方案。但是先進(jìn)的未必就最適用。在某些應(yīng)用場景下,需要結(jié)合各種因素,采取靈活的策略。

          面向?qū)ο笈c面向記錄

          現(xiàn)在大多業(yè)務(wù)系統(tǒng)都采用面向?qū)ο蠓治鲈O(shè)計,這就需要每個應(yīng)用系統(tǒng)都自行實(shí)現(xiàn)將對象映射成記錄,并存儲到數(shù)據(jù)庫中,而有JDO這樣的面向?qū)ο蟮某志没夹g(shù),在某種程度上解放了這種轉(zhuǎn)化設(shè)計的不規(guī)范性,進(jìn)而獲得相對更優(yōu)的系統(tǒng)結(jié)構(gòu)。

          另一方面,一個業(yè)務(wù)系統(tǒng)的數(shù)據(jù)持久化,一般都有這樣的過程:對象層->記錄層->物理層,JDO無疑使分析設(shè)計人員從記錄層的苦海中解脫出來,從而更加專注于對象層,這對開發(fā)人員無疑是一個令人歡欣鼓舞的技術(shù)。

          JDO并不能完全代替JDBC。

          根據(jù)經(jīng)典的“8-2原理”,如果用JDO來解決80%的問題,余下的20%由JDBC來實(shí)現(xiàn),這種相互補(bǔ)充,各取所長的策略,是一個很有效的辦法。

          這樣一方面可以獲得較好的結(jié)構(gòu)及提升開發(fā)質(zhì)量,另一方面解決了JDO的某些技術(shù)不足,并可根據(jù)以后的技術(shù)變化,再做適當(dāng)轉(zhuǎn)化。

          性能問題

          JDO與JDBC究竟誰的性能更優(yōu),目前還沒有一個權(quán)威、且令人滿意的答案。但對于一些JDO實(shí)現(xiàn)而言,通過采用緩存機(jī)制,使得性能有了較大提高。

          跨數(shù)據(jù)庫

          使用JDO的系統(tǒng)能更好地進(jìn)行數(shù)據(jù)庫移植,甚至可以在對象數(shù)據(jù)庫上運(yùn)行;當(dāng)然JDBC處理層如果完全遵循SQL-92標(biāo)準(zhǔn),也同樣具有很好的跨數(shù)據(jù)庫能力。
          posted on 2005-11-04 13:53 Sung 閱讀(255) 評論(0)  編輯  收藏 所屬分類: Java
          主站蜘蛛池模板: 青海省| 于田县| 沧州市| 徐汇区| 措美县| 丹东市| 广州市| 招远市| 咸阳市| 隆安县| 宁化县| 东光县| 龙里县| 淮安市| 平凉市| 罗源县| 嘉定区| 岐山县| 新干县| 绍兴县| 韶关市| 扶风县| 威宁| 巴彦县| 罗定市| 务川| 保定市| 区。| 西吉县| 都安| 深泽县| 怀仁县| 山阴县| 府谷县| 噶尔县| 滕州市| 南京市| 彩票| 万州区| 南和县| 蒙自县|