??xml version="1.0" encoding="utf-8" standalone="yes"?>久久精品亚洲一区二区三区浴池,日韩亚洲一区二区三区,国产精品亚洲mnbav网站http://www.tkk7.com/wyxdeniro/Ʋؓ怽龙象Q必先做众生牛马zh-cnMon, 12 May 2025 16:10:59 GMTMon, 12 May 2025 16:10:59 GMT60Hibernate深入出(二十?-----L入浅出hibernate有感http://www.tkk7.com/wyxdeniro/archive/2010/01/02/308034.html王永?/dc:creator>王永?/author>Sat, 02 Jan 2010 07:27:00 GMThttp://www.tkk7.com/wyxdeniro/archive/2010/01/02/308034.htmlhttp://www.tkk7.com/wyxdeniro/comments/308034.htmlhttp://www.tkk7.com/wyxdeniro/archive/2010/01/02/308034.html#Feedback0http://www.tkk7.com/wyxdeniro/comments/commentRss/308034.htmlhttp://www.tkk7.com/wyxdeniro/services/trackbacks/308034.htmlpackage 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;
    
/**
     * 初始化资?br />      
*/
    
protected void setUp() throws Exception {
        
try {
            
//加蝲c\径下的hibernate.cfg.xml文g
            Configuration config = new Configuration().configure();
            
//创徏sessionFactory对象
            sessionFactory = config.buildSessionFactory();
            
//创徏session
            session = sessionFactory.openSession();
        } 
catch (HibernateException e) {
            e.printStackTrace();
        }
    }
    
/**
     * load/getҎ均可以根据指定的实体cdid从数据库d记录Qƈq回与之对应的实体对象?br />      * 区别在于Q?br />      * 1、如果未发现W合条g的记录,getҎq回null,而loadҎ抛出一个ObjectNotFoundException
     * 2、loadҎ可以q回实体的代理类实例Q而getҎ永远直接q回实体cR?br />      * 3、loadҎ可以充分利用内部~存和二U缓存中的现有数据,而getҎ则仅仅在内部~存中进行数据查找,如果
     * 没有发现数据Q将过二~存Q直接调用SQL完成数据d?br />      *
     
*/
    
public void loadOrGetData(){
        TUser user 
= (TUser)session.load(TUser.class,new Integer(1));
    }
    
/**
     * 查询性能往往是一pȝ性能表现的一个重要方面?br />      * query.listҎ通过一条select SQL实现了查询操作,而iterateҎQ则执行?ơselectSQLQ第一ơ获取了所有符合条件的记录
     * 的id,之后Q在Ҏ各个id从库表中d对应的哦记录Q这是一个典型的N+1ơ查询问题?br />      * 
     * 我们q行query.list数据查询Ӟ即ɾ~存中已l有一些符合条件的实体对象存在Q我们也无法保证q些数据是库表中所有符合条件的数据。假?br />      * W一ơ查询条件是age>25,随即~存中就包括了所有age>25的user数据;W二ơ查询条件ؓage>20,此时~存中虽然包含了满age>25d?br />      * 数据Q但q些q不是满x件age>20的全部数?br />      * 因此Qquery.listҎq是需要执行一ơselect sql以保证查询结果的完整?iterateҎ通过首先查询获取所有符合条件记录的id,以此保证
     * 查询l果的完整??br />      * 因此Qquery.listҎ实际上无法利用缓存,它对~存只写不读。而iterateҎ则可以充分发挥缓存带来的优势Q如果目标数据只L者读取相?br />      * 较ؓ频繁Q通过q种机制可以大大减少性能上的损耗?br />      
*/
    
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());
        }
    }
    
/**
     * 大数据量的批量读?10W?
     * 解决ҎQ结合iterateҎ和evictҎ逐条对记录进行处理,内存消耗保持在可以接受的范围之内?br />      * 在实际开发中Q对于大扚w数据处理Q还是推荐采用SQL或存储过E实玎ͼ以获得较高的性能Qƈ保证pȝqxq行?br />      
*/
    
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();
            
//对象从一U缓存中U除
            session.evict(user);
            
//二~存可以讑֮最大数据缓存数量,辑ֈ峰值时会自动对~存中的较老数据进行废除,但是我们q里q是通过
            
//~码指定对象从二~存中移除,q有助保持缓存的数据有效性?/span>
            sessionFactory.evict(TUser.class,user.getId());
        }
    }
    
/**
     * Query Cache弥补了findҎ的不IQueryCache中缓存的SQL及其l果及ƈ非永q存在,当Hibernate发现此SQL对应的库表发生变动,
     * 会自动将Query Cache中对应表的SQL~存废除。因此Query Cache只在特定的情况下产生作用Q?br />      * 1、完全相同的select SQL重复执行?br />      * 2、在2ơ查询之_此select SQL对应的库表没有发生过改变?br />      
*/
    
public void queryForQueryCache(){
        String hql 
= "from TUser where age>?";
        Query query 
= session.createQuery(hql);
        query.setInteger(
11);
        
//除了在这里设|QueryCache外,q要在hibernate.cfg.xml中进行设|?br />         //<property name="hibernate.cache.use_query_cache">true</property>
        query.setCacheable(true);
        List userList 
= query.list();
    }
    
/**
     * 所谓gq加载,是在需要数据的时候,才真正执行数据加载操作?br />      * 延迟加蝲实现主要针对Q?br />      * 1、实体对?通过class的lazy属性,我们可以打开实体对象的gq加载功能?br />      * 2、集?br />      
*/
    
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);
        
//虽然使用了gq加载,但是我们可以通过hibernate的初始化Ҏq行强制加蝲Q这样即使session关闭之后Q关联的对象仍让可以使用
        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();
    }
    
/**
     * 关闭资源
     
*/
    
