posts - 66,  comments - 11,  trackbacks - 0
          package com.hibernate.higherApplication;

          import java.util.Iterator;
          import java.util.List;
          import java.util.Set;

          import junit.framework.TestCase;

          import org.hibernate.Criteria;
          import org.hibernate.Hibernate;
          import org.hibernate.HibernateException;
          import org.hibernate.Query;
          import org.hibernate.Session;
          import org.hibernate.SessionFactory;
          import org.hibernate.cfg.Configuration;
          import org.hibernate.criterion.Expression;

          public class DurationOperator extends TestCase {
              
          private SessionFactory sessionFactory = null;
              
          private Session session = null;
              
          /**
               * 初始化資源
               
          */
              
          protected void setUp() throws Exception {
                  
          try {
                      
          //加載類(lèi)路徑下的hibernate.cfg.xml文件
                      Configuration config = new Configuration().configure();
                      
          //創(chuàng)建sessionFactory對(duì)象
                      sessionFactory = config.buildSessionFactory();
                      
          //創(chuàng)建session
                      session = sessionFactory.openSession();
                  } 
          catch (HibernateException e) {
                      e.printStackTrace();
                  }
              }
              
          /**
               * load/get方法均可以根據(jù)指定的實(shí)體類(lèi)和id從數(shù)據(jù)庫(kù)讀取記錄,并返回與之對(duì)應(yīng)的實(shí)體對(duì)象。
               * 區(qū)別在于:
               * 1、如果未發(fā)現(xiàn)符合條件的記錄,get方法返回null,而load方法拋出一個(gè)ObjectNotFoundException
               * 2、load方法可以返回實(shí)體的代理類(lèi)實(shí)例,而get方法永遠(yuǎn)直接返回實(shí)體類(lèi)。
               * 3、load方法可以充分利用內(nèi)部緩存和二級(jí)緩存中的現(xiàn)有數(shù)據(jù),而get方法則僅僅在內(nèi)部緩存中進(jìn)行數(shù)據(jù)查找,如果
               * 沒(méi)有發(fā)現(xiàn)數(shù)據(jù),將越過(guò)二級(jí)緩存,直接調(diào)用SQL完成數(shù)據(jù)讀取。
               *
               
          */
              
          public void loadOrGetData(){
                  TUser user 
          = (TUser)session.load(TUser.class,new Integer(1));
              }
              
          /**
               * 查詢性能往往是一系統(tǒng)性能表現(xiàn)的一個(gè)重要方面。
               * query.list方法通過(guò)一條select SQL實(shí)現(xiàn)了查詢操作,而iterate方法,則執(zhí)行了3次selectSQL,第一次獲取了所有符合條件的記錄
               * 的id,之后,在根據(jù)各個(gè)id從庫(kù)表中讀取對(duì)應(yīng)的哦記錄,這是一個(gè)典型的N+1次查詢問(wèn)題。
               * 
               * 我們進(jìn)行query.list數(shù)據(jù)查詢時(shí),即使緩存中已經(jīng)有一些符合條件的實(shí)體對(duì)象存在,我們也無(wú)法保證這些數(shù)據(jù)就是庫(kù)表中所有符合條件的數(shù)據(jù)。假設(shè)
               * 第一次查詢條件是age>25,隨即緩存中就包括了所有age>25的user數(shù)據(jù);第二次查詢條件為age>20,此時(shí)緩存中雖然包含了滿足age>25d的
               * 數(shù)據(jù),但這些并不是滿足條件age>20的全部數(shù)據(jù)
               * 因此,query.list方法還是需要執(zhí)行一次select sql以保證查詢結(jié)果的完整性(iterate方法通過(guò)首先查詢獲取所有符合條件記錄的id,以此保證
               * 查詢結(jié)果的完整性)。
               * 因此,query.list方法實(shí)際上無(wú)法利用緩存,它對(duì)緩存只寫(xiě)不讀。而iterate方法則可以充分發(fā)揮緩存帶來(lái)的優(yōu)勢(shì),如果目標(biāo)數(shù)據(jù)只讀或者讀取相對(duì)
               * 較為頻繁,通過(guò)這種機(jī)制可以大大減少性能上的損耗。
               
          */
              
          public void queryForList(){
                  String hql 
          = "from TUser where age>?";
                  Query query 
          = session.createQuery(hql);
                  query.setInteger(
          1,1);
                  
                  List list 
          = query.list();
                  
                  
          for(int i=0;i<list.size();i++){
                      TUser user 
          = (TUser)list.get(i);
                      System.out.println(
          "User age:"+user.getAge());
                  }
              }
              
          public void queryForIterate(){
                  String hql 
          = "from TUser where age>?";
                  Query query 
          = session.createQuery(hql);
                  query.setInteger(
          1,1);
                  
                  Iterator it 
          = query.iterate();
                  
                  
          while(it.hasNext()){
                      TUser user 
          = (TUser)it.next();
                      System.out.println(
          "User age:"+user.getAge());
                  }
              }
              
          /**
               * 大數(shù)據(jù)量的批量讀取(10W條)
               * 解決方案:結(jié)合iterate方法和evict方法逐條對(duì)記錄進(jìn)行處理,將內(nèi)存消耗保持在可以接受的范圍之內(nèi)。
               * 在實(shí)際開(kāi)發(fā)中,對(duì)于大批量數(shù)據(jù)處理,還是推薦采用SQL或存儲(chǔ)過(guò)程實(shí)現(xiàn),以獲得較高的性能,并保證系統(tǒng)平滑運(yùn)行。
               
          */
              
          public void bigDataRead(){
                  String hql 
          = "from TUser where age>?";
                  Query query 
          = session.createQuery(hql);
                  query.setInteger(
          "age"1);
                  Iterator it 
          = query.iterate();
                  
                  
          while(it.hasNext()){
                      TUser user 
          = (TUser)it.next();
                      
          //將對(duì)象從一級(jí)緩存中移除
                      session.evict(user);
                      
          //二級(jí)緩存可以設(shè)定最大數(shù)據(jù)緩存數(shù)量,達(dá)到峰值時(shí)會(huì)自動(dòng)對(duì)緩存中的較老數(shù)據(jù)進(jìn)行廢除,但是我們這里還是通過(guò)
                      
          //編碼指定將對(duì)象從二級(jí)緩存中移除,這有助保持緩存的數(shù)據(jù)有效性。
                      sessionFactory.evict(TUser.class,user.getId());
                  }
              }
              
          /**
               * Query Cache彌補(bǔ)了find方法的不足,QueryCache中緩存的SQL及其結(jié)果及并非永遠(yuǎn)存在,當(dāng)Hibernate發(fā)現(xiàn)此SQL對(duì)應(yīng)的庫(kù)表發(fā)生變動(dòng),
               * 會(huì)自動(dòng)將Query Cache中對(duì)應(yīng)表的SQL緩存廢除。因此Query Cache只在特定的情況下產(chǎn)生作用:
               * 1、完全相同的select SQL重復(fù)執(zhí)行。
               * 2、在2次查詢之間,此select SQL對(duì)應(yīng)的庫(kù)表沒(méi)有發(fā)生過(guò)改變。
               
          */
              
          public void queryForQueryCache(){
                  String hql 
          = "from TUser where age>?";
                  Query query 
          = session.createQuery(hql);
                  query.setInteger(
          11);
                  
          //除了在這里設(shè)置QueryCache外,還要在hibernate.cfg.xml中進(jìn)行設(shè)置
                  
          //<property name="hibernate.cache.use_query_cache">true</property>
                  query.setCacheable(true);
                  List userList 
          = query.list();
              }
              
          /**
               * 所謂延遲加載,就是在需要數(shù)據(jù)的時(shí)候,才真正執(zhí)行數(shù)據(jù)加載操作。
               * 延遲加載實(shí)現(xiàn)主要針對(duì):
               * 1、實(shí)體對(duì)象:通過(guò)class的lazy屬性,我們可以打開(kāi)實(shí)體對(duì)象的延遲加載功能。
               * 2、集合
               
          */
              
          public void queryForEntityLazy(){
                  Criteria criteria 
          = session.createCriteria(TUser.class);
                  criteria.add(Expression.eq(
          "name","Erica"));
                  
                  List userList 
          = criteria.list();
                  TUser user 
          = (TUser)userList.get(0);
                  
          //雖然使用了延遲加載,但是我們可以通過(guò)hibernate的初始化方法進(jìn)行強(qiáng)制加載,這樣即使session關(guān)閉之后,關(guān)聯(lián)的對(duì)象仍讓可以使用
                  Hibernate.initialize(user.getAddresses());
                  
                  System.out.println(
          "User name=>"+user.getAge());
                  
                  Set hset 
          =user.getAddresses();
                  TAddresses addr 
          = (TAddresses)hset.toArray()[0];
                  System.out.println(addr.getAddress());
                  
                  session.close();
              }
              
          /**
               * 關(guān)閉資源
               
          */
              
          protected void tearDown() throws Exception {
                  
          try{
                      session.close();
                  }
          catch(HibernateException e){
                      e.printStackTrace();
                  }
              }

          }
          posted @ 2010-01-02 15:27 王永慶 閱讀(367) | 評(píng)論 (0)編輯 收藏
            基于Java的緩存實(shí)現(xiàn),最簡(jiǎn)單的方式莫過(guò)于對(duì)集合類(lèi)數(shù)據(jù)類(lèi)型進(jìn)行封裝。Hibernate提供了基于Hashtable的緩存實(shí)現(xiàn)機(jī)制,不過(guò),由于其性能和功能上的局限,僅供開(kāi)發(fā)調(diào)試中使用。同時(shí),Hibernate還提供了面向第三方緩存實(shí)現(xiàn)的接口,如:
          HashTable--------------------------------net.sf.hibernate.cache.HashtableCacheProvider
          1、JSC
          2、EHCache->默認(rèn)的二級(jí)Cache實(shí)現(xiàn)。--------net.sf.encache.hibernate.Provider
          3、OSCache-------------------------------net.sf.hibernate.cache.OSCacheProvider
          4、JBoss Cache->分布式緩存---------------net.sf.hibernate.cache.TreeCacheProvider
          5、SwarmCache----------------------------net.sf.hibernate.cache.SwarmCacheProvider
          相對(duì)于JSC而言,EHCache更加穩(wěn)定,并具備更好的混存調(diào)度性能,其缺陷是目前還無(wú)法做到分布式緩存。
          首先設(shè)置hibernate.cfg.xml然后設(shè)置ehcache.xml最后設(shè)置緩存策略。

            緩存同步策略決定了數(shù)據(jù)對(duì)象在緩存中的存取規(guī)則。為了使得緩存調(diào)度遵循正確的應(yīng)用級(jí)事物隔離機(jī)制,我們必須為每個(gè)實(shí)體類(lèi)指定相應(yīng)的緩存同步策略。Hibernate提供4種內(nèi)置的緩存同步策略:
          1、read-only:只讀。對(duì)于不會(huì)發(fā)生改變的數(shù)據(jù),可使用只讀型緩存。
          2、nonstrict-read-write:如果程序?qū)Σl(fā)訪問(wèn)下的數(shù)據(jù)同步要求不是非常嚴(yán)格,且數(shù)據(jù)更新操作頻率較低,可以采用本選項(xiàng)。
          3、read-write:嚴(yán)格可讀寫(xiě)緩存。
          4、transactional:事務(wù)型緩存,必須運(yùn)行在JTA事物環(huán)境中。

            JDBC事物由Connection管理,也就是說(shuō),事務(wù)管理實(shí)際上是在JDBC Connection中實(shí)現(xiàn)。事務(wù)周期限于Connection的生命周期之類(lèi)。同樣,對(duì)于基于JDBC Transaction的Hibernate事務(wù)管理機(jī)制而言,事物管理在Session所以托的JDBCConnection中實(shí)現(xiàn),事務(wù)周期限于Session的生命周期。
            JTA事物管理則由JTA容器實(shí)現(xiàn),JTA容器對(duì)當(dāng)前加入事物的眾多Connection進(jìn)行調(diào)度,實(shí)現(xiàn)其事務(wù)性要求。JTA的事物周期可橫跨多個(gè)JDBC Connectin生命周期。同樣對(duì)于基于JTA事務(wù)的Hibernate而言,JTA事物橫跨多個(gè)Session.

            Hibernate支持2種鎖機(jī)制:即通常所說(shuō)的悲觀鎖和樂(lè)觀鎖。
            悲觀鎖的實(shí)現(xiàn),往往依靠數(shù)據(jù)庫(kù)提供的鎖機(jī)制。典型的悲觀鎖調(diào)用:
            select * from account where name=="Erica" for update
          package com.hibernate.higherApplication;

          import java.util.List;

          import junit.framework.TestCase;

          import org.hibernate.Criteria;
          import org.hibernate.HibernateException;
          import org.hibernate.LockMode;
          import org.hibernate.Query;
          import org.hibernate.Session;
          import org.hibernate.SessionFactory;
          import org.hibernate.Transaction;
          import org.hibernate.cfg.Configuration;
          import org.hibernate.criterion.Expression;

          public class LockOperator extends TestCase {
              
          private Session session = null;
              
          /**
               * 初始化資源
               
          */
              
          protected void setUp() throws Exception {
                  
          try {
                      
          //加載類(lèi)路徑下的hibernate.cfg.xml文件
                      Configuration config = new Configuration().configure();
                      
          //創(chuàng)建sessionFactory對(duì)象
                      SessionFactory sessionFactory = config.buildSessionFactory();
                      
          //創(chuàng)建session
                      session = sessionFactory.openSession();
                  } 
          catch (HibernateException e) {
                      e.printStackTrace();
                  }        
              }
              
          /**
               * 悲觀鎖
               * Hibernate的加鎖模式有:
               * 1、LockMode.NONE:無(wú)鎖機(jī)制
               * 2、LockMode.WRITE:Hibernate在Insert和Update記錄的時(shí)候會(huì)自動(dòng)獲取
               * 3、LockMode.READ:Hibernate在讀取記錄的時(shí)候會(huì)自動(dòng)獲取
               * 上述3種鎖機(jī)制為了保證update過(guò)程中對(duì)象不會(huì)被外界修改,在目標(biāo)對(duì)象上加鎖,與數(shù)據(jù)庫(kù)無(wú)關(guān)
               * 4、LockMode.UPGRADE:利用數(shù)據(jù)庫(kù)的for update子句加鎖
               * 5、LockMode.UPGRADE_NOWAIT:oracle的特定實(shí)現(xiàn)
               * 注意:只有在查詢開(kāi)始之前設(shè)定加鎖,才會(huì)真正通過(guò)數(shù)據(jù)庫(kù)的鎖機(jī)制進(jìn)行加鎖處理。
               
          */
              
          public void addPessimismLock(){
                  String hqlStr 
          = "from TUser as user where user.name='Erica'";
                  Query query 
          = session.createQuery(hqlStr);
                  query.setLockMode(
          "user",LockMode.UPGRADE);//多所有返回的user對(duì)象加鎖
                  List userList = query.list();//執(zhí)行查詢
              }
              
          /**
               * 樂(lè)觀鎖
               * 數(shù)據(jù)版本:即為數(shù)據(jù)增加一個(gè)版本標(biāo)識(shí),在基于數(shù)據(jù)庫(kù)表的版本解決方案中,一般是通過(guò)為數(shù)據(jù)庫(kù)表增加一個(gè)version字段來(lái)實(shí)現(xiàn)。
               * 讀取出數(shù)據(jù)時(shí),將此版本號(hào)一同讀出,之后更新時(shí),對(duì)此版本號(hào)加1.此時(shí),將提交數(shù)據(jù)的版本數(shù)據(jù)與數(shù)據(jù)庫(kù)對(duì)應(yīng)記錄的當(dāng)前版本信息
               * 進(jìn)行比對(duì),如果提交的數(shù)據(jù)版本號(hào)大于數(shù)據(jù)庫(kù)表當(dāng)前版本號(hào),則予以更新,否則認(rèn)為是過(guò)期數(shù)據(jù)。
               * 
               * Hibernate在其數(shù)據(jù)訪問(wèn)引擎中內(nèi)置了樂(lè)觀鎖實(shí)現(xiàn)。如果不考慮外部系統(tǒng)對(duì)數(shù)據(jù)庫(kù)的更新操作,利用Hibernate提供的透明化樂(lè)觀鎖
               * 實(shí)現(xiàn),將大大提升我們的生產(chǎn)力。見(jiàn)配置文件T_USER.hbm.xml
               * 樂(lè)觀鎖機(jī)制避免了長(zhǎng)事務(wù)中的數(shù)據(jù)加鎖開(kāi)銷(xiāo),大大提升了大并發(fā)量下的系統(tǒng)整體性能表象。
               *
               
          */
              
          public void addOptimismLock(){
                  Criteria criteria 
          = session.createCriteria(TUser.class);
                  criteria.add(Expression.eq(
          "name","Erica"));
                  
                  List userList 
          = criteria.list();
                  TUser user 
          = (TUser)userList.get(0);
                  
                  Transaction tx 
          = session.beginTransaction();
                  user.setVersion(
          1);
                  tx.commit();
              }
              
          /**
               * 關(guān)閉資源
               
          */
              
          protected void tearDown() throws Exception {
                  
          try{
                      session.close();
                  }
          catch(HibernateException e){
                      e.printStackTrace();
                  }
              }
              
          }

          <?xml version="1.0"?>
          <!DOCTYPE hibernate-mapping PUBLIC
              "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
              "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
          >
          <hibernate-mapping>
              
          <!-- 
                  none:無(wú)樂(lè)觀鎖
                  version:通過(guò)版本機(jī)制實(shí)現(xiàn)樂(lè)觀鎖
                  dirty:通過(guò)檢查發(fā)生變動(dòng)過(guò)的屬性實(shí)現(xiàn)樂(lè)觀鎖
                  all通過(guò)檢查所有屬性實(shí)現(xiàn)樂(lè)觀鎖
               
          -->
              
          <class
                  
          name="org.hibernate.sample.TUSER"
                  table
          ="t_user"
                  dynamic-update
          ="true"
                  dynamic-insert
          ="true"
                  optimistic-lock
          ="version"
                  lazy
          ="true"
                  
          >
                  
          <id
                  
          name="id"
                  column
          ="id"
                  type
          ="java.lang.Integer"
                  
          >
                      
          <generator class="native">
                      
          </generator>
                  
          </id>
                  
          <version name="version" column="version" type="java.lang.Integer">
                  
          </version>
                  
          <set name="addresses"
                       table
          ="t_address"
                       lazy
          ="true"
                       inverse
          ="false"
                       cascade
          ="all"
                  
          >
                      
          <key
                          
          column="user_id"
                      
          >
                      
          </key>
                      
          <one-to-many class=""/>
                  
          </set>
              
          </class>
          </hibernate-mapping>


          posted @ 2010-01-02 15:25 王永慶 閱讀(565) | 評(píng)論 (0)編輯 收藏
              實(shí)體對(duì)象,特指Hibernate O/R映射關(guān)系中的域?qū)ο蟆?shí)體對(duì)象生命周期中的3種狀態(tài)
              1、Transient(自由狀態(tài)):所謂Transient,即實(shí)體對(duì)象在內(nèi)存中的自由存在,它與數(shù)據(jù)庫(kù)中的記錄無(wú)關(guān)。
              2、Persistent(持久狀態(tài)):即實(shí)體對(duì)象處于由Hibernate框架所管理的狀態(tài)。
              3、Detached(游離狀態(tài)):處于Persistent狀態(tài)的對(duì)象,其對(duì)應(yīng)的Session實(shí)例關(guān)閉之后,那么,此對(duì)象就處于"Detached"狀態(tài)。
              Transient狀態(tài)的user對(duì)象與庫(kù)表的數(shù)據(jù)缺乏對(duì)應(yīng)關(guān)系,而Detached狀態(tài)的user對(duì)象,卻在庫(kù)表中存在對(duì)應(yīng)的記錄,只不過(guò)由于Detached對(duì)象脫離了session這個(gè)數(shù)據(jù)操作平臺(tái),其狀態(tài)的變化無(wú)法更新到庫(kù)表中的對(duì)應(yīng)記錄。
              處于Transient和Detached狀態(tài)的對(duì)象統(tǒng)稱為值對(duì)象(VO),而處于Persistent狀態(tài)的對(duì)象稱為持久對(duì)象(PO).這是站在實(shí)體對(duì)象是否被納入Hibernate實(shí)體管理容器的立場(chǎng)加以區(qū)分的,非管理的實(shí)體對(duì)象統(tǒng)稱為VO,而被管理的實(shí)體對(duì)象稱為PO.
          VO與PO的主要區(qū)別在于:
          1、VO是相對(duì)獨(dú)立的實(shí)體對(duì)象,處于非管理狀態(tài)。
          2、PO是由Hibernate納入其實(shí)體管理容器的對(duì)象,它代表了與數(shù)據(jù)庫(kù)中某條記錄對(duì)應(yīng)的Hibernate實(shí)體,PO的變化在事務(wù)提交時(shí)將反映到實(shí)際數(shù)據(jù)庫(kù)中
          3、如果一個(gè)PO與其對(duì)應(yīng)的Session實(shí)例分離,那么此時(shí),它又會(huì)變成一個(gè)VO。

              不覆蓋equals/hashCode方法的情況下我們要面對(duì)的問(wèn)題:實(shí)體對(duì)象的跨session識(shí)別。解決辦法一個(gè)是實(shí)現(xiàn)所謂的值比對(duì),即在equals/hashCode方法中,對(duì)實(shí)體類(lèi)的所有屬性值進(jìn)行比對(duì).除了值比對(duì),還有另外一種基于業(yè)務(wù)邏輯的對(duì)象判定方式業(yè)務(wù)關(guān)鍵信息判定。

              tx.commint();方法中會(huì)調(diào)用session.flush()方法,在flush()方法中會(huì)執(zhí)行2個(gè)主要任務(wù)
          1、flushEverything();//刷新所有數(shù)據(jù)
          2、execute(0);//執(zhí)行數(shù)據(jù)庫(kù)SQL完成持久化動(dòng)作。

              數(shù)據(jù)緩存:在特定硬件基礎(chǔ)上緩存往往是提升系統(tǒng)性能的關(guān)鍵因素。緩存是數(shù)據(jù)庫(kù)數(shù)據(jù)在內(nèi)存中的臨時(shí)容器,它包含了庫(kù)表數(shù)據(jù)在內(nèi)存中的臨時(shí)拷貝,位于數(shù)據(jù)庫(kù)與數(shù)據(jù)訪問(wèn)層之間。ORM在進(jìn)行數(shù)據(jù)讀取時(shí),會(huì)根據(jù)其緩存管理策略,首先在緩存中查詢,如果在緩存中發(fā)現(xiàn)所需數(shù)據(jù),則直接以此數(shù)據(jù)作為查詢結(jié)果加以利用,從而避免了數(shù)據(jù)庫(kù)調(diào)用的性能開(kāi)銷(xiāo)。
              相對(duì)內(nèi)存操作而言,數(shù)據(jù)庫(kù)調(diào)用是一個(gè)代價(jià)高昂的過(guò)程,對(duì)于典型企業(yè)及應(yīng)用結(jié)構(gòu),數(shù)據(jù)庫(kù)往往與應(yīng)用服務(wù)器位于不同的物理服務(wù)器,這也就意味著每次數(shù)據(jù)庫(kù)訪問(wèn)都是一次遠(yuǎn)程調(diào)用,Socket的創(chuàng)建與銷(xiāo)毀,數(shù)據(jù)的打包拆包,數(shù)據(jù)庫(kù)執(zhí)行查詢命令,網(wǎng)絡(luò)傳輸上的延時(shí),這些消耗都給系統(tǒng)整體性能造成了嚴(yán)重影響。
              ORM的數(shù)據(jù)緩存應(yīng)包含如下幾個(gè)層次:
          1、事務(wù)級(jí)緩存:事務(wù)級(jí)緩存是基于Session生命周期實(shí)現(xiàn)的,每個(gè)Session會(huì)在內(nèi)部維持一個(gè)數(shù)據(jù)緩存,此緩存隨著Session的創(chuàng)建而存在,因此也成為Session Level Cache(內(nèi)部緩存)
          2、應(yīng)用級(jí)/進(jìn)程級(jí)緩存:在某個(gè)應(yīng)用中,或者應(yīng)用中某個(gè)獨(dú)立數(shù)據(jù)訪問(wèn)子集中的共享緩存。此緩存可由多個(gè)事物共享。在Hibernate中,應(yīng)用級(jí)緩存在SessinFactory層實(shí)現(xiàn),所有由此SessionFactory創(chuàng)建的Session實(shí)例共享此緩存。多實(shí)例并發(fā)運(yùn)行的環(huán)境要特別小心進(jìn)程級(jí)緩存的調(diào)用。
          3、分布式緩存:分布式緩存由多個(gè)應(yīng)用級(jí)緩存實(shí)例組成集群,通過(guò)某種遠(yuǎn)程機(jī)制實(shí)現(xiàn)各個(gè)緩存實(shí)例間的數(shù)據(jù)同步,任何一個(gè)實(shí)例的數(shù)據(jù)修改操作,將導(dǎo)致整個(gè)集群間的數(shù)據(jù)狀態(tài)同步。由于多個(gè)實(shí)例間的數(shù)據(jù)同步機(jī)制,每個(gè)緩存實(shí)例發(fā)生的變動(dòng)都會(huì)復(fù)制到其余所有節(jié)點(diǎn)中,這樣的遠(yuǎn)程同步開(kāi)銷(xiāo)不可忽視。

              Hibernate數(shù)據(jù)緩存分為2個(gè)層次,1、內(nèi)部緩存2、二級(jí)緩存hibernate中,緩存將在以下情況中發(fā)揮作用:
          1、通過(guò)ID加載數(shù)據(jù)時(shí)
          這包括了根據(jù)id查詢數(shù)據(jù)的Session.load方法,以及Session.ierate等批量查詢方法
          2、延遲加載

              Session在進(jìn)行數(shù)據(jù)查詢操作時(shí),會(huì)首先在自身內(nèi)部的一級(jí)緩存中進(jìn)行查找,如果一級(jí)緩存未能命中,則將在二級(jí)緩存中查詢,如果二級(jí)緩存命中,則以此數(shù)據(jù)作為結(jié)果返回。
              如果數(shù)據(jù)滿足以下條件,則可將其納入緩存管理
          1、數(shù)據(jù)不會(huì)被第三方應(yīng)用修改
          2、數(shù)據(jù)大小在可接受的范圍之內(nèi)
          3、數(shù)據(jù)更新頻率較低
          4、同一數(shù)據(jù)可能會(huì)被系統(tǒng)頻繁引用
          5、非關(guān)鍵數(shù)據(jù)(關(guān)鍵數(shù)據(jù),如金融賬戶數(shù)據(jù))
          Hibernate本身并未提供二級(jí)緩存的產(chǎn)品化實(shí)現(xiàn)(只是提供了一個(gè)基于Hashtable的簡(jiǎn)單緩存以供調(diào)試),而是為眾多的第三方緩存組件提供了接入接口,我們可以根據(jù)實(shí)際情況選擇不同的緩存實(shí)現(xiàn)版本。

             
          posted @ 2009-12-22 15:01 王永慶 閱讀(223) | 評(píng)論 (0)編輯 收藏
              比較字符串是否相等使用equals方法
              使用"=="與equals到底有哪些不同?
              equals:可以比較內(nèi)容,是2個(gè)字符串內(nèi)容的比較。
              ==:數(shù)值比較,比較的是內(nèi)存地址的值是否相等。

              一個(gè)字符串就是String類(lèi)的匿名對(duì)象。
              String name1 = new String("wyq");->開(kāi)辟了2個(gè)空間,其中一個(gè)是垃圾空間。
              String name2 = "wyq";->開(kāi)辟了一個(gè)空間,所以應(yīng)該選擇它。

              String的另一個(gè)特殊之處:String使用了Java中的共享模式,它只要發(fā)現(xiàn)在內(nèi)存中有這塊數(shù)據(jù),不會(huì)在內(nèi)存中重新生成。
              String類(lèi)中的內(nèi)容一旦聲明則不可改變。
              StringBuffer與String的本質(zhì)區(qū)別,在于StringBuffer可以改變。

              this可以調(diào)用本類(lèi)中的屬性,也可以調(diào)用本類(lèi)中的方法(含構(gòu)造方法this())。
              注意:構(gòu)造方法本身必須在首行被使用,為了給類(lèi)中的屬性初始化。
              this調(diào)用屬性、本類(lèi)方法、構(gòu)造方法這三點(diǎn)是this的基本應(yīng)用,也是最常用的,但是以上三點(diǎn)實(shí)際上可以綜合成一點(diǎn)---表示當(dāng)前對(duì)象。
              this表示當(dāng)前對(duì)象主要應(yīng)用在一點(diǎn):用于進(jìn)行對(duì)象的比較。
          public boolean compare(Person p1){
              
          boolean flag = false;
              Person p2 
          = this;
              
          if(p1.name.equals(p2.name)&&p1.age==p2.age)
              
          {
                 flag 
          = true;
              }

              
          return flag;
          }

          posted @ 2009-12-08 09:56 王永慶 閱讀(195) | 評(píng)論 (0)編輯 收藏

              在軟件中,要么全有要么全無(wú)的操作成為事務(wù)。事務(wù)允許你把幾個(gè)操作組成一個(gè)單一的工作單元,這個(gè)工作單元要么全部發(fā)生要么全部不發(fā)生。如果每件事都順利,那么這個(gè)事務(wù)是成功的。但是如果任何一件事情出錯(cuò)的話,那么已經(jīng)發(fā)生的行為就被清除掉,就像什么事情都沒(méi)發(fā)生一樣。
              Spring對(duì)事務(wù)管理有豐富的支持,程序控制的和聲明式的。
              原子性(Atomic):事務(wù)由一個(gè)或多個(gè)行為綁定在一起組成,好像是一個(gè)單獨(dú)工作單元。原子性確保在十五中的所有操作要么都發(fā)生,要么都不發(fā)生。
              一致性(Consistent):一旦一個(gè)事務(wù)結(jié)束了(不管成功失敗),系統(tǒng)所處的狀態(tài)和它的業(yè)務(wù)規(guī)則是一致的。就是說(shuō)數(shù)據(jù)應(yīng)當(dāng)不會(huì)被破壞。
              隔離性(Isolated):事務(wù)應(yīng)該允許多個(gè)用戶操作同一數(shù)據(jù),一個(gè)用戶的操作不會(huì)和其他用戶的操作相混淆。因此,事務(wù)必須是互相隔離的,防止并發(fā)讀寫(xiě)同一數(shù)據(jù)的情況發(fā)生。
              持久性(Durable):一旦事務(wù)完成,事務(wù)的結(jié)果應(yīng)該持久化,這樣不管什么樣的系統(tǒng)崩潰,他們都將幸免于難。
           
              Spring對(duì)程序控制事務(wù)管理的支持和EJB的有很大不同。EJB的事務(wù)管理和JTA密不可分,和EJB不同的是,Spring使用了一種回調(diào)機(jī)制,把真實(shí)的事務(wù)實(shí)現(xiàn)從事務(wù)代碼中抽象出來(lái)。選擇程序控制事務(wù)管理還是聲明式事務(wù)管理,很大程度上是在細(xì)粒度控制與簡(jiǎn)便操作之間做出決定。當(dāng)你在代碼中編寫(xiě)事務(wù)時(shí),你能精確控制事務(wù)的邊界,在你希望的地方精確的開(kāi)始和結(jié)束。典型的情況下,你不需要程序控制事務(wù)所提供的細(xì)粒度控制,你會(huì)選擇在上下文定義文件中聲明你的事務(wù)。

              Spring對(duì)聲明式事務(wù)管理的支持是通過(guò)它的AOP框架實(shí)現(xiàn)的。這樣做是非常自然的,因?yàn)槭聞?wù)是系統(tǒng)級(jí)的,凌駕于應(yīng)用的主要功能之上的。

              在Spring里,事務(wù)屬性是對(duì)事務(wù)策略如何應(yīng)用到方法的描述。這個(gè)描述包括:傳播行為、隔離級(jí)別、只讀提示、事務(wù)超時(shí)間隔
              傳播行為:
              PROPAGATION_MANDATORY:表示該方法必須運(yùn)行在一個(gè)事務(wù)中。如果當(dāng)前事務(wù)不存在,將拋出一個(gè)異常。
              PROPAGATION_NESTED:表示如果當(dāng)前已經(jīng)存在一個(gè)事務(wù),則該方法應(yīng)當(dāng)運(yùn)行在一個(gè)嵌套的事務(wù)中。被嵌套的事務(wù)可以從當(dāng)前事務(wù)中單獨(dú)的提交或回滾。如果當(dāng)前事務(wù)不存在,那么它看起來(lái)和PROPAGATION_REQUIRED沒(méi)有兩樣。
              PROPAGATION_NEVER:表示當(dāng)前的方法不應(yīng)該運(yùn)行在一個(gè)事務(wù)上下文中。如果當(dāng)前存在一個(gè)事務(wù),則會(huì)拋出一個(gè)異常。
              PROPAGATION_NOT_SUPPORTED:表示該方法不應(yīng)在事務(wù)中運(yùn)行。如果一個(gè)現(xiàn)有的事務(wù)正在運(yùn)行中,它將在該方法的運(yùn)行期間被掛起。
              PROPAGATION_REQUIRED:表示當(dāng)前方法必須運(yùn)行在一個(gè)事務(wù)中。如果一個(gè)現(xiàn)有的事務(wù)正在運(yùn)行中,該方法將運(yùn)行在這個(gè)事務(wù)中。否則的話,要開(kāi)始一個(gè)新的事務(wù)。
              PROPAGATION_REQUIRES_NEW:表示當(dāng)前方法必須運(yùn)行在它自己的事務(wù)里。它將啟動(dòng)一個(gè)新的事務(wù)。如果有事務(wù)運(yùn)行的話,將在這個(gè)方法運(yùn)行期間被掛起。
              PROPAGATION_SUPPORTS:表示當(dāng)前方法不需要事務(wù)處理環(huán)境,但如果有一個(gè)事務(wù)已經(jīng)在運(yùn)行的話,這個(gè)方法也可以在這個(gè)事務(wù)里運(yùn)行。

             傳播規(guī)則回答了一個(gè)問(wèn)題:就是新的事務(wù)是否要被啟動(dòng)或是被掛起,或者方法是否要在事務(wù)環(huán)境中運(yùn)行。

             隔離級(jí)別:在一個(gè)典型的應(yīng)用中,多個(gè)事務(wù)并發(fā)運(yùn)行,經(jīng)常會(huì)操作同一個(gè)數(shù)據(jù)來(lái)完成它們的任務(wù)。并發(fā),雖然是必須的,但會(huì)導(dǎo)致下面問(wèn)題:
          1、臟讀:臟讀發(fā)生在一個(gè)事務(wù)讀取了被另一個(gè)事務(wù)改寫(xiě)但還未提交的數(shù)據(jù)時(shí)。如果這些改變?cè)谏院蟊换貪L,那么第一個(gè)事務(wù)讀取的數(shù)據(jù)就是無(wú)效的。
          2、不可重復(fù)讀:不可重復(fù)讀發(fā)生在一個(gè)事務(wù)執(zhí)行相同的查詢2次或2次以上,但每一次查詢結(jié)果都不同時(shí)。這通常是由于另一個(gè)并發(fā)事務(wù)在2次查詢之間更新了數(shù)據(jù)。
          3、幻讀:幻讀和不可重復(fù)讀相似。當(dāng)一個(gè)事務(wù)讀取幾行紀(jì)錄后,另一個(gè)并發(fā)事務(wù)插入一些記錄,幻讀就發(fā)生了。隔離級(jí)別有如下幾個(gè):
          ISOLATION_DEFAULT:使用后端數(shù)據(jù)庫(kù)默認(rèn)的隔離級(jí)別
          ISOLATION_READ_UNCOMMITTED:允許你讀取還未提交的改變了的數(shù)據(jù),可能導(dǎo)致臟讀、幻讀、不可重復(fù)讀
          ISOLATION_READ_COMMITTED:允許在并發(fā)事務(wù)已經(jīng)提交后讀取。可防止臟讀,但幻讀和不可重復(fù)讀仍可能發(fā)生。
          ISOLATION_REPEATABLE_READ:對(duì)相同字段的多次讀取的結(jié)果是一致的,除非數(shù)據(jù)被事務(wù)本身改變。可防止臟讀和不可重復(fù)讀,但幻讀仍可能發(fā)生。
          ISOLATION_SERIALIZABLE:完全服從ACID的隔離級(jí)別,確保不發(fā)生臟讀、不可重復(fù)讀和幻讀。這在所有隔離級(jí)別中也是最慢的。

              只讀:如果一個(gè)事務(wù)只對(duì)后端是據(jù)庫(kù)執(zhí)行讀操作,數(shù)據(jù)庫(kù)就可能利用事務(wù)只讀的特性,使用某些優(yōu)化措施。通過(guò)聲明一個(gè)事務(wù)為只讀,你就給了后端數(shù)據(jù)庫(kù)一個(gè)機(jī)會(huì),來(lái)應(yīng)用那些它認(rèn)為合適的優(yōu)化措施。因?yàn)橹蛔x的優(yōu)化措施是在事務(wù)啟動(dòng)時(shí)由后端數(shù)據(jù)庫(kù)實(shí)施的,所以,只有將那些具有可能啟動(dòng)新事務(wù)的傳播行為的方法的事務(wù)標(biāo)記成只讀才有意義(PROPAGATION_REQUIRED,PROPAGATION_REQUIRES_NEW和PROPAGATION_NESTED) TransactionProxyFactoryBean參照一個(gè)方法的事務(wù)屬性,決定如何在那個(gè)方法上執(zhí)行事務(wù)策略。

          <?xml version="1.0" encoding="UTF-8"?>
          <beans
              
          xmlns="http://www.springframework.org/schema/beans"
              xmlns:xsi
          ="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation
          ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
              
          <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
                  
          <property name="jndiName">
                      
          <value>java:comp/env/jdbc/myDatasource</value>
                  
          </property>
              
          </bean>
              
          <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
                  
          <property name="dataSource">
                      
          <ref bean="dataSource"/>
                  
          </property>
              
          </bean>
              
          <!-- 這個(gè)對(duì)象有一個(gè)值為courseService的id.當(dāng)應(yīng)用從應(yīng)用上下文里請(qǐng)求一個(gè)courseService時(shí),它將得到一個(gè)被
              TransactionProxyFactoryBean包裹的實(shí)例。 
          -->
              
          <bean id="courseService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
                  
          <!-- 代理所實(shí)現(xiàn)的接口 -->
                  
          <property name="proxyInterfaces">
                      
          <list>
                          
          <value>
                              com.springinaction.training.service.CourseService
                          
          </value>
                      
          </list>
                  
          </property>
                  
          <!-- 被代理的對(duì)象 -->
                  
          <property name="target">
                      
          <ref bean="courseServiceTarget"/>
                  
          </property>
                  
          <!-- 事務(wù)管理器 -->
                  
          <property name="transactionManager">
                      
          <ref bean="transactionManager"/>
                  
          </property>
                  
          <!-- 事務(wù)的屬性源 -->
                  
          <property name="transactionAttributeSource">
                      
          <ref bean="transactionAttributeSource"/>
                  
          </property>
              
          </bean>
              
          <!-- 要知道盡管可以改變MatchAlwaysTransactionAttributeSource的事務(wù)屬性參數(shù),但它總是返回相同的事務(wù)屬性,而
              不關(guān)心參與交易的哪一個(gè)方法。當(dāng)你有一個(gè)相對(duì)簡(jiǎn)單的應(yīng)用,把同樣的事務(wù)策略應(yīng)用到所有方法都沒(méi)問(wèn)題時(shí),使用MatchAlwaysT
              ransactionAttributeSource就相當(dāng)好。但是,在那些更為復(fù)雜的應(yīng)用中,你很可能需要對(duì)不同的方法應(yīng)用不同的事務(wù)策略。在那樣
              情況下,你需要在應(yīng)用何種策略的問(wèn)題上做更多精確的控制。 
          -->
              
          <bean id="transactionAttributeSource" class="org.springframework.transaction.interceptor.MatchAlwaysTransactionAttributeSource">
                  
          <property name="transactionAttribute">
                      
          <ref bean="myTransactionAttribute"/>
                  
          </property>
              
          </bean>
              
          <!-- 定義事務(wù)策略 -->
              
          <bean id="myTransactionAttribute" class="org.springframework.transaction.interceptor.DefaultTransactionAttribute">
                  
          <!-- 傳播行為 -->
                  
          <property name="propagationBehaviorName">
                      
          <value>PROPAGATION_REQUIRES_NEW</value>
                  
          </property>
                  
          <!-- 隔離級(jí)別 -->
                  
          <property name="isolationLevelName">
                      
          <value>ISOLATION_REPEATABLE_READ</value>
                  
          </property>
              
          </bean>
          </beans>

           

          除了將transactionAttributeSource對(duì)象織入到TransactionProxyFactoryBean的transactionAttributeSource屬性中外,還有一種簡(jiǎn)單的方法。發(fā)展到現(xiàn)在,TransactionProxyFactoryBean也有一個(gè)transactionAttributes屬性為transactionProperties.

          <?xml version="1.0" encoding="UTF-8"?>
          <beans
              
          xmlns="http://www.springframework.org/schema/beans"
              xmlns:xsi
          ="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation
          ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
              
          <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
                  
          <property name="jndiName">
                      
          <value>java:comp/env/jdbc/myDatasource</value>
                  
          </property>
              
          </bean>
              
          <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
                  
          <property name="dataSource">
                      
          <ref bean="dataSource"/>
                  
          </property>
              
          </bean>
              
          <!-- 這個(gè)對(duì)象有一個(gè)值為courseService的id.當(dāng)應(yīng)用從應(yīng)用上下文里請(qǐng)求一個(gè)courseService時(shí),它將得到一個(gè)被
              TransactionProxyFactoryBean包裹的實(shí)例。 
          -->
              
          <bean id="courseService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
                  
          <!-- 代理所實(shí)現(xiàn)的接口 -->
                  
          <property name="proxyInterfaces">
                      
          <list>
                          
          <value>
                              com.springinaction.training.service.CourseService
                          
          </value>
                      
          </list>
                  
          </property>
                  
          <!-- 被代理的對(duì)象 -->
                  
          <property name="target">
                      
          <ref bean="courseServiceTarget"/>
                  
          </property>
                  
          <!-- 事務(wù)管理器 -->
                  
          <property name="transactionManager">
                      
          <ref bean="transactionManager"/>
                  
          </property>
                  
          <!-- 事務(wù)的屬性源 -->
                  
          <property name="transactionAttributeSource">
                      
          <ref bean="transactionAttributeSource"/>
                  
          </property>
              
          </bean>
              
          <!-- NameMatchTransactionAttributeSource的properties屬性把方法名映射到事務(wù)屬性描述器上。注意CourseException
              用一個(gè)負(fù)號(hào)標(biāo)記。異常可以用負(fù)號(hào)或正號(hào)標(biāo)記,當(dāng)負(fù)號(hào)異常拋出時(shí),將觸發(fā)回滾;相反的,正號(hào)異常表示事務(wù)仍可提交,即使這個(gè)異常拋出 
          -->
              
          <bean id="transactionAttributeSource" class="org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource">
                  
          <property name="properties">
                      
          <props>
                          
          <prop key="enrollStudentInCourse">
                              PROPAGATION_REQUIRES_NEW,ISOLATION_REPEATABLE_READ,readOnly,
                              -CourseException
                          
          </prop>
                          
          <!-- 還可以使用通配符 -->
                          
          <prop key="get*">
                              PROPAGATION_SUPPORTS
                          
          </prop>
                      
          </props>
                  
          </property>
              
          </bean>
          </beans>

           

           

          posted @ 2009-11-22 11:43 王永慶 閱讀(261) | 評(píng)論 (0)編輯 收藏
          <2009年11月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          293012345

          常用鏈接

          留言簿(1)

          隨筆分類(lèi)

          隨筆檔案

          關(guān)注blogs

          搜索

          •  

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 宁陕县| 静乐县| 汾西县| 菏泽市| 沿河| 宜兰市| 邻水| 徐闻县| 宜君县| 皮山县| 玉屏| 四平市| 新邵县| 叶城县| 壤塘县| 涟源市| 夏邑县| 黄浦区| 尼木县| 濉溪县| 安国市| 南郑县| 奉化市| 宁乡县| 紫阳县| 林周县| 昌黎县| 铁岭市| 兴文县| 武胜县| 潮安县| 丹巴县| 延津县| 聂拉木县| 库尔勒市| 衡水市| 观塘区| 昭通市| 盖州市| 两当县| 乳山市|