<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    yxhxj2006

    常用鏈接

    統計

    最新評論

    ibatis 開發指南 3

    接 ibatis 開發指南 2 

    Cache 
    在特定硬件基礎上(同時假設系統不存在設計上的缺漏和糟糕低效的 SQL 語句) 
    Cache往往是提升系統性能的最關鍵因素)。 
    相對 Hibernate 等封裝較為嚴密的 ORM 實現而言(因為對數據對象的操作實現 
    了較為嚴密的封裝,可以保證其作用范圍內的緩存同步,而 ibatis 提供的是半封閉 
    的封裝實現,因此對緩存的操作難以做到完全的自動化同步)。 
    ibatis 的緩存機制使用必須特別謹慎。特別是 flushOnExecute 的設定(見 
    “ibatis配置”一節中的相關內容),需要考慮到所有可能引起實際數據與緩存數據 
    不符的操作。如本模塊中其他Statement對數據的更新,其他模塊對數據的更新,甚 
    至第三方系統對數據的更新。否則,臟數據的出現將為系統的正常運行造成極大隱患。 
    如果不能完全確定數據更新操作的波及范圍,建議避免 Cache的盲目使用。 
    結合cacheModel來看: 
    <cacheModel >
    id="product-cache" 
    type ="LRU" 
    readOnly="true" 
    serialize="false"> 
    </cacheModel> 

    可以看到,Cache有如下幾個比較重要的屬性: 
    ÿ readOnly 
    ÿ serialize 
    ÿ type 

    readOnly 
    readOnly值的是緩存中的數據對象是否只讀。 這里的只讀并不是意味著數據對象一 
    旦放入緩存中就無法再對數據進行修改。而是當數據對象發生變化的時候,如數據對 
    象的某個屬性發生了變化,則此數據對象就將被從緩存中廢除,下次需要重新從數據 
    庫讀取數據,構造新的數據對象。 
    而 readOnly="false"則意味著緩存中的數據對象可更新,如 user 對象的 name 
    屬性發生改變。 
    只讀Cache能提供更高的讀取性能,但一旦數據發生改變,則效率降低。系統設計 
    時需根據系統的實際情況(數據發生更新的概率有多大)來決定 Cache的讀寫策略。 

    serialize 
    如果需要全局的數據緩存,CacheModel的 serialize屬性必須被設為true。否則數據 
    緩存只對當前 Session(可簡單理解為當前線程)有效,局部緩存對系統的整體性能提 
    升有限。 
    在 serialize="true"的情況下,如果有多個 Session同時從 Cache 中讀取某個 
    數據對象,Cache 將為每個 Session返回一個對象的復本,也就是說,每個 Session將 
    得到包含相同信息的不同對象實例。因而 Session 可以對其從 Cache 獲得的數據進行 
    存取而無需擔心多線程并發情況下的同步沖突。 


    Cache Type: 
    與hibernate類似,ibatis通過緩沖接口的插件式實現,提供了多種 Cache的實現機 
    制可供選擇: 
    1. MEMORY 
    2. LRU 
    3. FIFO 
    4. OSCACHE 

    MEMORY類型Cache與 WeakReference 
    MEMORY 類型的 Cache 實現,實際上是通過 Java 對象引用進行。ibatis 中,其實現類 
    為com.ibatis.db.sqlmap.cache.memory.MemoryCacheController, MemoryCacheController 內部, 
    使用一個HashMap來保存當前需要緩存的數據對象的引用。 

    這里需要注意的是Java2中的三種對象引用關系: 
    a SoftReference 
    b WeakReference 
    c PhantomReference 
    傳統的Java 對象引用,如: 
    public void doSomeThing(){ 
    User user = new User() 
    …… 

    當doSomeThing方法結束時,user 對象的引用丟失,其所占的內存空間將由JVM在下 
    次垃圾回收時收回。如果我們將user 對象的引用保存在一個全局的 HashMap中,如: 
    Map map = new HashMap(); 

    public void doSomeThing(){ 
    User user = new User(); 
    map.put("user",user); 

    此時,user 對象由于在 map 中保存了引用,只要這個引用存在,那么 JVM 永遠也不會 
    收回user 對象所占用的內存。 
    這樣的內存管理機制相信諸位都已經耳熟能詳,在絕大多數情況下,這幾乎是一種完美 的解決方案。但在某些情況下,卻有些不便。如對于這里的 Cache 而言,當 user 對象使用 
    之后,我們希望保留其引用以供下次需要的時候可以重復使用,但又不希望這個引用長期保 
    存,如果每個對象的引用都長期保存下去的話,那隨著時間推移,有限的內存空間將立即被 
    這些數據所消耗殆盡。最好的方式,莫過于有一種引用方式,可以在對象沒有被垃圾回收器 
    回收之前, 依然能夠訪問此對象,當垃圾回收器啟動時, 如果此對象沒有被其他對象所使用, 
    則按照常規對其進行回收。 

    SoftReference、WeakReference、PhantomReference為上面的思路提供了有力支持。 

    這三種類型的引用都屬于“非持續性引用”,也就是說,這種引用關系并非持續存在, 
    它們所代表的引用的生命周期與JVM 的運行密切相關,而非與傳統意義上的引用一樣依賴 
    于編碼階段的預先規劃。 
    先看一個SoftReference的例子: 
    SoftReference ref; 

    public void doSomeThing(){ 
    User user = new User(); 
    ref = new SoftReference(user); 


    public void doAnotherThing(){ 
    User user = (User)ref.get();//通過SoftReference獲得對象引用 
    System.out.println(user.getName()); 



    假設我們先執行了 doSomeThing 方法,產生了一個 User 對象,并為其創建了一個 
    SoftReference引用。 
    之后的某個時刻,我們調用了doAnotherThing方法,并通過 SoftReference獲取 User 對 
    象的引用。 
    此時我們是否還能取得user 對象的引用?這要看JVM的運行情況。對于 SoftReference 
    而言,只有當目前內存不足的情況下,JVM 在垃圾回收時才會收回其包含的引用(JVM 并 
    不是只有當內存不足時才啟動垃圾回收機制,何時進行垃圾回收取決于各版本 JVM 的垃圾 
    回收策略。如某這垃圾回收策略為:當系統目前較為空閑,且無效對象達到一定比率時啟動 
    垃圾回收機制,此時的空余內存倒可能還比較充裕)。這里可能出現兩種情況,即: 

    ÿ JVM 目前還未出現過因內存不足所引起的垃圾回收,user 對象的引用可以通過 
    SoftReference從JVM Heap中收回。 
    ÿ JVM已經因為內存不足啟動了垃圾回收機制,SoftReference所包含的 user 對象的 
    引用被JVM所廢棄。此時 ref.get方法將返回一個空引用(null),對于上面 
    的代碼而言,也就意味著這里可能拋出一個 NullPointerException。 

    WeakReference比SoftReference在引用的維持性上來看更加微弱。 無需等到內存不足的 
    情況, 只要JVM啟動了垃圾回收機制, 那么WeakReference所對應的對象就將被JVM回收。 
    也就是說,相對SoftReference而言,WeakReference 被 JVM回收的概率更大。 

    PhantomReference 比 WeakReference 的引用維持性更弱。與 WeakReference 和 
    SoftReference不同,PhantomReference所引用的對象幾乎無法被回收重用。它指向的對象實 
    際上已經被JVM銷毀(finalize方法已經被執行),只是暫時還沒被垃圾回收器收回而已。 
    PhantomReference主要用于輔助對象的銷毀過程,在實際應用層研發中,幾乎不會涉及。 

    MEMORY類型的Cache正是借助SoftReference、 WeakReference以及通常意義上的Java 
    Reference實現了對象的緩存管理。 
    下面是一個典型的MEMORY類型 Cache配置: 
    <cacheModel id="user_cache" type="MEMORY"> 
    <flushInterval hours="24"/> 
    <flushOnExecute statement="updateUser"/> 
    <property name="reference-type" value="WEAK" /> 
    </cacheModel> 
    其中 flushInterval 指定了多長時間清除緩存,上例中指定每 24 小時強行清空緩存 
    區的所有內容。 
    reference-type屬性可以有以下幾種配置: 
    1. STRONG 
    即基于傳統的Java對象引用機制,除非對Cache顯式清空(如到了flushInterval 
    設定的時間;執行了flushOnExecute所指定的方法;或代碼中對Cache執行了清除 
    操作等),否則引用將被持續保留。 
    此類型的設定適用于緩存常用的數據對象,或者當前系統內存非常充裕的情況。 
    2. SOFT 
    基于 SoftReference 的緩存實現,只有 JVM 內存不足的時候,才會對緩沖池中的數 
    據對象進行回收。 
    此類型的設定適用于系統內存較為充裕,且系統并發量比較穩定的情況。 
    3. WEAK 
    基于 WeakReference 的緩存實現,當 JVM 垃圾回收時,緩存中的數據對象將被 JVM 
    收回。 
    一般情況下,可以采用WEAK的MEMORY型Cache配置。 

    LRU型 Cache 
    當 Cache達到預先設定的最大容量時,ibatis會按照“最少使用”原則將使用頻率最少 
    的對象從緩沖中清除。 
    <cacheModel id="userCache" type="LRU"> 
    <flushInterval hours="24"/> 
    <flushOnExecute statement="updateUser"/> 
    <property name="size" value="1000" /> 
    </cacheModel> 
    可配置的參數有: 
    u flushInterval 
    指定了多長時間清除緩存, 上例中指定每24小時強行清空緩存區的所有內容。 
    u size Cache的最大容量。 

    FIFO型 Cache 
    先進先出型緩存,最先放入Cache中的數據將被最先廢除。可配置參數與 LRU型相同: 
    <cacheModel id="userCache" type="FIFO"> 
    <flushInterval hours="24"/> 
    <flushOnExecute statement="updateUser"/> 
    <property name="size" value="1000" /> 
    </cacheModel> 

    OSCache 

    與上面幾種類型的Cache不同,OSCache來自第三方組織 Opensymphony。可以通過以 
    下網址獲得OSCache的最新版本(http://www.opensymphony.com/oscache/)。 

    在生產部署時,建議采用 OSCache,OSCache 是得到了廣泛使用的開源 Cache 實現 
    (Hibernate 中也提供了對 OSCache 的支持),它基于更加可靠高效的設計,更重要的是, 
    最新版本的 OSCache 已經支持 Cache 集群。如果系統需要部署在集群中,或者需要部署在 
    多機負載均衡模式的環境中以獲得性能上的優勢,那么OSCache在這里則是不二之選。 

    Ibatis中對于OSCache的配置相當簡單: 
    <cacheModel id="userCache" type="OSCACHE"> 
    <flushInterval hours="24"/> 
    <flushOnExecute statement="updateUser"/> 
    <property name="size" value="1000" /> 
    </cacheModel> 

    之所以配置簡單,原因在于,OSCache擁有自己的配置文件(oscache.properties)J。 
    下面是一個典型的OSCache配置文件: 
    #是否使用內存作為緩存空間 
    cache.memory=true 

    #緩存管理事件監聽器,通過這個監聽器可以獲知當前Cache的運行情況 
    cache.event.listeners=com.opensymphony.oscache.plugins.clustersupport.JMSBroa 
    dcastingListener 

    #如果使用磁盤緩存(cache.memory=false),則需要指定磁盤存儲接口實現 
    #cache.persistence.class=com.opensymphony.oscache.plugins.diskpersistence.Disk 
    PersistenceListener 

    # 磁盤緩存所使用的文件存儲路徑 
    # cache.path=c:\\myapp\\cache 

    # 緩存調度算法,可選的有LRU,FIFO和無限緩存(UnlimitedCache) # cache.algorithm=com.opensymphony.oscache.base.algorithm.FIFOCache 
    # cache.algorithm=com.opensymphony.oscache.base.algorithm.UnlimitedCache 
    cache.algorithm=com.opensymphony.oscache.base.algorithm.LRUCache 

    #內存緩存的最大容量 
    cache.capacity=1000 

    # 是否限制磁盤緩存的容量 
    # cache.unlimited.disk=false 

    # 基于JMS的集群緩存同步配置 
    #cache.cluster.jms.topic.factory=java:comp/env/jms/TopicConnectionFactory 
    #cache.cluster.jms.topic.name=java:comp/env/jms/OSCacheTopic 
    #cache.cluster.jms.node.name=node1 

    # 基于JAVAGROUP的集群緩存同步配置 
    #cache.cluster.properties=UDP(mcast_addr=231.12.21.132;mcast_port=45566;ip_ 
    ttl=32;mcast_send_buf_size=150000;mcast_recv_buf_size=80000):PING(timeout 
    =2000;num_initial_members=3):MERGE2(min_interval=5000;max_interval=10000 
    ):FD_SOCK:VERIFY_SUSPECT(timeout=1500):pbcast.NAKACK(gc_lag=50;retransm 
    it_timeout=300,600,1200,2400,4800):pbcast.STABLE(desired_avg_gossip=20000): 
    UNICAST(timeout=5000):FRAG(frag_size=8096;down_thread=false;up_thread=fal 
    se):pbcast.GMS(join_timeout=5000;join_retry_timeout=2000;shun=false;print_loc 
    al_addr=true) 
    #cache.cluster.multicast.ip=231.12.21.132 

    配置好之后,將此文件放在 CLASSPATH 中,OSCache 在初始化時會自動找到此 
    文件并根據其中的配置創建緩存實例。 
    ibatis in Spring 
    這里我們重點探討Spring框架下的ibatis應用,特別是在容器事務管理模式下的ibatis 
    應用開發。 

    關于Spring Framework,請參見筆者另一篇文檔: 
    《Spring 開發指南》http://www.xiaxin.net/Spring_Dev_Guide.rar 

    針對ibatis,Spring配置文件如下: 

    Ibatis-Context.xml: 
    <?xml version="1.0" encoding="UTF-8"?> 
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" >
    "http://www.springframework.org/dtd/spring-beans.dtd"> 

    <beans> 

    <bean id="dataSource" >
    class="org.apache.commons.dbcp.BasicDataSource" 
    destroy-method="close"> 
    <property name="driverClassName"> 
    <value>net.sourceforge.jtds.jdbc.Driver</value> 
    </property> 
    <property name="url"> 
    <value>jdbc:jtds:sqlserver://127.0.0.1:1433/Sample</value> 
    </property> 
    <property name="username"> 
    <value>test</value> 
    </property> 
    <property name="password"> 
    <value>changeit</value> 
    </property> 
    </bean> 

    <bean id="sqlMapClient" >
    class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"> 
    <property name="configLocation"> 
    <value>SqlMapConfig.xml</value> 
    </property> 
    </bean> 

    <bean id="transactionManager" >
    class="org.springframework.jdbc.datasource.DataSourceTransactio 
    nManager"> <property name="dataSource"> 
    <ref local="dataSource"/> 
    </property> 
    </bean> 

    <bean id="userDAO" class="net.xiaxin.dao.UserDAO"> 
    <property name="dataSource"> 
    <ref local="dataSource" /> 
    </property> 
    <property name="sqlMapClient"> 
    <ref local="sqlMapClient" /> 
    </property> 
    </bean> 

    <bean id="userDAOProxy" >
    class="org.springframework.transaction.interceptor.TransactionPro 
    xyFactoryBean"> 

    <property name="transactionManager"> 
    <ref bean="transactionManager" /> 
    </property> 

    <property name="target"> 
    <ref local="userDAO" /> 
    </property> 

    <property name="transactionAttributes"> 
    <props> 
    <prop key="insert*">PROPAGATION_REQUIRED</prop> 
    <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop> 
    </props> 
    </property> 
    </bean> 
    </beans> 

    可以看到: 
    1. sqlMapClient節點 
    sqlMapClient節點實際上配置了一個sqlMapClient的創建工廠類。 
    configLocation屬性配置了ibatis映射文件的名稱。 

    2. transactionManager節點 
    transactionManager采用了Spring中的DataSourceTransactionManager。 

    3. userDAO節點 對應的,UserDAO需要配置兩個屬性,sqlMapClient和DataSource, 
    sqlMapClient將從指定的DataSource中獲取數據庫連接。 

    本例中Ibatis映射文件非常簡單: 

    sqlMapConfig.xml: 
    <sqlMapConfig> 
    <sqlMap resource="net/xiaxin/dao/entity/user.xml"/> 
    </sqlMapConfig> 

    net/xiaxin/dao/entity/user .xml 
    <sqlMap namespace="User"> 
    <typeAlias alias="user" type="net.xiaxin.dao.entity.User" /> 

    <insert id="insertUser" parameterClass="user"> 
    INSERT INTO users ( username, password) VALUES ( #username#, 
    #password# ) 
    </insert> 

    </sqlMap> 

    UserDAO.java: 
    public class UserDAO extends SqlMapClientDaoSupport implements 
    IUserDAO { 

    public void insertUser(User user) { 
    getSqlMapClientTemplate().update("insertUser", user); 


    SqlMapClientDaoSupport(如果使用ibatis 1.x版本,對應支持類是 
    SqlMapDaoSupport)是Spring中面向ibatis的輔助類,它負責調度DataSource、 
    SqlMapClientTemplate(對應ibatis 1.x版本是SqlMapTemplate)完成ibatis操作, 
    而DAO則通過對此類進行擴展獲得上述功能。上面配置文件中針對UserDAO的屬性設 
    置部分,其中的屬性也是繼承自于這個基類。 

    SqlMapClientTemplate對傳統SqlMapClient調用模式進行了封裝,簡化了上層訪問 
    代碼。 

    User .java: 
    public class User { 

    public Integer id; 

    public String username; public String password; 

    public Integer getId() { 
    return id; 


    public void setId(Integer id) { 
    this.id = id; 

    public String getPassword() { 
    return password; 


    public void setPassword(String password) { 
    this.password = password; 


    public String getUsername() { 
    return username; 


    public void setUsername(String username) { 
    this.username = username; 



    測試代碼: 
    InputStream is = new FileInputStream("Ibatis-Context.xml"); 
    XmlBeanFactory factory = new XmlBeanFactory(is); 
    IUserDAO userdao = (IUserDAO)factory.getBean("userDAOProxy"); 

    User user = new User(); 
    user.setUsername("Sofia"); 
    user.setPassword("mypass"); 

    userdao.insertUser(user); 

    對比前面 ibatis 程序代碼,我們可以發現 UserDAO.java 變得異常簡潔,這也正是 
    Spring Framework為我們帶來的巨大幫助。 

    Spring以及其他IOC 框架對傳統的應用框架進行了顛覆性的革新, 也許這樣的評價有 
    點過于煽情,但是這確是筆者第一次跑通 Spring HelloWorld 時的切身感受。有興趣的 
    讀者可以研究一下Spring framework,enjoy it! 

    posted on 2012-09-20 00:56 奮斗成就男人 閱讀(575) 評論(0)  編輯  收藏 所屬分類: J2EE

    主站蜘蛛池模板: 成人性生交大片免费看无遮挡| 免费观看男人吊女人视频| 亚洲一级片免费看| 久久国内免费视频| 亚洲第一精品福利| xxxxx做受大片视频免费| mm1313亚洲精品无码又大又粗 | 欧美在线看片A免费观看| 美女啪啪网站又黄又免费| a级片免费在线观看| 亚洲 无码 在线 专区| 99久久99久久精品免费观看 | 亚洲欧洲精品无码AV| ssswww日本免费网站片| 亚洲美女一区二区三区| 麻豆69堂免费视频| 亚洲AV无码乱码在线观看性色扶 | 亚洲成av人片在线天堂无| 青青青国产在线观看免费| 日本中文字幕免费看| 一个人看www在线高清免费看| 亚洲综合伊人久久综合| 亚洲一区二区三区在线网站| 亚洲毛片在线免费观看| 中文字幕在线观看亚洲| 亚洲欧洲精品成人久久奇米网 | 国产VA免费精品高清在线| 亚洲午夜久久久久久尤物| 中国精品一级毛片免费播放| 国产亚洲人成无码网在线观看| 亚洲heyzo专区无码综合| 亚洲国产精品无码中文字| 一级做a爰性色毛片免费| 亚洲国产精品无码一线岛国| 亚洲成?v人片天堂网无码| 无码国产精品一区二区免费I6| 亚洲精品无码av中文字幕| 精品久久久久久久免费加勒比| 99人中文字幕亚洲区| 成人特黄a级毛片免费视频| 最近中文字幕大全免费版在线|