protected void tearDown() throws Exception {
        
try{
            session.close();
        }
catch(HibernateException e){
            e.printStackTrace();
        }
    }

}


]]>
Hibernate深入出(二十?-----L入浅出hibernate有感http://www.tkk7.com/wyxdeniro/archive/2010/01/02/308032.html王永?/dc:creator>王永?/author>Sat, 02 Jan 2010 07:25:00 GMThttp://www.tkk7.com/wyxdeniro/archive/2010/01/02/308032.htmlhttp://www.tkk7.com/wyxdeniro/comments/308032.htmlhttp://www.tkk7.com/wyxdeniro/archive/2010/01/02/308032.html#Feedback0http://www.tkk7.com/wyxdeniro/comments/commentRss/308032.htmlhttp://www.tkk7.com/wyxdeniro/services/trackbacks/308032.html HashTable--------------------------------net.sf.hibernate.cache.HashtableCacheProvider
1、JSC
2、EHCache->默认的二UCache实现?-------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
相对于JSC而言QEHCache更加E_Qƈ具备更好的؜存调度性能Q其~陷是目前还无法做到分布式缓存?br /> 首先讄hibernate.cfg.xml然后讄ehcache.xml最后设|缓存策略?br />
  ~存同步{略军_了数据对象在~存中的存取规则。ؓ了得缓存调度遵循正的应用U事物隔LӞ我们必须为每个实体类指定相应的缓存同步策略。Hibernate提供4U内|的~存同步{略Q?br /> 1、read-only:只读。对于不会发生改变的数据Q可使用只读型缓存?br /> 2、nonstrict-read-write:如果E序对ƈ发访问下的数据同步要求不是非怸|且数据更新操作频率较低,可以采用本选项?br /> 3、read-write:严格可读写缓存?br /> 4、transactional:事务型缓存,必须q行在JTA事物环境中?br />
  JDBC事物由Connection理Q也是_事务理实际上是在JDBC Connection中实现。事务周期限于Connection的生命周期之cR同P对于ZJDBC Transaction的Hibernate事务理机制而言Q事物管理在Session所以托的JDBCConnection中实玎ͼ事务周期限于Session的生命周期?br />   JTA事物理则由JTA容器实现QJTA容器对当前加入事物的众多Connectionq行调度Q实现其事务性要求。JTA的事物周期可横跨多个JDBC Connectin生命周期。同样对于基于JTA事务的Hibernate而言QJTA事物横跨多个Session.

  Hibernate支持2U锁机制Q即通常所说的悲观锁和乐观锁?br />   悲观锁的实现Q往往依靠数据库提供的锁机制。典型的悲观锁调用:
  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;
    
/**
     * 初始化资?br />      
*/
    
protected void setUp() throws Exception {
        
try {
            
//加蝲c\径下的hibernate.cfg.xml文g
            Configuration config = new Configuration().configure();
            
//创徏sessionFactory对象
            SessionFactory sessionFactory = config.buildSessionFactory();
            
//创徏session
            session = sessionFactory.openSession();
        } 
catch (HibernateException e) {
            e.printStackTrace();
        }        
    }
    
/**
     * 悲观?br />      * Hibernate的加锁模式有Q?br />      * 1、LockMode.NONE:无锁机制
     * 2、LockMode.WRITE:Hibernate在Insert和Update记录的时候会自动获取
     * 3、LockMode.READ:Hibernate在读取记录的时候会自动获取
     * 上述3U锁机制Z保证updateq程中对象不会被外界修改Q在目标对象上加锁,与数据库无关
     * 4、LockMode.UPGRADE:利用数据库的for update子句加锁
     * 5、LockMode.UPGRADE_NOWAIT:oracle的特定实?br />      * 注意Q只有在查询开始之前设定加锁,才会真正通过数据库的锁机制进行加锁处理?br />      
*/
    
public void addPessimismLock(){
        String hqlStr 
= "from TUser as user where user.name='Erica'";
        Query query 
= session.createQuery(hqlStr);
        query.setLockMode(
"user",LockMode.UPGRADE);//多所有返回的user对象加锁
        List userList = query.list();//执行查询
    }
    
/**
     * 乐观?br />      * 数据版本Q即为数据增加一个版本标识,在基于数据库表的版本解决Ҏ中,一般是通过为数据库表增加一个version字段来实现?br />      * d出数据时Q将此版本号一同读出,之后更新ӞҎ版本号加1.此时Q将提交数据的版本数据与数据库对应记录的当前版本信息
     * q行比对Q如果提交的数据版本号大于数据库表当前版本号Q则予以更新Q否则认为是q期数据?br />      * 
     * Hibernate在其数据讉K引擎中内|了乐观锁实现。如果不考虑外部pȝҎ据库的更新操作,利用Hibernate提供的透明化乐观锁
     * 实现Q将大大提升我们的生产力。见配置文gT_USER.hbm.xml
     * 乐观锁机刉免了长事务中的数据加锁开销Q大大提升了大ƈ发量下的pȝ整体性能表象?br />      *
     
*/
    
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();
    }
    
/**
     * 关闭资源
     
*/
    
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"
    "httpQ?/hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
>
<hibernate-mapping>
    
<!-- 
        none:无乐观锁
        version:通过版本机制实现乐观?br />         dirty:通过查发生变动过的属性实C观锁
        all通过查所有属性实C观锁
     
-->
    
<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>




]]>
Hibernate深入出(二十?-----L入浅出hibernate有感http://www.tkk7.com/wyxdeniro/archive/2009/12/22/306908.html王永?/dc:creator>王永?/author>Tue, 22 Dec 2009 07:01:00 GMThttp://www.tkk7.com/wyxdeniro/archive/2009/12/22/306908.htmlhttp://www.tkk7.com/wyxdeniro/comments/306908.htmlhttp://www.tkk7.com/wyxdeniro/archive/2009/12/22/306908.html#Feedback0http://www.tkk7.com/wyxdeniro/comments/commentRss/306908.htmlhttp://www.tkk7.com/wyxdeniro/services/trackbacks/306908.html     1、Transient(自由状?Q所谓Transient,卛_体对象在内存中的自由存在Q它与数据库中的记录无关?br />     2、Persistent(持久状?Q即实体对象处于由Hibernate框架所理的状态?br />     3、Detached(游离状?Q处于Persistent状态的对象Q其对应的Session实例关闭之后Q那么,此对象就处于"Detached"状态?br />     Transient状态的user对象与库表的数据~Z对应关系Q而Detached状态的user对象Q却在库表中存在对应的记录,只不q由于Detached对象q了sessionq个数据操作q_Q其状态的变化无法更新到库表中的对应记录?br />     处于Transient和Detached状态的对象l称为值对?VO),而处于Persistent状态的对象UCؓ持久对象(PO).q是站在实体对象是否被纳入Hibernate实体理容器的立场加以区分的Q非理的实体对象统UCؓVO,而被理的实体对象称为PO.
VO与PO的主要区别在于:
1、VO是相对独立的实体对象Q处于非理状态?br /> 2、PO是由HibernateU_其实体管理容器的对象Q它代表了与数据库中某条记录对应的Hibernate实体QPO的变化在事务提交时将反映到实际数据库?br /> 3、如果一个PO与其对应的Session实例分离Q那么此Ӟ它又会变成一个VO?br />
    不覆盖equals/hashCodeҎ的情况下我们要面对的问题Q实体对象的跨session识别。解军_法一个是实现所谓的值比对,卛_equals/hashCodeҎ中,对实体类的所有属性D行比?除了值比对,q有另外一U基于业务逻辑的对象判定方式业务关键信息判定?br />
    tx.commint();Ҏ中会调用session.flush()ҎQ在flush()Ҏ中会执行2个主要Q?br /> 1、flushEverything();//h所有数?br /> 2、execute(0);//执行数据库SQL完成持久化动作?br />
    数据~存Q在特定g基础上缓存往往是提升系l性能的关键因素。缓存是数据库数据在内存中的临时容器Q它包含了库表数据在内存中的临时拯Q位于数据库与数据访问层之间。ORM在进行数据读取时Q会Ҏ其缓存管理策略,首先在缓存中查询Q如果在~存中发现所需数据Q则直接以此数据作ؓ查询l果加以利用Q从而避免了数据库调用的性能开销?br />     相对内存操作而言Q数据库调用是一个代价高昂的q程Q对于典型企业及应用l构Q数据库往往与应用服务器位于不同的物理服务器Q这也就意味着每次数据库访问都是一ơ远E调用,Socket的创Z销毁,数据的打包拆包,数据库执行查询命令,|络传输上的延时Q这些消耗都l系l整体性能造成了严重媄响?br />     ORM的数据缓存应包含如下几个层次Q?br /> 1、事务~存Q事务~存是基于Session生命周期实现的,每个Session会在内部l持一个数据缓存,此缓存随着Session的创存在,因此也成为Session Level Cache(内部~存)
2、应用/q程U缓存:在某个应用中Q或者应用中某个独立数据讉K子集中的׃n~存。此~存可由多个事物׃n。在Hibernate中,应用U缓存在SessinFactory层实玎ͼ所有由此SessionFactory创徏的Session实例׃n此缓存。多实例q发q行的环境要特别心q程U缓存的调用?br /> 3、分布式~存Q分布式~存由多个应用~存实例l成集群Q通过某种q程机制实现各个~存实例间的数据同步QQ何一个实例的数据修改操作Q将D整个集群间的数据状态同步。由于多个实例间的数据同步机Ӟ每个~存实例发生的变动都会复制到其余所有节点中Q这Lq程同步开销不可忽视?br />
    Hibernate数据~存分ؓ2个层ơ,1、内部缓?、二U缓存hibernate中,~存在以下情况中发挥作用:
1、通过ID加蝲数据?br /> q包括了Ҏid查询数据的Session.loadҎQ以及Session.ierate{批量查询方?br /> 2、gq加?br />
    Session在进行数据查询操作时Q会首先在自w内部的一U缓存中q行查找Q如果一U缓存未能命中,则将在二U缓存中查询Q如果二U缓存命中,则以此数据作为结果返回?br />     如果数据满以下条gQ则可将其纳入缓存管?br /> 1、数据不会被W三方应用修?br /> 2、数据大在可接受的范围之内
3、数据更新频率较?br /> 4、同一数据可能会被pȝ频繁引用
5、非关键数据(关键数据Q如金融账户数据)
Hibernate本nq未提供二~存的品化实现(只是提供了一个基于Hashtable的简单缓存以供调?Q而是Z多的W三方缓存组件提供了接入接口Q我们可以根据实际情况选择不同的缓存实现版本?br />
   


]]>
java应用一http://www.tkk7.com/wyxdeniro/archive/2009/12/08/305102.html王永?/dc:creator>王永?/author>Tue, 08 Dec 2009 01:56:00 GMThttp://www.tkk7.com/wyxdeniro/archive/2009/12/08/305102.htmlhttp://www.tkk7.com/wyxdeniro/comments/305102.htmlhttp://www.tkk7.com/wyxdeniro/archive/2009/12/08/305102.html#Feedback0http://www.tkk7.com/wyxdeniro/comments/commentRss/305102.htmlhttp://www.tkk7.com/wyxdeniro/services/trackbacks/305102.html     使用"=="与equals到底有哪些不?
    equals:可以比较内容Q是2个字W串内容的比较?br />     ==Q数值比较,比较的是内存地址的值是否相{?br />
    一个字W串是Stringcȝ匿名对象?br />     String name1 = new String("wyq");->开辟了2个空_其中一个是垃圾I间?br />     String name2 = "wyq";->开辟了一个空_所以应该选择它?br />
    String的另一个特D之处:String使用了Java中的׃n模式Q它只要发现在内存中有这块数据,不会在内存中重新生成?br />     StringcM的内容一旦声明则不可改变?br />     StringBuffer与String的本质区别,在于StringBuffer可以改变?br />
    this可以调用本类中的属性,也可以调用本cM的方?含构造方法this())?br />     注意Q构造方法本w必d首行被用,Zl类中的属性初始化?br />     this调用属性、本cL法、构造方法这三点是this的基本应用,也是最常用的,但是以上三点实际上可以综合成一?--表示当前对象?br />     this表示当前对象主要应用在一点:用于q行对象的比较?br />
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;
}



]]>
Spring学习W记(十六)-----Spring in Action http://www.tkk7.com/wyxdeniro/archive/2009/11/22/303208.html王永?/dc:creator>王永?/author>Sun, 22 Nov 2009 03:43:00 GMThttp://www.tkk7.com/wyxdeniro/archive/2009/11/22/303208.htmlhttp://www.tkk7.com/wyxdeniro/comments/303208.htmlhttp://www.tkk7.com/wyxdeniro/archive/2009/11/22/303208.html#Feedback0http://www.tkk7.com/wyxdeniro/comments/commentRss/303208.htmlhttp://www.tkk7.com/wyxdeniro/services/trackbacks/303208.html    在Y件中Q要么全有要么全无的操作成ؓ事务。事务允怽把几个操作组成一个单一的工作单元,q个工作单元要么全部发生要么全部不发生。如果每件事都顺利,那么q个事务是成功的。但是如果Q何一件事情出错的话,那么已经发生的行为就被清除掉Q就像什么事情都没发生一栗?br />     Spring对事务管理有丰富的支持,E序控制的和声明式的?br />     原子?Atomic):事务׃个或多个行ؓl定在一L成,好像是一个单独工作单元。原子性确保在十五中的所有操作要么都发生Q要么都不发生?br />     一致?Consistent):一旦一个事务结束了(不管成功p|)Q系l所处的状态和它的业务规则是一致的。就是说数据应当不会被破坏?br />     隔离?Isolated):事务应该允许多个用户操作同一数据Q一个用L操作不会和其他用L操作相؜淆。因此,事务必须是互盔RȝQ防止ƈ发读写同一数据的情况发生?br />     持久?Durable):一旦事务完成,事务的结果应该持久化Q这样不什么样的系l崩溃,他们都将q免于难?br />  
    Spring对程序控制事务管理的支持和EJB的有很大不同。EJB的事务管理和JTA密不可分Q和EJB不同的是QSpring使用了一U回调机Ӟ把真实的事务实现从事务代码中抽象出来。选择E序控制事务理q是声明式事务管理,很大E度上是在细_度控制与简便操作之间做出决定。当你在代码中编写事务时Q你能精控制事务的边界Q在你希望的地方_的开始和l束。典型的情况下,你不需要程序控制事务所提供的细_度控制Q你会选择在上下文定义文g中声明你的事务?/p>

    Spring对声明式事务理的支持是通过它的AOP框架实现的。这样做是非常自然的Q因Z务是pȝU的Q凌驾于应用的主要功能之上的?/p>

    在Spring里,事务属性是对事务策略如何应用到Ҏ的描q。这个描q包括:传播行ؓ、隔ȝ别、只LC、事务超旉?br />     传播行ؓQ?br />     PROPAGATION_MANDATORY:表示该方法必运行在一个事务中。如果当前事务不存在Q将抛出一个异常?br />     PROPAGATION_NESTED:表示如果当前已经存在一个事务,则该Ҏ应当q行在一个嵌套的事务中。被嵌套的事务可以从当前事务中单独的提交或回滚。如果当前事务不存在Q那么它看v来和PROPAGATION_REQUIRED没有两样?br />     PROPAGATION_NEVER:表示当前的方法不应该q行在一个事务上下文中。如果当前存在一个事务,则会抛出一个异常?br />     PROPAGATION_NOT_SUPPORTED:表示该方法不应在事务中运行。如果一个现有的事务正在q行中,它将在该Ҏ的运行期间被挂v?br />     PROPAGATION_REQUIRED:表示当前Ҏ必须q行在一个事务中。如果一个现有的事务正在q行中,该方法将q行在这个事务中。否则的话,要开始一个新的事务?br />     PROPAGATION_REQUIRES_NEW:表示当前Ҏ必须q行在它自己的事务里。它启动一个新的事务。如果有事务q行的话Q将在这个方法运行期间被挂v?br />     PROPAGATION_SUPPORTS:表示当前Ҏ不需要事务处理环境,但如果有一个事务已l在q行的话Q这个方法也可以在这个事务里q行?/p>

   传播规则回答了一个问题:是新的事务是否要被启动或是被挂P或者方法是否要在事务环境中q行?/p>

   隔离U别Q在一个典型的应用中,多个事务q发q行Q经怼操作同一个数据来完成它们的Q务。ƈ发,虽然是必ȝQ但会导致下面问题:
