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

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

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

    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 {
                
    //加載類路徑下的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í)體類和id從數(shù)據(jù)庫(kù)讀取記錄,并返回與之對(duì)應(yīng)的實(shí)體對(duì)象。
         * 區(qū)別在于:
         * 1、如果未發(fā)現(xiàn)符合條件的記錄,get方法返回null,而load方法拋出一個(gè)ObjectNotFoundException
         * 2、load方法可以返回實(shí)體的代理類實(shí)例,而get方法永遠(yuǎn)直接返回實(shí)體類。
         * 3、load方法可以充分利用內(nèi)部緩存和二級(jí)緩存中的現(xiàn)有數(shù)據(jù),而get方法則僅僅在內(nèi)部緩存中進(jìn)行數(shù)據(jù)查找,如果
         * 沒有發(fā)現(xiàn)數(shù)據(jù),將越過二級(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方法通過一條select SQL實(shí)現(xiàn)了查詢操作,而iterate方法,則執(zhí)行了3次selectSQL,第一次獲取了所有符合條件的記錄
         * 的id,之后,在根據(jù)各個(gè)id從庫(kù)表中讀取對(duì)應(yīng)的哦記錄,這是一個(gè)典型的N+1次查詢問題。
         * 
         * 我們進(jìn)行query.list數(shù)據(jù)查詢時(shí),即使緩存中已經(jīng)有一些符合條件的實(shí)體對(duì)象存在,我們也無法保證這些數(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方法通過首先查詢獲取所有符合條件記錄的id,以此保證
         * 查詢結(jié)果的完整性)。
         * 因此,query.list方法實(shí)際上無法利用緩存,它對(duì)緩存只寫不讀。而iterate方法則可以充分發(fā)揮緩存帶來的優(yōu)勢(shì),如果目標(biāo)數(shù)據(jù)只讀或者讀取相對(duì)
         * 較為頻繁,通過這種機(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í)際開發(fā)中,對(duì)于大批量數(shù)據(jù)處理,還是推薦采用SQL或存儲(chǔ)過程實(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)行廢除,但是我們這里還是通過
                
    //編碼指定將對(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ù)表沒有發(fā)生過改變。
         
    */
        
    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ì)象:通過class的lazy屬性,我們可以打開實(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);
            
    //雖然使用了延遲加載,但是我們可以通過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 王永慶 閱讀(370) | 評(píng)論 (0)編輯 收藏
      基于Java的緩存實(shí)現(xiàn),最簡(jiǎn)單的方式莫過于對(duì)集合類數(shù)據(jù)類型進(jìn)行封裝。Hibernate提供了基于Hashtable的緩存實(shí)現(xiàn)機(jī)制,不過,由于其性能和功能上的局限,僅供開發(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)度性能,其缺陷是目前還無法做到分布式緩存。
    首先設(shè)置hibernate.cfg.xml然后設(shè)置ehcache.xml最后設(shè)置緩存策略。

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

      JDBC事物由Connection管理,也就是說,事務(wù)管理實(shí)際上是在JDBC Connection中實(shí)現(xiàn)。事務(wù)周期限于Connection的生命周期之類。同樣,對(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ī)制:即通常所說的悲觀鎖和樂觀鎖。
      悲觀鎖的實(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 {
                
    //加載類路徑下的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:無鎖機(jī)制
         * 2、LockMode.WRITE:Hibernate在Insert和Update記錄的時(shí)候會(huì)自動(dòng)獲取
         * 3、LockMode.READ:Hibernate在讀取記錄的時(shí)候會(huì)自動(dòng)獲取
         * 上述3種鎖機(jī)制為了保證update過程中對(duì)象不會(huì)被外界修改,在目標(biāo)對(duì)象上加鎖,與數(shù)據(jù)庫(kù)無關(guān)
         * 4、LockMode.UPGRADE:利用數(shù)據(jù)庫(kù)的for update子句加鎖
         * 5、LockMode.UPGRADE_NOWAIT:oracle的特定實(shí)現(xiàn)
         * 注意:只有在查詢開始之前設(shè)定加鎖,才會(huì)真正通過數(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í)行查詢
        }
        
    /**
         * 樂觀鎖
         * 數(shù)據(jù)版本:即為數(shù)據(jù)增加一個(gè)版本標(biāo)識(shí),在基于數(shù)據(jù)庫(kù)表的版本解決方案中,一般是通過為數(shù)據(jù)庫(kù)表增加一個(gè)version字段來實(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)為是過期數(shù)據(jù)。
         * 
         * Hibernate在其數(shù)據(jù)訪問引擎中內(nèi)置了樂觀鎖實(shí)現(xiàn)。如果不考慮外部系統(tǒng)對(duì)數(shù)據(jù)庫(kù)的更新操作,利用Hibernate提供的透明化樂觀鎖
         * 實(shí)現(xiàn),將大大提升我們的生產(chǎn)力。見配置文件T_USER.hbm.xml
         * 樂觀鎖機(jī)制避免了長(zhǎng)事務(wù)中的數(shù)據(jù)加鎖開銷,大大提升了大并發(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:無樂觀鎖
            version:通過版本機(jī)制實(shí)現(xiàn)樂觀鎖
            dirty:通過檢查發(fā)生變動(dòng)過的屬性實(shí)現(xiàn)樂觀鎖
            all通過檢查所有屬性實(shí)現(xiàn)樂觀鎖
         
    -->
        
    <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 王永慶 閱讀(569) | 評(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ù)中的記錄無關(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)的記錄,只不過由于Detached對(duì)象脫離了session這個(gè)數(shù)據(jù)操作平臺(tái),其狀態(tài)的變化無法更新到庫(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ì)的問題:實(shí)體對(duì)象的跨session識(shí)別。解決辦法一個(gè)是實(shí)現(xiàn)所謂的值比對(duì),即在equals/hashCode方法中,對(duì)實(shí)體類的所有屬性值進(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ù)訪問層之間。ORM在進(jìn)行數(shù)據(jù)讀取時(shí),會(huì)根據(jù)其緩存管理策略,首先在緩存中查詢,如果在緩存中發(fā)現(xiàn)所需數(shù)據(jù),則直接以此數(shù)據(jù)作為查詢結(jié)果加以利用,從而避免了數(shù)據(jù)庫(kù)調(diào)用的性能開銷。
        相對(duì)內(nèi)存操作而言,數(shù)據(jù)庫(kù)調(diào)用是一個(gè)代價(jià)高昂的過程,對(duì)于典型企業(yè)及應(yīng)用結(jié)構(gòu),數(shù)據(jù)庫(kù)往往與應(yīng)用服務(wù)器位于不同的物理服務(wù)器,這也就意味著每次數(shù)據(jù)庫(kù)訪問都是一次遠(yuǎn)程調(diào)用,Socket的創(chuàng)建與銷毀,數(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ù)訪問子集中的共享緩存。此緩存可由多個(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í)例組成集群,通過某種遠(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)程同步開銷不可忽視。

        Hibernate數(shù)據(jù)緩存分為2個(gè)層次,1、內(nèi)部緩存2、二級(jí)緩存hibernate中,緩存將在以下情況中發(fā)揮作用:
    1、通過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 王永慶 閱讀(227) | 評(píng)論 (0)編輯 收藏
        比較字符串是否相等使用equals方法
        使用"=="與equals到底有哪些不同?
        equals:可以比較內(nèi)容,是2個(gè)字符串內(nèi)容的比較。
        ==:數(shù)值比較,比較的是內(nèi)存地址的值是否相等。

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

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

        this可以調(diào)用本類中的屬性,也可以調(diào)用本類中的方法(含構(gòu)造方法this())。
        注意:構(gòu)造方法本身必須在首行被使用,為了給類中的屬性初始化。
        this調(diào)用屬性、本類方法、構(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 王永慶 閱讀(199) | 評(píng)論 (0)編輯 收藏

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

        Spring對(duì)聲明式事務(wù)管理的支持是通過它的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ù)不存在,那么它看起來和PROPAGATION_REQUIRED沒有兩樣。
        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ù)中。否則的話,要開始一個(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ù)是否要被啟動(dòng)或是被掛起,或者方法是否要在事務(wù)環(huán)境中運(yùn)行。

       隔離級(jí)別:在一個(gè)典型的應(yīng)用中,多個(gè)事務(wù)并發(fā)運(yùn)行,經(jīng)常會(huì)操作同一個(gè)數(shù)據(jù)來完成它們的任務(wù)。并發(fā),雖然是必須的,但會(huì)導(dǎo)致下面問題:
    1、臟讀:臟讀發(fā)生在一個(gè)事務(wù)讀取了被另一個(gè)事務(wù)改寫但還未提交的數(shù)據(jù)時(shí)。如果這些改變?cè)谏院蟊换貪L,那么第一個(gè)事務(wù)讀取的數(shù)據(jù)就是無效的。
    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)提交后讀取??煞乐古K讀,但幻讀和不可重復(fù)讀仍可能發(fā)生。
    ISOLATION_REPEATABLE_READ:對(duì)相同字段的多次讀取的結(jié)果是一致的,除非數(shù)據(jù)被事務(wù)本身改變??煞乐古K讀和不可重復(fù)讀,但幻讀仍可能發(fā)生。
    ISOLATION_SERIALIZABLE:完全服從ACID的隔離級(jí)別,確保不發(fā)生臟讀、不可重復(fù)讀和幻讀。這在所有隔離級(jí)別中也是最慢的。

        只讀:如果一個(gè)事務(wù)只對(duì)后端是據(jù)庫(kù)執(zhí)行讀操作,數(shù)據(jù)庫(kù)就可能利用事務(wù)只讀的特性,使用某些優(yōu)化措施。通過聲明一個(gè)事務(wù)為只讀,你就給了后端數(shù)據(jù)庫(kù)一個(gè)機(jī)會(huì),來應(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)用到所有方法都沒問題時(shí),使用MatchAlwaysT
        ransactionAttributeSource就相當(dāng)好。但是,在那些更為復(fù)雜的應(yīng)用中,你很可能需要對(duì)不同的方法應(yīng)用不同的事務(wù)策略。在那樣
        情況下,你需要在應(yīng)用何種策略的問題上做更多精確的控制。 
    -->
        
    <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 王永慶 閱讀(264) | 評(píng)論 (0)編輯 收藏

        HQL作為Hibernate的查詢語(yǔ)言,提供了ANSI SQL面向?qū)ο蟮姆庋b形式。
        與Criteria和HQL互為補(bǔ)充,Hibernate也提供了對(duì)原生SQL以及存儲(chǔ)過程的支持,相對(duì)于JDBC的SQL操作,Hibernate提供了更為妥善的封裝。代碼如下:

    package com.testproject.hibernate;

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

    import org.hibernate.Query;
    import org.hibernate.Session;

    public class HibernateSqlQuery {
        Session session 
    = null;
        
    public void querySql(){
            String sql 
    = "select {usr.*} from T_User usr";
            List list 
    = session.createSQLQuery(sql).addEntity("usr", TUser.class).list();
            Iterator it 
    = list.iterator();
            
    while(it.hasNext()){
                TUser user 
    = (TUser)it.next();
            }

        }

        
    public void queryMappingSql(){
            Query query 
    = session.getNamedQuery("queryUser");
            query.setParameter(
    "name","Erica");
            Iterator it 
    = query.list().iterator();
            
    while(it.hasNext()){
                TUser user 
    = (TUser)it.next();
            }

        }

    }

     

    <?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>
        
    <class name="com.testproject.hibernate.TUser" table="T_USER">
            
    <id name="id" column="id">
                
    <generator class="native"></generator>
            
    </id>
        
    </class>
        
    <sql-query name="queryUser">
            
    <![CDATA[
                select {usr.*} from T_User usr where name=:name
            
    ]]>
            
    <return alias = "usr" class="com.testproject.hibernate.TUser"></return>
        
    </sql-query>
        
    <!-- 基于存儲(chǔ)過程查詢 sql-query節(jié)點(diǎn)的callable屬性設(shè)定為true,指明當(dāng)前查詢基于存儲(chǔ)過程定義-->
        
    <sql-query name="getUsersByAge" callable="true">
            
    <return alias="user" class="com.testproject.hibernate.TUser">
                
    <return-property name="id" column="ID"></return-property>
                
    <return-property name="name" column="NAME"></return-property>
                
    <return-property name="age" column="AGE"></return-property>
            
    </return>
            {?=call getUsersByAge(?)}
        
    </sql-query>
    </hibernate-mapping>






        與HQL相同,Native SQL也可以在實(shí)體映射文件中進(jìn)行配置:

    posted @ 2009-11-21 21:37 王永慶 閱讀(248) | 評(píng)論 (0)編輯 收藏
         摘要:     實(shí)體Bean包含BMP和CMP兩種類型。對(duì)BMP實(shí)體Bean而言,開發(fā)者必須提供各自的數(shù)據(jù)訪問邏輯。為了實(shí)現(xiàn)BMP,通常會(huì)使用操作數(shù)據(jù)庫(kù)的API,比如JDBC.對(duì)于CMP實(shí)體Bean而言,EJB容器會(huì)自動(dòng)實(shí)現(xiàn)數(shù)據(jù)訪問邏輯。這就是CMP的優(yōu)勢(shì)所在。通常,只有在應(yīng)用服務(wù)器提供的CMP和目標(biāo)RDBMS不能滿足性能要求時(shí),才去考慮BMP.此時(shí),開發(fā)者能夠細(xì)粒度調(diào)整BM...  閱讀全文
    posted @ 2009-11-21 12:32 王永慶 閱讀(223) | 評(píng)論 (0)編輯 收藏

        Criteria提供了符合面向?qū)ο缶幊田L(fēng)格的查詢封裝模式。不過HQL提供了更加豐富靈活的特性,它在涵蓋了Criteria功能范圍的前提下,提供了更為強(qiáng)大的查詢能力。HQL基于SQL,同時(shí)提供了更加面向?qū)ο蟮姆庋b。
        實(shí)體查詢:HQL子句本身大小寫無關(guān),但是其中出現(xiàn)的類名和屬性名必須注意大小寫區(qū)分。需要注意的是,Hibernate中,查詢的目標(biāo)實(shí)體存在著繼承關(guān)系的判定,如"from TUser"將返回所有TUser以及TUser子類的記錄,我們知道,Java中所有類的根類都是java.lang.Object,那么,如下HQL將返回?cái)?shù)據(jù)庫(kù)中所有庫(kù)表的記錄:"from java.lang.Object",在where子句中,我們可以通過比較操作符指定條件,=,<>,>,>,<=,>=,between,notbetween,in,not in,is,like等。與SQL相同,我們可以通過and,or等邏輯連接符組合各個(gè)邏輯表達(dá)式。

        屬性查詢:有時(shí)我們并不需要獲取完整的實(shí)體對(duì)象,只需要現(xiàn)實(shí)部分列,通過HQL也可以做到這點(diǎn),如:"select user.name,user.age form TUser user"表明我們需要讀取name和age屬性的內(nèi)容,而此時(shí),返回的list數(shù)據(jù)結(jié)構(gòu)中,每個(gè)條目都是一個(gè)對(duì)象數(shù)組(Object[]),其中一次包含了我們所獲取的屬性數(shù)據(jù)。
        如果覺得返回?cái)?shù)組的方式不夠符合面向?qū)ο蟮娘L(fēng)格,我們可以通過在HQL中動(dòng)態(tài)構(gòu)造對(duì)象實(shí)例的方法對(duì)這些平面化的數(shù)據(jù)進(jìn)行封裝。"select new TUser(user.name,user.age) from TUser user",我們通過HQL獲取數(shù)據(jù)的部分屬性值,與此同時(shí),我們也可以在HQL的select字句中使用統(tǒng)計(jì)函數(shù),甚至原生SQL函數(shù),或者利用distinct關(guān)鍵字,剔除返回集中的重復(fù)記錄。

        實(shí)體更新與刪除:在Hibernate2中,HQL僅僅用于數(shù)據(jù)查詢,而在Hibernate3中,HQL具備了更加強(qiáng)大的功能。實(shí)體更新與刪除就是其中的主要特征之一。

        分組和排序:與SQL類似,HQL通過order by子句實(shí)現(xiàn)對(duì)查詢結(jié)果的排序,order by子句可以指定多個(gè)排序條件:"from TUser user order by user.name ,user.age desc"通過Group by子句可進(jìn)行分組統(tǒng)計(jì)。如:"select count(user),user.age from TUser user group by user.age",我們知道where子句可以對(duì)記錄進(jìn)行甄選。那么,對(duì)于Group by子句獲得的結(jié)果集我們可以通過Having子句進(jìn)行甄選。例如:"select count(user),user.age from TUser user gourp by user.age having count(user)>10".

         參數(shù)綁定:類似JDBC中的SQL操作,我們可以通過順序占位符"?"對(duì)參數(shù)進(jìn)行標(biāo)識(shí),并在之后對(duì)參數(shù)內(nèi)容進(jìn)行填充。建議使用Query接口"from TUser user where user.name=? and user.age>?",這里除了順序占位符,我們還可以使用引用占位符,如:"from TUser where name=:name"參數(shù)綁定機(jī)制可以使得查詢語(yǔ)法與具體參數(shù)數(shù)值相互獨(dú)立。這樣,對(duì)于參數(shù)不同,查詢語(yǔ)法相同的查詢操作,數(shù)據(jù)庫(kù)即可實(shí)施性能優(yōu)化策略。同時(shí),參數(shù)綁定機(jī)制也杜絕了參數(shù)值對(duì)查詢語(yǔ)法本身的影響。

         引用查詢:SQL語(yǔ)句混雜在代碼之間將破壞代碼的可讀性,并使得系統(tǒng)的可維護(hù)性降低。為了避免這樣的情況出現(xiàn),我們通常采取將SQL配置化的方式,也就是將SQL保存在配置文件中,需要調(diào)用的時(shí)候在進(jìn)行讀取。
    <query name="queryByName">
     <![CDATA[
      from TUser user where user.name=:name
     ]]>
    </query>
    之后,我們可通過session.getNamedQuery方法從配置文件中調(diào)用引用的HQL.

         聯(lián)合查詢:inner join,left outer join,right outer join,full join
         子查詢:如:"from TUser user where (select count(*) from user.addresses)>1"HQL中,子查詢必須出現(xiàn)在where子句中,且必須以一對(duì)圓括號(hào)包圍。
         數(shù)據(jù)加載方式:Hibernate支持以下幾種數(shù)據(jù)加載方式:
    1、即時(shí)加載:當(dāng)實(shí)體加載完畢后,立即加載其關(guān)聯(lián)數(shù)據(jù)。
    2、延遲加載:實(shí)體加載時(shí),其關(guān)聯(lián)數(shù)據(jù)并非即刻獲取,而是當(dāng)關(guān)聯(lián)數(shù)據(jù)第一次被訪問時(shí)再進(jìn)行讀取。
    3、預(yù)先加載:預(yù)先加載時(shí),實(shí)體及其關(guān)聯(lián)對(duì)象同時(shí)讀取,這與即時(shí)加載類似。
    4、批量加載:對(duì)于即時(shí)加載和延遲加載,可以采用批量加載方式進(jìn)行性能上的優(yōu)化。

    posted @ 2009-11-15 22:25 王永慶 閱讀(326) | 評(píng)論 (0)編輯 收藏

    持久化實(shí)體Bean的兩種方式:
        既然需要將實(shí)體Bean映射到存儲(chǔ)源中,應(yīng)用肯定需要提供操作RDBMS的代碼。
        Bean管理持久化實(shí)體Bean,是手工完成持久化行為的EJB類型。換句話所,組件開發(fā)者必須開發(fā)代碼,以將內(nèi)存中的持久化域存儲(chǔ)到底層存儲(chǔ)源中。這種方式成為BMP。
        EJB規(guī)范還提供了BMP的替代組件類型:借助于EJB容器完成數(shù)據(jù)的持久化。這就是容器管理持久化(CMP)。此時(shí),通常都要將持久化邏輯從CMP中剝離出來。然后借助于容器提供的工具完成數(shù)據(jù)的自動(dòng)持久化。最后,EJB容器將生成訪問數(shù)據(jù)庫(kù)的代碼。注意,CMP是獨(dú)立于任何O/RMapping技術(shù)的數(shù)據(jù)對(duì)象,因此可以在各種企業(yè)環(huán)境中重用CMP組件。
        CMP極大減少了實(shí)體Bean的代碼量,因?yàn)椴挥弥苯泳帉慗DBC代碼了。EJB容器將會(huì)處理所有的持久化操作,這是EJB勢(shì)能應(yīng)用的優(yōu)勢(shì)之一。
        在執(zhí)行ejbCreate()方法期間,即在初始化內(nèi)存中的實(shí)體Bean時(shí),將會(huì)在底層RDBMS中插入新的記錄,并將這些記錄同實(shí)體Bean實(shí)例建立起映射關(guān)系。當(dāng)調(diào)用BMP實(shí)體Bean的ejbCreate()時(shí),它將負(fù)責(zé)生成RDBMS中的數(shù)據(jù)。類似的,當(dāng)調(diào)用BMP實(shí)體Bean的ejbRemo()時(shí),它將負(fù)責(zé)RDBMS中數(shù)據(jù)的刪除。

        在EJB領(lǐng)域中,客戶并沒有直接調(diào)用EJB實(shí)例,它們僅僅調(diào)用了EJB對(duì)象代理。借助于Home對(duì)象能夠生成EJB對(duì)象。因此,對(duì)于定義在EJB Bean類中的各個(gè)ejbCreate()方法,在Home接口中也將存在對(duì)象的create()方法。當(dāng)客戶調(diào)用Home對(duì)象的create()方法時(shí),容器將把調(diào)用請(qǐng)求委派給ejbCreate()方法。
        開發(fā)者可以通過多種方式查找實(shí)體Bean.需要在實(shí)體Bean的Home接口中列舉出這些查找方法。我們稱這些方法為"finder"方法。除了暴露創(chuàng)建、銷毀實(shí)體Bean實(shí)例的方法外,Home接口還需暴露finder方法。這是實(shí)體Bean的Home接口同其他EJB類型中的Home接口的最明顯區(qū)別。

        實(shí)體上下文,所有的EJB組件都存在上下文對(duì)象供組件訪問到容器環(huán)境使用。這些上下文對(duì)象含有EJB容器設(shè)置的環(huán)境信息。因此EJB組件能夠訪問到上下文,從而獲取各種信息,比如事務(wù),安全性信息。對(duì)于實(shí)體Bean而言,存在javax.ejb.EntityContext上下文接口。它繼承自EJBContext
    public interface javax.ejb.EntityContext extends javax.ejb.EJBContext{
     public javax.ejb.EJBLocalObject getEJBLocalObject();
     public javax.ejb.EJBObject getEJBObject();
     public java.lang.Object getPrimarykey();
    }
        通過調(diào)用getEJBObject()方法,當(dāng)前客戶能夠獲得某實(shí)體Bean實(shí)例對(duì)應(yīng)的EJB對(duì)象??蛻粽{(diào)用的是EJB對(duì)象,而不是實(shí)體Bean實(shí)例本身。因此,客戶能夠在應(yīng)用中引用返回的EJB對(duì)象。
        實(shí)體Bean實(shí)例對(duì)應(yīng)的主鍵可以通過getPrimaryKey()方法獲得。主鍵唯一標(biāo)識(shí)某實(shí)體Bean實(shí)例。當(dāng)實(shí)體Bean實(shí)例存儲(chǔ)到存儲(chǔ)源中時(shí),可以使用主鍵獲得單個(gè)實(shí)體Bean實(shí)例。由于在RDBMS中也存在主鍵,因此主鍵能夠唯一標(biāo)識(shí)某個(gè)實(shí)體Bean實(shí)例。

    posted @ 2009-11-15 12:21 王永慶 閱讀(206) | 評(píng)論 (0)編輯 收藏

        實(shí)體Bean是持久化對(duì)象,它能夠存儲(chǔ)到持久化存儲(chǔ)源中。實(shí)體Bean是EJB編程模型中最為重要的利器之一。
        將對(duì)象映射到RDBMS的技術(shù)稱之為對(duì)象-關(guān)系映射。它能夠?qū)崿F(xiàn)內(nèi)存對(duì)象同關(guān)系數(shù)據(jù)的相互轉(zhuǎn)換。O/R映射器能夠?qū)ava對(duì)象映射到任意RDBMS模式。比如簡(jiǎn)單的O/RMapping引擎能夠?qū)ava類映射成SQL表定義。Java語(yǔ)言提供的對(duì)象序列化功能比O/RMapping簡(jiǎn)單多了。O/RMapping是更加復(fù)雜、成熟的對(duì)象持久化機(jī)制。通過將Java對(duì)象分解成關(guān)系數(shù)據(jù),應(yīng)用便能夠查找到所需的數(shù)據(jù)了。
        通過如下兩種方式能夠完成Java對(duì)象到關(guān)系數(shù)據(jù)的映射。其一,通過硬編碼實(shí)現(xiàn)O/RMapping.其二,借助于O/RMapping產(chǎn)品,自動(dòng)完成映射過程,比如:Hibernate.
        對(duì)于任何成熟的、基于OO多層部署的企業(yè)應(yīng)用而言,總可以劃分出2種截然不同的組件類型。1、應(yīng)用邏輯組件,2、持久化數(shù)據(jù)組件。會(huì)話Bean和實(shí)體Bean的最大區(qū)別在于實(shí)體Bean是實(shí)體,客戶是可以看的到的。因此實(shí)體Bean能夠獨(dú)立于客戶應(yīng)用的生命周期。對(duì)于實(shí)體Bean而言,通過比較它們各自含有的數(shù)據(jù)便能夠區(qū)分不同的實(shí)體Bean.這意味著客戶能夠引用單個(gè)的實(shí)體Bean實(shí)例并將它傳入到其他應(yīng)用中,不同的客戶可以共享同樣的實(shí)體Bean實(shí)例,這對(duì)于會(huì)話Bean是辦不到的。會(huì)話Bean建模過程或者工作流。實(shí)體Bean本身就是客戶,它就是持久化狀態(tài)對(duì)象。
        實(shí)體Bean實(shí)例存在幾方面的含義:
    1、持久化數(shù)據(jù)的Java表示,即它能夠從持久化存儲(chǔ)源裝載數(shù)據(jù)到內(nèi)存中。同時(shí),實(shí)體Bean實(shí)例能夠?qū)⒀b載到的數(shù)據(jù)存儲(chǔ)到實(shí)例的成員變量中。
    2、通過修改內(nèi)存中的Java對(duì)象可以改變數(shù)據(jù)的取值。
    3、還可以將修改后的數(shù)據(jù)保存到存儲(chǔ)源匯中,從而更新RDBMS中的物理數(shù)據(jù)。
        實(shí)體Bean是持久化對(duì)象,它能夠長(zhǎng)期存在。即使出現(xiàn)了不可恢復(fù)的失敗,比如應(yīng)用服務(wù)器癱瘓、數(shù)據(jù)庫(kù)癱瘓,實(shí)體Bean還是能夠存活的。原因在于實(shí)體Bean只是對(duì)底層具有容錯(cuò)行為的持久化存儲(chǔ)源中數(shù)據(jù)的映射,因此,即使極其癱瘓,內(nèi)存中的實(shí)體Bean實(shí)例還可以重新構(gòu)建。在極其重啟后,實(shí)體Bean實(shí)例需要從底層存儲(chǔ)源裝載數(shù)據(jù),并使用獲得的數(shù)據(jù)對(duì)實(shí)體Bean實(shí)例中的各個(gè)域進(jìn)行setter操作。實(shí)體Bean比客戶會(huì)話的生命周期要長(zhǎng)。可以認(rèn)為,數(shù)據(jù)庫(kù)中記錄存活的時(shí)間決定了實(shí)體Bean實(shí)例的生命周期。
        相同數(shù)據(jù)往往存在多分物理拷貝,比如內(nèi)存中的實(shí)體Bean實(shí)例、實(shí)體Bean數(shù)據(jù)本身,他們都是對(duì)RDBMS中數(shù)據(jù)的拷貝。因此,EJB容器需要提供某種機(jī)制實(shí)現(xiàn)數(shù)據(jù)在Java對(duì)象和RDBMS間的自動(dòng)傳輸。實(shí)體Bean的Bean類為此提供了2個(gè)特殊方法:
    ejbLoad():它能夠從持久化存儲(chǔ)源中讀取數(shù)據(jù),并存儲(chǔ)到實(shí)體Bean實(shí)例的域中。
    ejbStore():它能夠?qū)?dāng)前實(shí)體Bean實(shí)例的域值保存到底層RDBMS中。
    那么何時(shí)需要完成內(nèi)存中實(shí)體Bean實(shí)例和RDBMS中數(shù)據(jù)的傳遞和轉(zhuǎn)換,開發(fā)者需要知道是誰(shuí)調(diào)用了ejbLoad()和ejbStore(),答案是EJB容器。它們是回調(diào)方法,供EJB容器調(diào)用。EJB規(guī)范要求所有的實(shí)體Bean組件必須提供它們。至于讀取或存儲(chǔ)數(shù)據(jù)的時(shí)機(jī),由EJB容器決定。依據(jù)實(shí)體Bean實(shí)例當(dāng)前的事務(wù)狀態(tài),EJB容器會(huì)自動(dòng)計(jì)算出需要調(diào)用實(shí)體Bean實(shí)例中的ejbLoad(),ejbStore()方法的時(shí)機(jī),這也是使用實(shí)體Bean組件的優(yōu)勢(shì)之一:開發(fā)者不用考慮java對(duì)象同步底層RDBMS的問題。

        為了滿足大量并發(fā)客戶訪問同一數(shù)據(jù)的要求,架構(gòu)師需要借助于實(shí)體Bean設(shè)計(jì)出高性能的訪問系統(tǒng)。如下給出一種解決方案:允許多個(gè)客戶共享同一實(shí)體Bean實(shí)例。因此,實(shí)體Bean實(shí)例能夠同時(shí)服務(wù)多個(gè)客戶。盡管表面上看是可行的,但是對(duì)于EJB而言,這是行不通的。原因有亮點(diǎn):其一,為實(shí)現(xiàn)實(shí)體Bean實(shí)例服務(wù)多個(gè)并發(fā)客戶,必須保證實(shí)體Bean實(shí)例是線程安全的,開發(fā)線程安全的代碼并不是一件容易的工作,而且經(jīng)常會(huì)出現(xiàn)一堆錯(cuò)我。其二,底層事務(wù)系統(tǒng)幾乎不可能控制多個(gè)線程的并發(fā)執(zhí)行,事務(wù)往往同具體的線程綁定在一起。因此,基于上述理由,單個(gè)實(shí)體Bean實(shí)例只能夠在單線程環(huán)境中運(yùn)行。對(duì)于所有的EJB組件而言,包括會(huì)話Bean、消息驅(qū)動(dòng)Bean、實(shí)體Bean,它們都是以單線程方式運(yùn)行的。
        當(dāng)然,強(qiáng)制要求各個(gè)實(shí)體Bean實(shí)例只能同時(shí)服務(wù)單個(gè)客戶,將引入性能瓶頸。由于實(shí)例以單線程方式運(yùn)行,客戶需要排隊(duì)等候?qū)嶓wBean實(shí)例,從而獲得對(duì)實(shí)體Bean實(shí)例的調(diào)用,這對(duì)于大型企業(yè)應(yīng)用而言,是不允許出現(xiàn)的
        為了提供系統(tǒng)性能,EJB容器會(huì)實(shí)例化同一實(shí)體Bean的多個(gè)實(shí)例。這使得多個(gè)客戶能夠并發(fā)同不同實(shí)體Bean實(shí)例進(jìn)行交互,而這些實(shí)體Bean實(shí)例代表了同一RDBMS數(shù)據(jù)。事實(shí)上,這就是EJB容器的運(yùn)行行為。因此,客戶再也不用排隊(duì)等候?qū)嶓wBean實(shí)例,因?yàn)榇嬖诙鄠€(gè)實(shí)體Bean實(shí)例了。
        一旦多個(gè)實(shí)體Bean實(shí)例代表了同一RDBMS數(shù)據(jù),則引入了另外一個(gè)問題:數(shù)據(jù)癱瘓。如果多個(gè)實(shí)體Bean實(shí)例代表的數(shù)據(jù)是通過緩存管理的,則需要在內(nèi)存中拷貝多分緩存中的數(shù)據(jù)。顯然,某些緩存中的數(shù)據(jù)將變得陳舊,因此會(huì)出現(xiàn)很多過期的數(shù)據(jù)。
        為了實(shí)現(xiàn)實(shí)體Bean實(shí)例的緩存一致性,各個(gè)實(shí)體Bean實(shí)例必須同底層存儲(chǔ)元進(jìn)行同步。EJB容器將通過調(diào)用ejbLoad(),ejbStore()方法同步這些實(shí)體Bean實(shí)例。
        至于實(shí)體Bean實(shí)例同底層RDBMS數(shù)據(jù)的同步頻率,則取決于事務(wù)。事務(wù)將各個(gè)客戶請(qǐng)求隔離起來。借助于事務(wù)實(shí)現(xiàn)數(shù)據(jù)同步。

        EJB容器提供的實(shí)例池是很有意義的。當(dāng)然,并不是只有實(shí)體Bean才存在實(shí)例池。在將實(shí)體Bean實(shí)例重新分配給不同EJB對(duì)象時(shí),會(huì)存在一些問題,并要求容器去解決。比如當(dāng)實(shí)體Bean實(shí)例被指定給EJB對(duì)象時(shí),它可能還持有資源(比如Socket連接)。如果將實(shí)體Bean實(shí)例放置在實(shí)例池中,Socket連接不在需要。因此為實(shí)現(xiàn)資源的獲取和釋放,實(shí)體Bean的Bean類需要實(shí)現(xiàn)如下2個(gè)回調(diào)方法:
    1、ejbActivate().在將實(shí)體Bean實(shí)例從實(shí)例池中取出來時(shí),EJB容器會(huì)自動(dòng)調(diào)用它。該過程稱之為激活。進(jìn)而,EJB容器會(huì)將實(shí)體Bean實(shí)例分配給某EJB對(duì)象,并同時(shí)獲得主鍵對(duì)象。在執(zhí)行ejbActivate()方法期間,實(shí)例需要獲得所需的資源,比如Socke,否則,在將實(shí)體Bean實(shí)例分配給某EJB對(duì)象時(shí),無法對(duì)資源進(jìn)行操作。
    2、ejbPassivate().在將實(shí)體Bean實(shí)例放置到實(shí)例池中時(shí),EJB容器會(huì)調(diào)用它。注意,它也是回調(diào)方法。這一過程稱之為掛起。進(jìn)而,EJB容器需要從某EJB對(duì)象中取回分配于它的實(shí)體Bean實(shí)例,并將實(shí)例的主鍵對(duì)象也收回。在執(zhí)行ejbPassivate()方法期間,需要釋放ejbActivate()執(zhí)行期間獲得的相關(guān)資源,比如:Socket.
        一旦實(shí)體Bean實(shí)例被掛起,不但要釋放它持有的資源,還將實(shí)例的狀態(tài)信息保存起來。因此,實(shí)體Bean實(shí)例最新的狀態(tài)信息可以從RDBMS中找到了。為了保存實(shí)體Bean實(shí)例的域信息到RDBMS中,容器要在掛起實(shí)例前調(diào)用ejbStore()方法。類似的,一旦實(shí)體Bean被激活,不但要獲得所需的資源,還要從RDBMS裝載最新的數(shù)據(jù),為了完成數(shù)據(jù)的讀取,EJB容器將在激活實(shí)體Bean實(shí)例后調(diào)用ejbLoad()方法。


     

    posted @ 2009-11-15 11:46 王永慶 閱讀(296) | 評(píng)論 (0)編輯 收藏
    Spring提供了對(duì)Sun的標(biāo)準(zhǔn)的持久化API-JDO的整合,以及其他開放源碼的ORM框架,如Hibernate、ApacheOJB和iBATIS SQL Maps.Spring對(duì)這些技術(shù)的支持沒有像它對(duì)JDBC的支持那么廣泛。
    <?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/trainingDatasource</value>
            
    </property>
        
    </bean>
        
    <!-- 管理Hibernate資源,在應(yīng)用的整個(gè)生命周期里,你只要保存一個(gè)SessionFactory實(shí)例就可以了。-->
        
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
            
    <!-- 先要知道連接哪個(gè)數(shù)據(jù)源 -->
            
    <property name="dataSource">
                
    <ref bean="dataSource"/>
            
    </property>
            
    <!-- Hibernate本身有數(shù)十個(gè)屬性,通過這些屬性你就可以控制它的行為。當(dāng)在Spring之外使用Hibernage的時(shí)候,
            Hibernate在應(yīng)用的class path下的某個(gè)地方尋找一個(gè)名叫hibernate.properties的文件,并用它來進(jìn)行配置。
            然而,用Spring就不需要在一個(gè)獨(dú)立的屬性文件里管理這些配置。 
    -->
            
    <property name="hibernateProperties">
                
    <props>
                    
    <prop key="hibernate.dialect">net.sf.hibernate.dialect.MySQLDialect</prop>
                
    </props>
            
    </property>
            
    <!-- 同樣,你也要告訴Spring從哪里讀取Hibernate.hbm.xml映射文件 -->
            
    <property name="mappingResources">
                
    <list>
                    
    <value>Student.hbm.xml</value>
                
    </list>
            
    </property>
            
    <!-- 還有一種簡(jiǎn)單的方法設(shè)置映射文件資源,你可以用你應(yīng)用的class path下的一個(gè)子路徑來配置
            mappingDirectoryLocation屬性,spring將找到這個(gè)路徑下的每個(gè)*.hbm.xml文件,來配置SessionFactory 
    -->
            
    <property name="mappingDirectoryLocations">
                
    <list>
                    
    <value>classpath:/com/springinaction/training/model</value>
                
    </list>
            
    </property>
        
    </bean>
        
    <!-- 如果把這個(gè)模版對(duì)象織入到一個(gè)個(gè)DAOBean中顯得很麻煩的時(shí)候,可以使用Spring自動(dòng)連接功能來將模版對(duì)象隱士的織入到
        DAObean. 
    -->
        
    <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
            
    <property name="sessionFactory">
                
    <ref bean="sessionFactory"/>
            
    </property>
        
    </bean>
        
    </beans>
    posted @ 2009-11-14 15:59 王永慶 閱讀(263) | 評(píng)論 (0)編輯 收藏

    調(diào)用存儲(chǔ)過程:
    Spring通過實(shí)現(xiàn)CallableStatementCallback來支持存儲(chǔ)過程。假定有個(gè)存儲(chǔ)過程的名字是ARCHIVE_STUDENTS,執(zhí)行代碼如下:

    package com.testproject.spring.datasource;

    import java.sql.CallableStatement;
    import java.sql.SQLException;

    import org.springframework.jdbc.core.CallableStatementCallback;
    import org.springframework.jdbc.core.JdbcTemplate;
    /*
     * 為了讓JdbcTemplate工作,它所需要的,只是一個(gè)DataSource實(shí)例。
     
    */

    public class StudentDaoImpl implements StudentDao {
        
    private JdbcTemplate jdbcTemplate;
        
        
    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
            
    this.jdbcTemplate = jdbcTemplate;
        }

        
    /**
         * 調(diào)用存儲(chǔ)過程,通過CallableStatementCallback來實(shí)現(xiàn)
         
    */

        
    public void archiveStudentData(){
            CallableStatementCallback cb 
    = new CallableStatementCallback(){
                
    public Object doInCallableStatement(CallableStatement cs)throws SQLException{
                    cs.execute();
                    
    return null;
                }

            }
    ;
            jdbcTemplate.execute(
    "{ARCHIVE_STUDENTS}",cb);
        }

    }


    把操作創(chuàng)建成對(duì)象:

    插入:

    package com.testproject.spring.datasource;

    import java.sql.Types;

    import javax.sql.DataSource;

    import org.springframework.jdbc.core.SqlParameter;
    import org.springframework.jdbc.object.SqlUpdate;
    /**
     * Spring提供了一種真正把數(shù)據(jù)庫(kù)操作建模成對(duì)象的方法,這樣就在的代碼和直接JDBC之間又加了一個(gè)絕緣層。
     * 首先,這些數(shù)據(jù)庫(kù)操作對(duì)象是線程安全的,意味著對(duì)于每個(gè)數(shù)據(jù)庫(kù)操作,你只需創(chuàng)建一個(gè)實(shí)例。
     * 其次,任何數(shù)據(jù)庫(kù)操作對(duì)象必須在運(yùn)行前先編譯一下,這樣就讓對(duì)象知道什么時(shí)候可以預(yù)備statement,以便在稍后能執(zhí)行它們。
     * 使用:
     * private InsertPerson insertPerson;
     * public int insertPerson(Person person){
     *     return insertPerson.insert(person);
     * }
     *
     
    */

    public class InsertPerson extends SqlUpdate {
        
    public InsertPerson(DataSource ds){
            
    //首先要給sqlUpdate提供一個(gè)DataSource,用來創(chuàng)建JdbcTemplate
            setDataSource(ds);
            setSql(
    "insert into person(id,firstName,lastName) values(?,?,?)");
            
    //其次,我們需要為statement中的每個(gè)參數(shù)調(diào)用這個(gè)方法,順序也是很重要的
            declareParameter(new SqlParameter(Types.NUMERIC));
            declareParameter(
    new SqlParameter(Types.VARCHAR));
            declareParameter(
    new SqlParameter(Types.VARCHAR));
            
    //最后編譯它,每個(gè)數(shù)據(jù)庫(kù)操作對(duì)象必須在它被使用之前編譯好。
            compile();
        }

        
    public int insert(Person person){
            Object[] params 
    = new Object[]{
                    person.getId(),
                    person.getFirstName(),
                    person.getLastName()
            }
    ;
            
    return update(params);
        }

    }

    查詢:

    package com.testproject.spring.datasource;

    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Types;

    import javax.sql.DataSource;

    import org.springframework.jdbc.core.SqlParameter;
    import org.springframework.jdbc.object.MappingSqlQuery;

    /**
     * 使用:
     * private PersonByIdQuery personByIdQuery;
     * public person getPerson(Integer id){
     *     Object[] params = new Object[]{id};
     *  return (Person)personByIdQuery.execute(params).get(0);
     * }
     *
     
    */

    public class PersonByIdQuery extends MappingSqlQuery {
        
        
    public PersonByIdQuery(DataSource ds){
            
    super(ds,"select id,first_name,last_name from person where id=?");
            declareParameter(
    new SqlParameter("id",Types.INTEGER));
            compile();
        }

        
        
    protected Object mapRow(ResultSet rs, int rowNumber) throws SQLException {
            Person person 
    = new Person();
            person.setId((Integer)rs.getObject(
    "id"));
            person.setFirstName(rs.getString(
    "first_name"));
            person.setLastName(rs.getString(
    "last_name"));
            
    return person;
        }


    }

     

    posted @ 2009-11-14 15:21 王永慶 閱讀(285) | 評(píng)論 (0)編輯 收藏
    實(shí)現(xiàn)WEB服務(wù)客戶
    web服務(wù)是跨平臺(tái)的、跨語(yǔ)言的,所以WEB服務(wù)的客戶端使用的語(yǔ)言和平臺(tái)和他的服務(wù)端沒有必然的關(guān)系。比如我們可以在.Net下開發(fā)、部署web服務(wù),然后在J2EE平臺(tái)下調(diào)用它,或者使用在J2EE平臺(tái)下開發(fā)、部署web服務(wù),然后使用VB來調(diào)用它。
    在J2EE平臺(tái)中,WEB服務(wù)客戶同EJB客戶類似。如下兩種方式能夠訪問到WEB服務(wù):
    1、不借助于JNDI查找,即使用單獨(dú)的JAX-RPC客戶訪問。
    2、借助于JNDI上下文訪問WEB服務(wù)的J2EE客戶
    第一種方法稱之為靜態(tài)存根,此時(shí)需要在客戶端預(yù)先生成SOAP客戶存根,這同RMI存根類似。第二種方法稱之為動(dòng)態(tài)代理。它將在運(yùn)行時(shí)獲得WSDL描述,然后創(chuàng)建動(dòng)態(tài)代理。無論采用哪種方式訪問WEB服務(wù),客戶都需要獲得服務(wù)Endpoint地址URL,否則單憑JNDI名是很難訪問到WEB服務(wù)的。
    package com.testproject.ejb.web;

    import java.net.URL;

    import javax.xml.namespace.QName;
    import javax.xml.rpc.Service;
    import javax.xml.rpc.ServiceFactory;

    /**
     * 單獨(dú)JAX-RPC客戶代碼實(shí)例。
     * 它使用了動(dòng)態(tài)代理方法,以獲得對(duì)遠(yuǎn)程WEB服務(wù)的引用。
     *
     
    */

    public class HelloClient {
        
    static String host = "localhost";
        
    //web服務(wù)的名字
        static String serviceURL = "HelloBean";
        
    //名稱空間
        static String nameSpaceUri = "urn:examples";
        
    static String serviceName = "HelloWorldWS";
        
    //web服務(wù)調(diào)用的地址
        static String serviceEndpointAddress = "http://"+host+":8000"+serviceURL;
        
    public static void main(String[] args)throws Exception{
            HelloInterface hello 
    = null;
            
    //動(dòng)態(tài)代理方法
            
    //1、指定WSDL文件的位置
            URL url = new URL(serviceEndpointAddress+"?WSDL");
            
    //2、創(chuàng)建服務(wù)工廠實(shí)例
            ServiceFactory serviceFactory = ServiceFactory.newInstance();
            
    //3、創(chuàng)建服務(wù)對(duì)象,以作為代理工廠
            Service HelloService = serviceFactory.createService(url,new QName(nameSpaceUri,serviceName));
            
    //4、獲得port引用
            hello = (HelloInterface)HelloService.getPort(HelloInterface.class);
            
    //調(diào)用hello()方法
            System.out.println("Dynamic Proxy:"+hello.hello());
        }

    }

    posted @ 2009-11-13 16:45 王永慶 閱讀(142) | 評(píng)論 (0)編輯 收藏
    EJB2.1和web服務(wù)
    1、下載安裝服務(wù)器后,需要設(shè)置環(huán)境變量。
    Set J2EE_HOME=J2EE安裝目錄
    Set CLASSPATH 
    =%CLASSPATH%;%J2EE_HOME%\\lib\\j2ee.jar;.
    Set Path =%Path%;%J2EE_HOME%\\bin;.

    2、創(chuàng)建初始目錄
    +HelloBeanService
        +META-INF(application.xml;sun-j2ee-ri.xml )
        +ejb
           +META-INF(ejb-jar.xml; webservices.xml;mapping.xml)
           -*.java文件(EJB相關(guān)的類)
           -config.xml
    3、定義web服務(wù)接口
    package com.testproject.ejb.web;

    /*
     * Hello服務(wù)Endpoint接口
     * 需要注意的是,這里使用的是EJB2.1無狀態(tài)會(huì)話Bean,它作為WEB服務(wù)端點(diǎn)時(shí)可以不提供Home接口和Remote
     * Locale接口,它提供的是web服務(wù)端點(diǎn)接口,這個(gè)接口擴(kuò)展了Remote接口。
     
    */

    public interface HelloInterface extends java.rmi.Remote {
        
    public String hello()throws java.rmi.RemoteException;
    }


    4、實(shí)現(xiàn)服務(wù)端點(diǎn)接口
    package com.testproject.ejb.web;

    import java.rmi.RemoteException;

    import javax.ejb.EJBException;
    import javax.ejb.SessionBean;
    import javax.ejb.SessionContext;

    /*
     * 定義了服務(wù)端點(diǎn)接口,接下來的任務(wù)就是開發(fā)無狀態(tài)會(huì)話Bean。無狀態(tài)會(huì)話Bean同樣需要實(shí)現(xiàn)SessionBean接口,
     * 服務(wù)端點(diǎn)接口定義的方法在會(huì)話Bean中實(shí)現(xiàn)。
     
    */

    public class HelloBean implements SessionBean {
        
        
    public void ejbCreate(){
            
    /*
             * 這里不能接收任何參數(shù)
             
    */

        }


        
    public void ejbActivate() throws EJBException, RemoteException {
        }


        
    public void ejbPassivate() throws EJBException, RemoteException {
        }


        
    public void ejbRemove() throws EJBException, RemoteException {
        }


        
    public void setSessionContext(SessionContext arg0) throws EJBException,
                RemoteException 
    {
        }

        
    /*
         * 業(yè)務(wù)方法:輸出hello
         
    */

        
    public String hello(){
            
    return "Hello wyq";
        }


    }


    5、創(chuàng)建EJB描述
    用于部署成Web服務(wù)的無狀態(tài)會(huì)話Bean的描述符和普通的無狀態(tài)會(huì)話Bean不同ejb-jar.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <ejb-jar version="2.1"
    xmlns
    ="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation
    ="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd">
        
    <display-name>HelloBean</display-name>
        
    <enterprise-beans>
            
    <session>
                
    <display-name>HelloBean</display-name>
                
    <ejb-name>HelloBean</ejb-name>
                
    <service-endpoint>com.testproject.ejb.web.HelloInterface</service-endpoint>
                
    <ejb-class>com.testproject.ejb.web.HelloBean</ejb-class>
                
    <session-type>Stateless</session-type>
                
    <transaction-type>Container</transaction-type>
            
    </session>
        
    </enterprise-beans>
    </ejb-jar>

    在這個(gè)新的部署描述符中,使用<service-endpoint>指定了服務(wù)端點(diǎn),同時(shí),必須指定EJB為無狀態(tài)會(huì)話Bean
    6、生成WEB服務(wù)描述

    下面的任務(wù)就是生成一個(gè)Web服務(wù)描述,我們通常使用工具來生成這個(gè)描述符。在這里使用J2EE提供的wscompile工具來生成。在使用wscompile工具生成web服務(wù)描述前,首先手工編寫一個(gè)簡(jiǎn)單的XML描述config.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <configuration xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/config">
        
    <service 
            
    name="MyHelloBeanService" 
            targetNamespace
    ="urn:HelloBean" 
            typeNamespace
    ="urn:HelloBean"
            packageName
    ="helloBeanService">
            
    <interface name="com.testproject.ejb.web.HelloInterface"/>
        
    </service>
    </configuration>

    在這個(gè)描述中,指定了目標(biāo)的名稱空間、包的名字和Web服務(wù)端點(diǎn)接口:HelloInterface。如下命令就可以生成一個(gè)web服務(wù)描述

    c:\\ HelloBeanService\\ejb \\>wscompile -define -d . -nd . -classpath . config.xml
    自動(dòng)生成MyHelloBeanService.wsdl文件。
    7、編寫一個(gè)web服務(wù)映射文件:
    在ejb\\META-INF目錄下新建一個(gè)mapping.xml文件,然后編輯這個(gè)描述符
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE java-wsdl-mapping PUBLIC
        "-//IBM Corporation,Inc.//DTD J2EE JAX-RPC mapping 1.0//EN"
        "http://www.ibm.com/standards/xml/webservices/j2ee/j2ee_jaxrpc_mapping_1_0.dtd"
    >
    <java-wsdl-mapping>
        
    <package-mapping>
            
    <package-type>HelloBeanService</package-type>
            
    <namespaceURI>urn:HelloBean</namespaceURI>
        
    </package-mapping>
    </java-wsdl-mapping>
    8、編寫webservices.xml文件
    另外,還需要提供webservices.xml文件,并存放到Ejb-jar存檔的META-INF目錄中。各個(gè)J2EE產(chǎn)品可能提供相應(yīng)的部署工具來創(chuàng)建這個(gè)文件。
    9、EJB打包
    另外,web服務(wù)部署描述符在EJB-JAR文件中的位置是META-INF/webservices.xml.把生成的HelloBeanService.wsdl拷貝到ejb\\META-INF目錄下
    c:\\HelloBeanService\\ejb\\jar cvf ejb.jar com META-INF
    10、Application打包
    HelloBeanService\\MEAT-INF目錄下創(chuàng)建2個(gè)文件:application.xml和sun-j2ee-ri.xml
    application.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE application PUBLIC '-//Sun Microsystems,
        Inc.//DTD J2EE Application 1.3//EN'
        'http://java.sun.com/dtd/application_1_3.dtd'
    >
    <application>
        
    <description>Application description</description>
        
    <display-name>HelloBeanServiceApp</display-name>
        
    <module>
            
    <ejb>ejb.jar</ejb>
        
    </module>
    </application>

    最后歸檔
    c:\\ HelloBeanService\\ejb\\>copy ejb.jar ../
    c:\\ HelloBeanService\\ejb\\>cd..
    c:\\ HelloBeanService\\\\>jar cvf encryptservice.ear ejb.jar META-INF

     


     

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

    常用鏈接

    留言簿(1)

    隨筆分類

    隨筆檔案

    關(guān)注blogs

    搜索

    •  

    最新評(píng)論

    • 1.?re: 心中的那個(gè)她[未登錄]
    • 如果心情能那么容易放開就好了,碰到她是我的緣分,但是她的緣分不知道在哪里。
    • --王永慶
    • 2.?re: 心中的那個(gè)她[未登錄]
    • 兄弟,喜歡就大膽去追好了,就是因?yàn)橄矚g才會(huì)有不愉快,如果想一輩子沒有這些煩惱,找一個(gè)可有可無的人就好了。這種事講的是緣分吧。別人對(duì)你好不好其實(shí)不太重要。放開心情就好了。
    • --萍水相逢
    • 3.?re: 心中的那個(gè)她
    • 只能同甘不能共苦,就他媽算了吧,程序員也是人?。∥椰F(xiàn)在也很討厭女的不理解人情。
    • --咖啡妝
    • 4.?re: 難以割舍的那份情感
    • 評(píng)論內(nèi)容較長(zhǎng),點(diǎn)擊標(biāo)題查看
    • --王永慶
    • 5.?re: 難以割舍的那份情感
    • 評(píng)論內(nèi)容較長(zhǎng),點(diǎn)擊標(biāo)題查看
    • --隔葉黃鶯

    閱讀排行榜

    評(píng)論排行榜

    主站蜘蛛池模板: 亚洲最大黄色网址| 欧美日韩国产免费一区二区三区 | 亚洲va无码专区国产乱码| 国产精品黄页免费高清在线观看| 亚洲国产婷婷香蕉久久久久久| 白白色免费在线视频| 免费播放春色aⅴ视频| 麻豆安全免费网址入口| 亚洲国产日韩在线观频| 特级做a爰片毛片免费看| 亚洲精品乱码久久久久久蜜桃 | 麻豆最新国产剧情AV原创免费 | 亚洲AV成人无码网站| 国产女高清在线看免费观看| 精品国产日韩亚洲一区在线| www.亚洲精品.com| 一级做a爱过程免费视| 亚洲色欲久久久综合网东京热| 色www永久免费网站| 亚洲日本一区二区三区| 国产a视频精品免费观看| 亚洲丰满熟女一区二区v| 女人18毛片特级一级免费视频| 亚洲av无码专区青青草原| 亚洲av麻豆aⅴ无码电影| a级毛片免费观看在线| 狠狠色伊人亚洲综合成人| 日韩免费人妻AV无码专区蜜桃 | 亚洲精品高清国产一线久久| 亚洲电影免费在线观看| 亚洲第一页在线播放| 成人免费毛片视频| 美女视频黄视大全视频免费的| 91麻豆国产自产在线观看亚洲| 久久国产精品免费专区| 亚洲a∨无码男人的天堂| 四虎影视永久免费观看网址| 久青草视频在线观看免费| 日本久久久久亚洲中字幕| 在线观看日本免费a∨视频| 日韩色日韩视频亚洲网站|