1、脏读:脏读发生在一个事务读取了被另一个事务改写但q未提交的数据时。如果这些改变在E后被回滚,那么W一个事务读取的数据是无效的?br /> 2、不可重复读Q不可重复读发生在一个事务执行相同的查询2ơ或2ơ以上,但每一ơ查询结果都不同时。这通常是由于另一个ƈ发事务在2ơ查询之间更C数据?br /> 3、读:q读和不可重复读怼。当一个事务读取几行纪录后Q另一个ƈ发事务插入一些记录,q读发生了。隔ȝ别有如下几个Q?br /> ISOLATION_DEFAULT:使用后端数据库默认的隔离U别
ISOLATION_READ_UNCOMMITTED:允许你读取还未提交的改变了的数据Q可能导致脏诅R诅R不可重复读
ISOLATION_READ_COMMITTED:允许在ƈ发事务已l提交后d。可防止脏读Q但q读和不可重复读仍可能发生?br /> ISOLATION_REPEATABLE_READ:对相同字D늚多次d的结果是一致的Q除非数据被事务本n改变。可防止脏读和不可重复读Q但q读仍可能发生?br /> ISOLATION_SERIALIZABLE:完全服从ACID的隔ȝ别,保不发生脏诅R不可重复读和诅R这在所有隔ȝ别中也是最慢的?/p>

    只读Q如果一个事务只对后端是据库执行L作,数据库就可能利用事务只读的特性,使用某些优化措施。通过声明一个事务ؓ只读Q你q了后端数据库一个机会,来应用那些它认ؓ合适的优化措施。因为只ȝ优化措施是在事务启动时由后端数据库实施的Q所以,只有那些具有可能启动新事务的传播行为的Ҏ的事务标记成只读才有意义(PROPAGATION_REQUIRED,PROPAGATION_REQUIRES_NEW和PROPAGATION_NESTED) TransactionProxyFactoryBean参照一个方法的事务属性,军_如何在那个方法上执行事务{略?br />

<?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>
    
<!-- q个对象有一个gؓcourseService的id.当应用从应用上下文里h一个courseServiceӞ它将得到一个被
    TransactionProxyFactoryBean包裹的实例?nbsp;
-->
    
<bean id="courseService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        
<!-- 代理所实现的接?nbsp;-->
        
<property name="proxyInterfaces">
            
<list>
                
<value>
                    com.springinaction.training.service.CourseService
                
</value>
            
</list>
        
</property>
        
<!-- 被代理的对象 -->
        
<property name="target">
            
<ref bean="courseServiceTarget"/>
        
</property>
        
<!-- 事务理?nbsp;-->
        
<property name="transactionManager">
            
<ref bean="transactionManager"/>
        
</property>
        
<!-- 事务的属性源 -->
        
<property name="transactionAttributeSource">
            
<ref bean="transactionAttributeSource"/>
        
</property>
    
</bean>
    
<!-- 要知道尽可以改变MatchAlwaysTransactionAttributeSource的事务属性参敎ͼ但它Lq回相同的事务属性,?br />     不关心参与交易的哪一个方法。当你有一个相对简单的应用Q把同样的事务策略应用到所有方法都没问题时Q用MatchAlwaysT
    ransactionAttributeSourceq当好。但是,在那些更为复杂的应用中,你很可能需要对不同的方法应用不同的事务{略。在那样
    情况下,你需要在应用何种{略的问题上做更多精的控制?nbsp;
-->
    
<bean id="transactionAttributeSource" class="org.springframework.transaction.interceptor.MatchAlwaysTransactionAttributeSource">
        
<property name="transactionAttribute">
            
<ref bean="myTransactionAttribute"/>
        
</property>
    
</bean>
    
<!-- 定义事务{略 -->
    
<bean id="myTransactionAttribute" class="org.springframework.transaction.interceptor.DefaultTransactionAttribute">
        
<!-- 传播行ؓ -->
        
<property name="propagationBehaviorName">
            
<value>PROPAGATION_REQUIRES_NEW</value>
        
</property>
        
<!-- 隔离U别 -->
        
<property name="isolationLevelName">
            
<value>ISOLATION_REPEATABLE_READ</value>
        
</property>
    
</bean>
</beans>

 

除了transactionAttributeSource对象l入到TransactionProxyFactoryBean的transactionAttributeSource属性中外,q有一U简单的Ҏ。发展到现在QTransactionProxyFactoryBean也有一个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>
    
<!-- q个对象有一个gؓcourseService的id.当应用从应用上下文里h一个courseServiceӞ它将得到一个被
    TransactionProxyFactoryBean包裹的实例?nbsp;
-->
    
<bean id="courseService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        
<!-- 代理所实现的接?nbsp;-->
        
<property name="proxyInterfaces">
            
<list>
                
<value>
                    com.springinaction.training.service.CourseService
                
</value>
            
</list>
        
</property>
        
<!-- 被代理的对象 -->
        
<property name="target">
            
<ref bean="courseServiceTarget"/>
        
</property>
        
<!-- 事务理?nbsp;-->
        
<property name="transactionManager">
            
<ref bean="transactionManager"/>
        
</property>
        
<!-- 事务的属性源 -->
        
<property name="transactionAttributeSource">
            
<ref bean="transactionAttributeSource"/>
        
</property>
    
</bean>
    
<!-- NameMatchTransactionAttributeSource的properties属性把Ҏ名映到事务属性描q器上。注意CourseException
    用一个负h记。异常可以用负号或正h讎ͼ当负号异常抛出时Q将触发回滚;相反的,正号异常表示事务仍可提交Q即使这个异常抛?nbsp;
-->
    
<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>
                
<!-- q可以用通配W?nbsp;-->
                
<prop key="get*">
                    PROPAGATION_SUPPORTS
                
</prop>
            
</props>
        
</property>
    
</bean>
</beans>

 

 



]]>
Hibernate深入出(二十?-----L入浅出hibernate有感 http://www.tkk7.com/wyxdeniro/archive/2009/11/21/303169.html王永?/dc:creator>王永?/author>Sat, 21 Nov 2009 13:37:00 GMThttp://www.tkk7.com/wyxdeniro/archive/2009/11/21/303169.htmlhttp://www.tkk7.com/wyxdeniro/comments/303169.htmlhttp://www.tkk7.com/wyxdeniro/archive/2009/11/21/303169.html#Feedback0http://www.tkk7.com/wyxdeniro/comments/commentRss/303169.htmlhttp://www.tkk7.com/wyxdeniro/services/trackbacks/303169.html    HQL作ؓHibernate的查询语aQ提供了ANSI SQL面向对象的封装Ş式?br />     与Criteria和HQL互ؓ补充QHibernate也提供了对原生SQL以及存储q程的支持,相对于JDBC的SQL操作QHibernate提供了更为妥善的装。代码如下:

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>
    
<!-- Z存储q程查询 sql-query节点的callable属性设定ؓtrue,指明当前查询Z存储q程定义-->
    
<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相同QNative SQL也可以在实体映射文g中进行配|:



]]>
EJB学习W记(十三) http://www.tkk7.com/wyxdeniro/archive/2009/11/21/303139.html王永?/dc:creator>王永?/author>Sat, 21 Nov 2009 04:32:00 GMThttp://www.tkk7.com/wyxdeniro/archive/2009/11/21/303139.htmlhttp://www.tkk7.com/wyxdeniro/comments/303139.htmlhttp://www.tkk7.com/wyxdeniro/archive/2009/11/21/303139.html#Feedback0http://www.tkk7.com/wyxdeniro/comments/commentRss/303139.htmlhttp://www.tkk7.com/wyxdeniro/services/trackbacks/303139.html阅读全文

]]>
Hibernate深入出(二十一)-----L入浅出hibernate有感http://www.tkk7.com/wyxdeniro/archive/2009/11/15/302447.html王永?/dc:creator>王永?/author>Sun, 15 Nov 2009 14:25:00 GMThttp://www.tkk7.com/wyxdeniro/archive/2009/11/15/302447.htmlhttp://www.tkk7.com/wyxdeniro/comments/302447.htmlhttp://www.tkk7.com/wyxdeniro/archive/2009/11/15/302447.html#Feedback0http://www.tkk7.com/wyxdeniro/comments/commentRss/302447.htmlhttp://www.tkk7.com/wyxdeniro/services/trackbacks/302447.html    Criteria提供了符合面向对象编E风格的查询装模式。不qHQL提供了更加丰富灵zȝҎ,它在늛了Criteria功能范围的前提下Q提供了更ؓ强大的查询能力。HQLZSQL,同时提供了更加面向对象的装?br />     实体查询QHQL子句本n大小写无养I但是其中出现的类名和属性名必须注意大小写区分。需要注意的是,Hibernate中,查询的目标实体存在着l承关系的判定,?from TUser"返回所有TUser以及TUser子类的记录,我们知道QJava中所有类的根c都是java.lang.Object,那么Q如下HQL返回数据库中所有库表的记录Q?from java.lang.Object",在where子句中,我们可以通过比较操作W指定条Ӟ=Q?lt;>,>,>,<=,>=,between,notbetween,in,not in,is,like{。与SQL相同Q我们可以通过and,or{逻辑q接W组合各个逻辑表达式?/p>

    属性查询:有时我们q不需要获取完整的实体对象Q只需要现实部分列Q通过HQL也可以做到这点,如:"select user.name,user.age form TUser user"表明我们需要读取name和age属性的内容Q而此Ӟq回的list数据l构中,每个条目都是一个对象数l?Object[]),其中一ơ包含了我们所获取的属性数据?br />     如果觉得q回数组的方式不够符合面向对象的风格Q我们可以通过在HQL中动态构造对象实例的Ҏ对这些^面化的数据进行封装?select new TUser(user.name,user.age) from TUser user",我们通过HQL获取数据的部分属性|与此同时Q我们也可以在HQL的select字句中用统计函敎ͼ甚至原生SQL函数Q或者利用distinct关键字,剔除q回集中的重复记录?/p>

    实体更新与删除:在Hibernate2中,HQL仅仅用于数据查询Q而在Hibernate3中,HQL具备了更加强大的功能。实体更C删除是其中的主要特征之一?/p>

    分组和排序:与SQLcMQHQL通过order by子句实现Ҏ询结果的排序Qorder by子句可以指定多个排序条gQ?from TUser user order by user.name ,user.age desc"通过Group by子句可进行分l统计。如Q?select count(user),user.age from TUser user group by user.age",我们知道where子句可以对记录进行甄选。那么,对于Group by子句获得的结果集我们可以通过Having子句q行甄选。例如:"select count(user),user.age from TUser user gourp by user.age having count(user)>10".

     参数l定Q类似JDBC中的SQL操作Q我们可以通过序占位W??"对参数进行标识,q在之后对参数内容进行填充。徏议用Query接口"from TUser user where user.name=? and user.age>?",q里除了序占位W,我们q可以用引用占位符Q如Q?from TUser where name=:name"参数l定机制可以使得查询语法与具体参数数值相互独立。这P对于参数不同Q查询语法相同的查询操作Q数据库卛_实施性能优化{略。同Ӟ参数l定机制也杜l了参数值对查询语法本n的媄响?/p>

     引用查询QSQL语句h在代码之间将破坏代码的可L,q得系l的可维护性降低。ؓ了避免这L情况出现Q我们通常采取SQL配置化的方式Q也是SQL保存在配|文件中Q需要调用的时候在q行d?br /> <query name="queryByName">
 <![CDATA[
  from TUser user where user.name=:name
 ]]>
</query>
之后Q我们可通过session.getNamedQueryҎ从配|文件中调用引用的HQL.

     联合查询Qinner join,left outer join,right outer join,full join
     子查询:如:"from TUser user where (select count(*) from user.addresses)>1"HQL中,子查询必d现在where子句中,且必M一对圆括号包围?br />      数据加蝲方式QHibernate支持以下几种数据加蝲方式Q?br /> 1、即时加载:当实体加载完毕后Q立卛_载其兌数据?br /> 2、gq加载:实体加蝲Ӟ其关联数据ƈ非即刻获取,而是当关联数据第一ơ被讉K时再q行d?br /> 3、预先加载:预先加蝲Ӟ实体及其兌对象同时dQ这与即时加载类伹{?br /> 4、批量加载:对于x加蝲和gq加载,可以采用扚w加蝲方式q行性能上的优化?/p>

]]>
EJB学习W记(十二) http://www.tkk7.com/wyxdeniro/archive/2009/11/15/302399.html王永?/dc:creator>王永?/author>Sun, 15 Nov 2009 04:21:00 GMThttp://www.tkk7.com/wyxdeniro/archive/2009/11/15/302399.htmlhttp://www.tkk7.com/wyxdeniro/comments/302399.htmlhttp://www.tkk7.com/wyxdeniro/archive/2009/11/15/302399.html#Feedback0http://www.tkk7.com/wyxdeniro/comments/commentRss/302399.htmlhttp://www.tkk7.com/wyxdeniro/services/trackbacks/302399.html持久化实体Bean的两U方式:
    既然需要将实体Bean映射到存储源中,应用肯定需要提供操作RDBMS的代码?br />     Bean理持久化实体Bean,是手工完成持久化行ؓ的EJBcd。换句话所Q组件开发者必d发代码,以将内存中的持久化域存储到底层存储源中。这U方式成为BMP?br />     EJB规范q提供了BMP的替代组件类型:借助于EJB容器完成数据的持久化。这是容器理持久?CMP)。此Ӟ通常都要持久化逻辑从CMP中剥d来。然后借助于容器提供的工具完成数据的自动持久化。最?EJB容器生成访问数据库的代码。注意,CMP是独立于MO/RMapping技术的数据对象Q因此可以在各种企业环境中重用CMPlg?br />     CMP极大减少了实体Bean的代码量Q因Z用直接编写JDBC代码了。EJB容器会处理所有的持久化操作,q是EJB势能应用的优势之一?br />     在执行ejbCreate()Ҏ期间Q即在初始化内存中的实体BeanӞ会在底层RDBMS中插入新的记录,q将q些记录同实体Bean实例建立h关pR当调用BMP实体Bean的ejbCreate()Ӟ它将负责生成RDBMS中的数据。类似的Q当调用BMP实体Bean的ejbRemo()Ӟ它将负责RDBMS中数据的删除?/p>

    在EJB领域中,客户q没有直接调用EJB实例Q它们仅仅调用了EJB对象代理。借助于Home对象能够生成EJB对象。因此,对于定义在EJB BeancM的各个ejbCreate()ҎQ在Home接口中也存在对象的create()Ҏ。当客户调用Home对象的create()ҎӞ容器把调用h委派lejbCreate()Ҏ?br />     开发者可以通过多种方式查找实体Bean.需要在实体Bean的Home接口中列丑ևq些查找Ҏ。我们称q些Ҏ?finder"Ҏ。除了暴露创建、销毁实体Bean实例的方法外QHome接口q需暴露finderҎ。这是实体Bean的Home接口同其他EJBcd中的Home接口的最明显区别?/p>

    实体上下文,所有的EJBlg都存在上下文对象供组件访问到容器环境使用。这些上下文对象含有EJB容器讄的环境信息。因此EJBlg能够讉KC下文Q从而获取各U信息,比如事务Q安全性信息。对于实体Bean而言Q存在javax.ejb.EntityContext上下文接口。它l承自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();
}
    通过调用getEJBObject()ҎQ当前客戯够获得某实体Bean实例对应的EJB对象。客戯用的是EJB对象Q而不是实体Bean实例本n。因此,客户能够在应用中引用q回的EJB对象?br />     实体Bean实例对应的主键可以通过getPrimaryKey()Ҏ获得。主键唯一标识某实体Bean实例。当实体Bean实例存储到存储源中时Q可以用主键获得单个实体Bean实例。由于在RDBMS中也存在主键Q因此主键能够唯一标识某个实体Bean实例?/p>

]]>
EJB学习W记(十一) http://www.tkk7.com/wyxdeniro/archive/2009/11/15/302395.html王永?/dc:creator>王永?/author>Sun, 15 Nov 2009 03:46:00 GMThttp://www.tkk7.com/wyxdeniro/archive/2009/11/15/302395.htmlhttp://www.tkk7.com/wyxdeniro/comments/302395.htmlhttp://www.tkk7.com/wyxdeniro/archive/2009/11/15/302395.html#Feedback0http://www.tkk7.com/wyxdeniro/comments/commentRss/302395.htmlhttp://www.tkk7.com/wyxdeniro/services/trackbacks/302395.html    实体Bean是持久化对象Q它能够存储到持久化存储源中。实体Bean是EJB~程模型中最为重要的利器之一?br />     对象映到RDBMS的技术称之ؓ对象-关系映射。它能够实现内存对象同关pL据的怺转换。O/R映射器能够将Java对象映射CQ意RDBMS模式。比如简单的O/RMapping引擎能够JavacL成SQL表定义。Java语言提供的对象序列化功能比O/RMapping单多了。O/RMapping是更加复杂、成熟的对象持久化机制。通过Java对象分解成关pL据,应用便能够查扑ֈ所需的数据了?br />     通过如下两种方式能够完成Java对象到关pL据的映射。其一Q通过编码实现O/RMapping.其二Q借助于O/RMapping产品Q自动完成映过E,比如QHibernate.
    对于M成熟的、基于OO多层部v的企业应用而言Qd以划分出2U截然不同的lgcd?、应用逻辑lgQ?、持久化数据lg。会话Bean和实体Bean的最大区别在于实体Bean是实体,客户是可以看的到的。因此实体Bean能够独立于客户应用的生命周期。对于实体Bean而言Q通过比较它们各自含有的数据便能够区分不同的实体Bean.q意味着客户能够引用单个的实体Bean实例q将它传入到其他应用中,不同的客户可以共享同L实体Bean实例Q这对于会话Bean是办不到的。会话Bean建模q程或者工作流。实体Bean本n是客户Q它是持久化状态对象?br />     实体Bean实例存在几方面的含义Q?br /> 1、持久化数据的Java表示Q即它能够从持久化存储源装蝲数据到内存中。同Ӟ实体Bean实例能够装载到的数据存储到实例的成员变量中?br /> 2、通过修改内存中的Java对象可以改变数据的取倹{?br /> 3、还可以修改后的数据保存到存储源汇中,从而更新RDBMS中的物理数据?br />     实体Bean是持久化对象Q它能够长期存在。即使出C不可恢复的失败,比如应用服务器瘫痪、数据库瘫痪Q实体Beanq是能够存活的。原因在于实体Bean只是对底层具有容错行为的持久化存储源中数据的映射Q因此,即极其瘫痪Q内存中的实体Bean实例q可以重新构建。在极其重启后,实体Bean实例需要从底层存储源装载数据,q用获得的数据对实体Bean实例中的各个域进行setter操作。实体Bean比客户会话的生命周期要长。可以认为,数据库中记录存活的时间决定了实体Bean实例的生命周期?br />     相同数据往往存在多分物理拯Q比如内存中的实体Bean实例、实体Bean数据本nQ他们都是对RDBMS中数据的拯。因此,EJB容器需要提供某U机制实现数据在Java对象和RDBMS间的自动传输。实体Bean的BeancMؓ此提供了2个特D方法:
ejbLoad():它能够从持久化存储源中读取数据,q存储到实体Bean实例的域中?br /> ejbStore():它能够将当前实体Bean实例的域g存到底层RDBMS中?br /> 那么何时需要完成内存中实体Bean实例和RDBMS中数据的传递和转换Q开发者需要知道是谁调用了ejbLoad()和ejbStore(),{案是EJB容器。它们是回调ҎQ供EJB容器调用。EJB规范要求所有的实体Beanlg必须提供它们。至于读取或存储数据的时机,由EJB容器军_。依据实体Bean实例当前的事务状态,EJB容器会自动计出需要调用实体Bean实例中的ejbLoad()QejbStore()Ҏ的时机,q也是用实体Beanlg的优势之一Q开发者不用考虑java对象同步底层RDBMS的问题?/p>

    Z满大量q发客户讉K同一数据的要求,架构师需要借助于实体Bean设计出高性能的访问系l。如下给ZU解x案:允许多个客户׃n同一实体Bean实例。因此,实体Bean实例能够同时服务多个客户。尽表面上看是可行的,但是对于EJB而言Q这是行不通的。原因有亮点Q其一Qؓ实现实体Bean实例服务多个q发客户Q必M证实体Bean实例是线E安全的Q开发线E安全的代码q不是一件容易的工作Q而且l常会出C堆错我。其二,底层事务pȝ几乎不可能控制多个线E的q发执行Q事务往往同具体的U程l定在一赗因此,Z上述理由Q单个实体Bean实例只能够在单线E环境中q行。对于所有的EJBlg而言Q包括会话Bean、消息驱动Bean、实体BeanQ它们都是以单线E方式运行的?br />     当然Q强制要求各个实体Bean实例只能同时服务单个客户Q将引入性能瓉。由于实例以单线E方式运行,客户需要排队等候实体Bean实例Q从而获得对实体Bean实例的调用,q对于大型企业应用而言Q是不允许出现的
    Z提供pȝ性能QEJB容器会实例化同一实体Bean的多个实例。这使得多个客户能够q发同不同实体Bean实例q行交互Q而这些实体Bean实例代表了同一RDBMS数据。事实上Q这是EJB容器的运行行为。因此,客户再也不用排队{候实体Bean实例Q因为存在多个实体Bean实例了?br />     一旦多个实体Bean实例代表了同一RDBMS数据Q则引入了另外一个问题:数据瘫痪。如果多个实体Bean实例代表的数据是通过~存理的,则需要在内存中拷贝多分缓存中的数据。显Ӟ某些~存中的数据变得陈旧,因此会出现很多过期的数据?br />     Z实现实体Bean实例的缓存一致性,各个实体Bean实例必须同底层存储元q行同步。EJB容器通过调用ejbLoad(),ejbStore()Ҏ同步q些实体Bean实例?br />     至于实体Bean实例同底层RDBMS数据的同步频率,则取决于事务。事务将各个客户h隔离h。借助于事务实现数据同步?/p>

    EJB容器提供的实例池是很有意义的。当Ӟq不是只有实体Bean才存在实例池。在实体Bean实例重新分配l不同EJB对象Ӟ会存在一些问题,q要求容器去解决。比如当实体Bean实例被指定给EJB对象Ӟ它可能还持有资源(比如Socketq接)。如果将实体Bean实例攄在实例池中,Socketq接不在需要。因此ؓ实现资源的获取和释放Q实体Bean的Beanc需要实现如?个回调方法:
1、ejbActivate().在将实体Bean实例从实例池中取出来ӞEJB容器会自动调用它。该q程UC为激zR进而,EJB容器会将实体Bean实例分配l某EJB对象Qƈ同时获得主键对象。在执行ejbActivate()Ҏ期间Q实例需要获得所需的资源,比如Socke,否则Q在实体Bean实例分配l某EJB对象Ӟ无法对资源进行操作?br /> 2、ejbPassivate().在将实体Bean实例攄到实例池中时QEJB容器会调用它。注意,它也是回调方法。这一q程UC为挂赗进而,EJB容器需要从某EJB对象中取回分配于它的实体Bean实例Qƈ实例的主键对象也收回。在执行ejbPassivate()Ҏ期间Q需要释放ejbActivate()执行期间获得的相兌源,比如QSocket.
    一旦实体Bean实例被挂P不但要释攑֮持有的资源,q将实例的状态信息保存v来。因此,实体Bean实例最新的状态信息可以从RDBMS中找C。ؓ了保存实体Bean实例的域信息到RDBMS中,容器要在挂v实例前调用ejbStore()Ҏ。类似的Q一旦实体Bean被激z,不但要获得所需的资源,q要从RDBMS装蝲最新的数据Qؓ了完成数据的dQEJB容器在Ȁzd体Bean实例后调用ejbLoad()Ҏ?/p>


 



]]>
վ֩ģ壺 þþƷ7777| Ʒһֱ | ŷۺһ| Ļ벻Ӱ| ɫ߳Ƶ | պƷһůů| ŮAëƬ | Ļ߹ۿ| fc2˳Ƶ| Ļ| ޳ۺӰԺԺ| ĻƵ| պһ| èԴ߹ۿ| 67paoǿ| һ| Ƶ߹ۿ| Ʒ޵һ| ձxxwwxxwwƵ| ˳ѵӰ| ɫAAVѲ| aëƬ߹ۿ| ׾ƷƵ| պһѲ| ۺϳ| ߹ۿ޵Ӱ| ĻƵ| ֳִִӲ3pƵ| ޹һ| ޹Ƭ߹ۿ | ޾Ʒҹ| Ƶ߹ۿ| 91޹˾Ʒ| AVһAV| av뾫Ʒ| Av뾫Ʒ | ۺϼС˵| AV뼤Ƭ| ޹Ѽһ| Ʒѹۿ| Ʒѹۿ|