青韶论坛
  • 注册
  • 登录
  • 会员
  • 标签
  • 帮助
青韶论坛 » 『 编程设计 』 » Note,About Spring, Hibernate, Webwork, etc..
‹‹ 上一主题 | 下一主题 ››
发新话题
  • 发新话题
  • 发布投票
  • 发布商品
  • 发布悬赏
  • 发布活动
  • 发布辩论
  • 发布视频
打印

Note,About Spring, Hibernate, Webwork, etc..

楼主 大 中 小 发表于 2008-4-8 13:19  只看该作者

Note,About Spring, Hibernate, Webwork, etc..

Spring中的通知类型


org.aopalliance.intercept.MethodInterceptor
拦截对目标对象方法调用
该接口定义为
public Object invoke(MethodInvocation methodInvocation) throws Throwable;
实现接口的这个方法时,当调用methodInvocation.proceed()时,就是调用目标方法,在调用目标方法之前的操作为前置操作,调用之后return之前的操作为后续操作。


org.springframework.aop.BeforeAdvice
在目标方法被调用之前调用
       该接口定义为

void before(Method method, Object[] args, Object target) throws Throwable;

       这个接口提供了目标方法、参数数组及目标对象为参数。要注意的是不能改变这些参数的值,不能替换参数对象以及目标对象。

org.springframework.aop.AfterReturningAdvice
在目标方法被调用之后调用
接口定义如下
void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable;
该方法除了能获得像BeforeAdvice同样的参数列表之后,可以得到目标方法的返回值即returnValue。注意同样不能替换这些值。改变执行流程的惟一办法就是抛出异常。对异常的处理方法和MethodBeforeAdvice一样。

Org.springframework.aop.ThrowsAdvice
当目标方法抛出异常时调用。
      



org.springframework.aop.framework.ProxyFactoryBean 创建一个被通知的类。
常用的属性有:

1)
、target
代理的目标对象(要被通知的对象)

2
)、proxyInterfaces
代理应该实现的接口列表

3
)、interceptorNames
需要应用到目标对象上的通知Bean的名字,可以是拦截器、Advisor或其他通知类型的名字。这个属性必须按照BeanFactory中使用的顺序设置。
<bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">

<property name="proxyInterfaces">


<value>com.somepackage.ProxyInterface</value><!—
代理实现的接口类路径全名-->

</property>


<property name="interceptorNames">


<list>


<value>firstAdvice</value>
<!--
首先被应用的advice通知-->

<value>secondAdvice</value>
<!--
接着被应用的通知-->

<!--<value>theTarget</value>

<!--数组最后一个可以是自己的目标Bean,不推荐-->

</list>


</property>


<property name="target>


<value>theTarget</value>


</property>

</bean>


Spring切入点


       切入点决定了一个特定类的特定方法是否满足一条特定的规则。如果一个方法确实符合,通知就应用到该方法上。切入点可以让我们以一种灵活的方式定义在什么地方将通知织入到我们的类中。
       值得关注的接口有:

org.springframework.aop.Pointcut


org.springframework.aop.ClassFilter


org.springframework.aop.MethodMatcher

       实现上面的几个接口实现自己的切入点,不过平时通常使用的是Spring预定义的切入点。

Advisor
:把通知和切入点组合到一个对象中,org.springframework.aop.PointcutAdvisor。
       静态切入点只在代理创建的时候执行一次,动态切入点在运行期间每次方法调用都执行。性能来说静态切入点比动态切入点好。
       若想自己创建自制的静态切入点,只要继承

org.springframework.aop.support.StaticMethodMatcherPointcut

       就行了,对于大多数需求来说,只要使用Spring提供的静态切入点就可以了。如:


org.springframework.aop.support.NameMatchMethodPointcut

       以下配置通过NameMatchMethodPointcutAdvisor把NameMatchMethodPointcut和beforeGreet这个Advice组合到一起。

<bean id="pointcutTest"
class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">




<property name="mappedName">




<value>say*<value>




</property>




<property name="advice">




<ref bean="someAdvice" />




</property>



</bean>


<bean id="proxyFactoryBean"
class="org.springframework.aop.framework.ProxyFactoryBean">



<!---------------------
省略其它----------------------->



<property name="interceptorNames">



<list>



<value>pointcutTest</value>



</list>



</property>



<!----------------------
省略其它----------------------->



</bean>


上面的配置中,只有当调用的方法匹配“say*”这个正则表达式时,someAdvice这个Advice才会被调用。


另外,更复杂的正则表达式匹配应通过RegexpMethodPointcutAdvisor来完成。







[ 本帖最后由 大饼先生 于 2008-4-15 10:47 编辑 ]

闲看庭前花开花落

      
           漫随天外云卷云舒
      
大饼先生

版主

Rank: 16Rank: 16Rank: 16Rank: 16

重返江湖

帖子
2519 
青韶币
4703  
魅力
18  
威望
9  
注册时间
2003-10-7 

元老奖章

  • 个人空间
  • 发短消息
  • 加为好友
  • 当前离线

TOP

QQ
UID
1166 
帖子
2519 
精华
14 
积分
12621 
青韶币
4703  
魅力
18  
威望
9  
阅读权限
100 
性别
男 
在线时间
743 小时 
注册时间
2003-10-7 
最后登录
2008-10-14 

查看详细资料

沙发 大 中 小 发表于 2008-4-9 16:25  只看该作者

Note, About Spring-Hibernate config.

<!--加载类路径下的config.properties配置文件,以${keyName}这种方式访问-->
<bean id="propertiesConfig"
class="org.springframework.beans.factory.config. PropertyPlaceholderConfigurer">
<property name="locations">
        <list>
                <value>classpath:config.properties</value>
        </list>
</property>
</bean>

<!--配置数据源-->
<bean id="dataSource"
class="org.apache.common.dbcp.BasicDataSource"
destory-method="close" autowire="byName">
<property name="driverClassName">
        <value>${jdbc.dbDriver}</value>
</property>
<property name="url">
        <value>${jdbc.dbUrl}</value>
</property>
<property name="username">
        <value>${jdbc.dbUser}</value>
</property>
<property name="password">
        <value>${jdbc.dbPassword}</value>
</property>
</bean>

<!--配置SessionFactory-->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
        <ref bean="dataSource" />
</property>
<property name="mappingDirectoryLocations">
        <list>
                <value>classpath:somePackage/</value>
        </list>
</property>
<property name="hibernateProperties">
        <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <!--        <prop key="other properties key">value</prop>  -->
        </props>
</property>
</bean>

[ 本帖最后由 大饼先生 于 2008-4-9 16:26 编辑 ]

闲看庭前花开花落

      
           漫随天外云卷云舒
      
大饼先生

版主

Rank: 16Rank: 16Rank: 16Rank: 16

重返江湖

帖子
2519 
青韶币
4703  
魅力
18  
威望
9  
注册时间
2003-10-7 

元老奖章

  • 个人空间
  • 发短消息
  • 加为好友
  • 当前离线

TOP

QQ
UID
1166 
帖子
2519 
精华
14 
积分
12621 
青韶币
4703  
魅力
18  
威望
9  
阅读权限
100 
性别
男 
在线时间
743 小时 
注册时间
2003-10-7 
最后登录
2008-10-14 

查看详细资料

板凳 大 中 小 发表于 2008-4-9 16:42  只看该作者
测试代码:
org.springframework.context.ApplicationContext context =
           new org.springframework.context.support.FileSystemXmlApplicationContext("applicationContext.xml");

org.hibernate.SessionFactory sessionFactory = (SessionFactory) context.getBean("sessionFactory");

org.hibernate.Session session = sessionFactory.openSession();

.......

闲看庭前花开花落

      
           漫随天外云卷云舒
      
大饼先生

版主

Rank: 16Rank: 16Rank: 16Rank: 16

重返江湖

帖子
2519 
青韶币
4703  
魅力
18  
威望
9  
注册时间
2003-10-7 

元老奖章

  • 个人空间
  • 发短消息
  • 加为好友
  • 当前离线

TOP

QQ
UID
1166 
帖子
2519 
精华
14 
积分
12621 
青韶币
4703  
魅力
18  
威望
9  
阅读权限
100 
性别
男 
在线时间
743 小时 
注册时间
2003-10-7 
最后登录
2008-10-14 

查看详细资料

地板 大 中 小 发表于 2008-4-9 23:38  只看该作者
看不懂。。。
光大湘大网羽!
草根网羽的徒弟

骑士

Rank: 6Rank: 6

帖子
200 
青韶币
251  
魅力
0  
威望
0  
注册时间
2007-12-9 
  • 个人空间
  • 发短消息
  • 加为好友
  • 当前离线

TOP

UID
20435 
帖子
200 
精华
0 
积分
570 
青韶币
251  
魅力
0  
威望
0  
阅读权限
20 
在线时间
17 小时 
注册时间
2007-12-9 
最后登录
2008-5-29 

查看详细资料

地下室 大 中 小 发表于 2008-4-11 10:15  只看该作者
更常用的办法是直接将SessionFactory注入DAO对象里
<bean id="TestDao" class="somepackage.TestDaoImpl">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>

Dao里定义
private org.Hibernate.SessionFactory sessionFactory;
以及相应的get、set方法。
更方便的解决方法是让DaoImpl直接extends org.springframework.orm.hibernate3.support.HibernateDaoSupport。
这样的话,在自己的Dao实现里可以直接调用getHibernateTemplate()方法取得HibernateTemplate模板对象~~使用这个模板进行数据库操作,可以大量减少代码量~~

闲看庭前花开花落

      
           漫随天外云卷云舒
      
大饼先生

版主

Rank: 16Rank: 16Rank: 16Rank: 16

重返江湖

帖子
2519 
青韶币
4703  
魅力
18  
威望
9  
注册时间
2003-10-7 

元老奖章

  • 个人空间
  • 发短消息
  • 加为好友
  • 当前离线

TOP

QQ
UID
1166 
帖子
2519 
精华
14 
积分
12621 
青韶币
4703  
魅力
18  
威望
9  
阅读权限
100 
性别
男 
在线时间
743 小时 
注册时间
2003-10-7 
最后登录
2008-10-14 

查看详细资料

地底下 大 中 小 发表于 2008-4-11 10:19  只看该作者
再次感叹下
Spring实在太强大了……
不论是DI还是AOP,还是对各种MVC、ORM框架的支持,都让人觉得惊艳!!!
大神级的人设计出来的框架啊~~

闲看庭前花开花落

      
           漫随天外云卷云舒
      
大饼先生

版主

Rank: 16Rank: 16Rank: 16Rank: 16

重返江湖

帖子
2519 
青韶币
4703  
魅力
18  
威望
9  
注册时间
2003-10-7 

元老奖章

  • 个人空间
  • 发短消息
  • 加为好友
  • 当前离线

TOP

QQ
UID
1166 
帖子
2519 
精华
14 
积分
12621 
青韶币
4703  
魅力
18  
威望
9  
阅读权限
100 
性别
男 
在线时间
743 小时 
注册时间
2003-10-7 
最后登录
2008-10-14 

查看详细资料

7楼 大 中 小 发表于 2008-4-15 10:58  只看该作者

整合webwork+spring+hibernate

首先配置web.xml以整合webwork和spring:
<!--载入spring配置文件-->
<context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
                /WEB-INF/classes/example/example1-context.xml
        </param-value>
</context-param>

<!--加入webwork的filter及filter-mapping(2.2以上版本的webwork使用filter而不是servlet处理请求)-->
<filter>
        <filter-name>webwork</filter-name>
        <filter-class>om.opensymphony.webwork.dispatcher.FilterDispatcher</filter-class>
</filter>
<filter-mapping>
        <filter>webwork</filter>
        <url-pattern><!--some url pattern--></url-pattern>
</filter-mapping>

<!--加入spring的监听器,以监听请求,自动注入service-->
<listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

这样配置好以后,在webwork的action里添加services的getter、setter,对应的在spring的配置文件里完成service的配置,请求action时将会自动注入services

接下来是配置spring的配置文件以整合hibernate...关于这个已经在上面给出。

闲看庭前花开花落

      
           漫随天外云卷云舒
      
大饼先生

版主

Rank: 16Rank: 16Rank: 16Rank: 16

重返江湖

帖子
2519 
青韶币
4703  
魅力
18  
威望
9  
注册时间
2003-10-7 

元老奖章

  • 个人空间
  • 发短消息
  • 加为好友
  • 当前离线

TOP

QQ
UID
1166 
帖子
2519 
精华
14 
积分
12621 
青韶币
4703  
魅力
18  
威望
9  
阅读权限
100 
性别
男 
在线时间
743 小时 
注册时间
2003-10-7 
最后登录
2008-10-14 

查看详细资料

8楼 大 中 小 发表于 2008-4-15 11:02  只看该作者

一个完整的spring配置文件例子

数据库连接及hibernate的某些属些在mysqlConfig.properties文件中给出。
关于DAO的注入有两个:userManagerDao和userManagerDaoHibernateTemplate。可任选其一。
使用spring的interceptor进行事务管理。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC
        "-//SPRING//DTD BEAN//EN"
        "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
        <bean id="propertiesConfig"
                class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
                <property name="location">
                        <value>classpath:/mysqlConfig.properties</value>
                </property>
        </bean>

        <bean id="dataSource"
                class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"
                autowire="byName">
                <property name="driverClassName">
                        <value>${jdbc.driver}</value>
                </property>
                <property name="url">
                        <value>${jdbc.url}</value>
                </property>
                <property name="username">
                        <value>${jdbc.username}</value>
                </property>
                <property name="password">
                        <value>${jdbc.password}</value>
                </property>
        </bean>
       
        <bean id="sessionFactory"
                class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
                <property name="dataSource">
                        <ref bean="dataSource" />
                </property>
                <property name="mappingResources">
                        <list>
                                <value>/example/pojo/MobileUser.hbm.xml</value>
                        </list>
                </property>
                <property name="hibernateProperties">
                        <props>
                                <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                                <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
                               
                        </props>
                </property>
        </bean>
       
       
        <!-- 注入DAO -->
        <bean id="userManagerDaoHibernateTemplate"
                class="example.dao.UserManagerDaoHibernateTemplateImpl">
                <property name="sessionFactory">
                        <ref bean="sessionFactory"/>
                </property>
        </bean>
       
        <bean id="userManagerDao" class="example.dao.UserManagerDaoImpl">
                <property name="sessionFactory">
                        <ref bean="sessionFactory" />
                </property>
        </bean>
       
               
        <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
                <property name="sessionFactory" ref="sessionFactory"/>
        </bean>
        <!--bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean"/>
           <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
     <property name="userTransaction">
                   <ref local="jotm"/>
          </property>
   </bean-->
   
         <bean id="baseTransactionProxy" abstract="true"
      class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
                <property name="transactionManager">
                          <ref bean="transactionManager"/>
        </property>
                <property name="transactionAttributes">
                        <props>
                                <prop key="create*">PROPAGATION_REQUIRED,-Exception</prop>
                                <prop key="update*">PROPAGATION_REQUIRED,-Exception</prop>
                                <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
                                <prop key="retrieve*">PROPAGATION_REQUIRED,readOnly</prop>
                                <prop key="*">PROPAGATION_REQUIRED,-Exception</prop>
                        </props>
                </property>
    </bean>
   
    <bean id="userManagerService" parent="baseTransactionProxy">
                <property name="target">
                        <bean class="example.services.UserManagerServiceImpl">
                                <property name="userManagerDao">
                                        <ref bean="userManagerDao" />
                                </property>
                        </bean>
                </property>
        </bean>
</beans>

闲看庭前花开花落

      
           漫随天外云卷云舒
      
大饼先生

版主

Rank: 16Rank: 16Rank: 16Rank: 16

重返江湖

帖子
2519 
青韶币
4703  
魅力
18  
威望
9  
注册时间
2003-10-7 

元老奖章

  • 个人空间
  • 发短消息
  • 加为好友
  • 当前离线

TOP

QQ
UID
1166 
帖子
2519 
精华
14 
积分
12621 
青韶币
4703  
魅力
18  
威望
9  
阅读权限
100 
性别
男 
在线时间
743 小时 
注册时间
2003-10-7 
最后登录
2008-10-14 

查看详细资料

9楼 大 中 小 发表于 2008-4-16 17:22  只看该作者
确实!
一新人问我:学长为什么发帖都这么个性和水平?
我沉思到:我只不过是把别人喝咖啡的时间用在灌水上了
左耳出灵

SCID:iLOVEloye

风云使者

Rank: 10Rank: 10Rank: 10

HONG一般的男子

帖子
1219 
青韶币
1373  
魅力
16  
威望
9  
注册时间
2006-8-12 

迎新贡献奖章 青韶警卫奖

  • 个人空间
  • 发短消息
  • 加为好友
  • 当前离线

TOP

QQ
UID
15117 
帖子
1219 
精华
5 
积分
7329 
青韶币
1373  
魅力
16  
威望
9  
阅读权限
50 
性别
男 
在线时间
483 小时 
注册时间
2006-8-12 
最后登录
2008-10-13 

查看详细资料

10楼 大 中 小 发表于 2008-4-17 11:33  只看该作者
Hibernate悲观锁,使用LockMode.UPGRADE,原理:锁定表的记录,直到一个事务完成以后才释放锁。
                乐观锁:使用<version>或<timestamp>或定义<class>的optimistic-lock="all",原理:更新数据库时在where子句中附上version或者timestamp或者所有属性值与之前查询出的结果相同,才更新数据库,否则抛出一个StaleObjectStateException


关于One-to-Many关系级联存储:
One端:OneObj.hbm.xml里配置
<set
name=”propertyName”
inverse=”true”
cascade=”all”
>
        <key column=”foreignKeyColumnName” />
        <one-to-many class=”ManyObj”>
</set>
inverse:当取值为“true”,表示在双向关联中,这一端为镜像端。(若不指定inverse为true,在级联删除操作时会出现异常。)
注意cascade缺省值为none,即保存、更新、删除当前对象是忽略其它对象。可选值为以下:

Many端:ManyObj.hbm.xml里配置:
        <many-to-one
name=”propertyName”
column=”FOREIGN_KEY_COLUMN”
class=”OneObj”
/>
注意在JAVA程序里也要建立双向关联关系


在<property>的属性里加上access=”field”这条属性,则可以自动访问pojo里对应的属性,而不用在pojo里加上属性的getter和setter。
        <property name=”someProperty” column=”db_property”/>


关于ID的generator:
当ID的主键和business直接相关时,适合将generator设为assgined,否则设为native。

<component>元素可以对应于一个无identity的POJO对象,例如User对象里有一个Address对象,Address包含city, street, zipcode之类的,则可以在<component name=”homeAddress” class=”full.packagename.Address”>里加入<property name=”city” />等等。

取得LastInsertId,可以在调用session.save(someObj)之后,直接调用someObj的getId()方法来取得Last Insert Id。
在执行session.save(someObj)后,someObj被持久化,并且保存在session的缓存中。所以可以使用getId()来取得ID。由于这个对象仍在session缓存中,当session未关闭时,调用session.load(SomeObj.class, someObj.getId())来重新取得这个对象时,不会执行任何SELECT查询(若这个对象不在Session的缓存中,调用load()时则会执行一条SELECT)。

关于Session缓存,和load()方法,在运行session.load()方法时Hibernate不执行任何select语句,仅仅返回Pojo对象的代理类的实例,它的OID即load()方法的第二个参数指定的。当应用程序调用Pojo对象的getId()时,仍然不会执行select查询,只有当访问Pojo的其它属性的时候,Hibernate才会初始化这个代理类的实例,从数据库中加载数据,执行Select查询。注意:如果在访问Pojo其它属性的时候Session已经关闭了,则会出现以下异常:
org.hibernate.LazyInitializationException: could not initialize proxy - the owning Session was closed。但是,如果在Pojo的Pojo.hbm.xml映射文件的class属性里定义了lazy=”false”,则会正常进行。(更多关于Hibernate延迟加载的文档参考目录下另一篇文章。)

闲看庭前花开花落

      
           漫随天外云卷云舒
      
大饼先生

版主

Rank: 16Rank: 16Rank: 16Rank: 16

重返江湖

帖子
2519 
青韶币
4703  
魅力
18  
威望
9  
注册时间
2003-10-7 

元老奖章

  • 个人空间
  • 发短消息
  • 加为好友
  • 当前离线

TOP

QQ
UID
1166 
帖子
2519 
精华
14 
积分
12621 
青韶币
4703  
魅力
18  
威望
9  
阅读权限
100 
性别
男 
在线时间
743 小时 
注册时间
2003-10-7 
最后登录
2008-10-14 

查看详细资料

11楼 大 中 小 发表于 2008-4-17 11:34  只看该作者

[转载]关于Hibernate延迟加载

LazyInitializer异常
其实这个异常写的非常之清楚,就是会话关闭,无法对Hibernate实体进行操作。造成这样的情况有很多,什么书写错误啊,逻辑错误啊。

但就此说一下关于lazy机制:

延迟初始化错误是运用Hibernate开发项目时最常见的错误。如果对一个类或者集合配置了延迟检索策略,那么必须当代理类实例或代理集合处于持久化状态(即处于Session范围内)时,才能初始化它。如果在游离状态时才初始化它,就会产生延迟初始化错误。

下面把Customer.hbm.xml文件的<class>元素的lazy属性设为true,表示使用延迟检索策略:

<class name="mypack.Customer" table="CUSTOMERS" lazy="true">

当执行Session的load()方法时,Hibernate不会立即执行查询CUSTOMERS表的select语句,仅仅返回Customer类的代理类的实例,这个代理类具由以下特征:

(1) 由Hibernate在运行时动态生成,它扩展了Customer类,因此它继承了Customer类的所有属性和方法,但它的实现对于应用程序是透明的。
(2) 当Hibernate创建Customer代理类实例时,仅仅初始化了它的OID属性,其他属性都为null,因此这个代理类实例占用的内存很少。
(3)当应用程序第一次访问Customer代理类实例时(例如调用customer.getXXX()或customer.setXXX()方法), Hibernate会初始化代理类实例,在初始化过程中执行select语句,真正从数据库中加载Customer对象的所有数据。但有个例外,那就是当应用程序访问Customer代理类实例的getId()方法时,Hibernate不会初始化代理类实例,因为在创建代理类实例时OID就存在了,不必到数据库中去查询。

提示:Hibernate采用CGLIB工具来生成持久化类的代理类。CGLIB是一个功能强大的Java字节码生成工具,它能够在程序运行时动态生成扩展 Java类或者实现Java接口的代理类。关于CGLIB的更多知识,请参考:http://cglib.sourceforge.net/。

以下代码先通过Session的load()方法加载Customer对象,然后访问它的name属性:

tx = session.beginTransaction();
Customer customer=(Customer)session.load(Customer.class,new Long(1));
customer.getName();
tx.commit();

在运行session.load()方法时Hibernate不执行任何select语句,仅仅返回Customer类的代理类的实例,它的OID为1,这是由load()方法的第二个参数指定的。当应用程序调用customer.getName()方法时,Hibernate会初始化Customer代理类实例,从数据库中加载Customer对象的数据,执行以下select语句:

select * from CUSTOMERS where ID=1;
select * from ORDERS where CUSTOMER_ID=1;

当<class>元素的lazy属性为true,会影响Session的load()方法的各种运行时行为,下面举例说明。

1.如果加载的Customer对象在数据库中不存在,Session的load()方法不会抛出异常,只有当运行customer.getName()方法时才会抛出以下异常:

ERROR LazyInitializer:63 - Exception initializing proxy
net.sf.hibernate.ObjectNotFoundException: No row with the given identifier exists: 1, of class:
mypack.Customer

2.如果在整个Session范围内,应用程序没有访问过Customer对象,那么Customer代理类的实例一直不会被初始化,Hibernate不会执行任何select语句。以下代码试图在关闭Session后访问Customer游离对象:

tx = session.beginTransaction();
Customer customer=(Customer)session.load(Customer.class,new Long(1));
tx.commit();
session.close();
customer.getName();

由于引用变量customer引用的Customer代理类的实例在Session范围内始终没有被初始化,因此在执行customer.getName()方法时,Hibernate会抛出以下异常:

ERROR LazyInitializer:63 - Exception initializing proxy
net.sf.hibernate.HibernateException: Could not initialize proxy - the owning Session was closed

由此可见,Customer代理类的实例只有在当前Session范围内才能被初始化。

3.net.sf.hibernate.Hibernate类的initialize()静态方法用于在Session范围内显式初始化代理类实例,isInitialized()方法用于判断代理类实例是否已经被初始化。例如:

tx = session.beginTransaction();
Customer customer=(Customer)session.load(Customer.class,new Long(1));
if(!Hibernate.isInitialized(customer))
Hibernate.initialize(customer);
tx.commit();
session.close();
customer.getName();

以上代码在Session范围内通过Hibernate类的initialize()方法显式初始化了Customer代理类实例,因此当Session关闭后,可以正常访问Customer游离对象。

4.当应用程序访问代理类实例的getId()方法时,不会触发Hibernate初始化代理类实例的行为,例如:

tx = session.beginTransaction();
Customer customer=(Customer)session.load(Customer.class,new Long(1));
customer.getId();
tx.commit();
session.close();
customer.getName();

当应用程序访问customer.getId()方法时,该方法直接返回Customer代理类实例的OID值,无需查询数据库。由于引用变量 customer始终引用的是没有被初始化的Customer代理类实例,因此当Session关闭后再执行customer.getName()方法, Hibernate会抛出以下异常:

ERROR LazyInitializer:63 - Exception initializing proxy
net.sf.hibernate.HibernateException: Could not initialize proxy - the owning Session was closed


解决方法:

由于hibernate采用了lazy=true,这样当你用hibernate查询时,返回实际为利用cglib增强的代理类,但其并没有实际填充;当你在前端,利用它来取值(getXXX)时,这时Hibernate才会到数据库执行查询,并填充对象,但此时如果和这个代理类相关的session已关闭掉,就会产生种错误.
在做一对多时,有时会出现"could not initialize proxy - clothe owning Session was sed,这个好像是hibernate的缓存问题.问题解决:需要在<many-to-one>里设置lazy="false". 但有可能会引发另一个异常叫

failed to lazily initialize a collection of role: XXXXXXXX, no session or session was closed

此异常解决方案请察看本人博客(http://hi.baidu.com/kekemao1)的Hibernate异常中的《failed to lazily initialize a collection of role异常》

?
解决方法:在web.xml中加入
<filter>
    <filter-name>hibernateFilter</filter-name>
    <filter-class>
     org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
    </filter-class>
</filter
<filter-mapping>
    <filter-name>hibernateFilter</filter-name>
    <url-pattern>*.do</url-pattern>
</filter-mapping>
就可以了;

参考了:
Hibernate与延迟加载:

Hibernate对象关系映射提供延迟的与非延迟的对象初始化。非延迟加载在读取一个对象的时候会将与这个对象所有相关的其他对象一起读取出来。这有时会导致成百的(如果不是成千的话)select语句在读取对象的时候执行。这个问题有时出现在使用双向关系的时候,经常会导致整个数据库都在初始化的阶段被读出来了。当然,你可以不厌其烦地检查每一个对象与其他对象的关系,并把那些最昂贵的删除,但是到最后,我们可能会因此失去了本想在ORM工具中获得的便利。


一个明显的解决方法是使用Hibernate提供的延迟加载机制。这种初始化策略只在一个对象调用它的一对多或多对多关系时才将关系对象读取出来。这个过程对开发者来说是透明的,而且只进行了很少的数据库操作请求,因此会得到比较明显的性能提升。这项技术的一个缺陷是延迟加载技术要求一个Hibernate会话要在对象使用的时候一直开着。这会成为通过使用DAO模式将持久层抽象出来时的一个主要问题。为了将持久化机制完全地抽象出来,所有的数据库逻辑,包括打开或关闭会话,都不能在应用层出现。最常见的是,一些实现了简单接口的DAO实现类将数据库逻辑完全封装起来了。一种快速但是笨拙的解决方法是放弃DAO模式,将数据库连接逻辑加到应用层中来。这可能对一些小的应用程序有效,但是在大的系统中,这是一个严重的设计缺陷,妨碍了系统的可扩展性。

在Web层进行延迟加载

幸运的是,Spring框架为Hibernate延迟加载与DAO模式的整合提供了一种方便的解决方法。对那些不熟悉Spring与Hibernate集成使用的人,我不会在这里讨论过多的细节,但是我建议你去了解Hibernate与Spring集成的数据访问。以一个Web应用为例,Spring提供了OpenSessionInViewFilter和OpenSessionInViewInterceptor。我们可以随意选择一个类来实现相同的功能。两种方法唯一的不同就在于interceptor在Spring容器中运行并被配置在web应用的上下文中,而Filter在Spring之前运行并被配置在web.xml中。不管用哪个,他们都在请求将当前会话与当前(数据库)线程绑定时打开Hibernate会话。一旦已绑定到线程,这个打开了的Hibernate会话可以在DAO实现类中透明地使用。这个会话会为延迟加载数据库中值对象的视图保持打开状态。一旦这个逻辑视图完成了,Hibernate会话会在Filter的doFilter方法或者Interceptor的postHandle方法中被关闭。下面是每个组件的配置示例:



Interceptor的配置:


<beans>
        <bean id="urlMapping"
        class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
                <property name="interceptors">
                        <list>
                                <ref bean="openSessionInViewInterceptor"/>
                        </list>
                </property>
                <property name="mappings">

        </bean>

        <bean name="openSessionInViewInterceptor"
        class="org.springframework.orm.hibernate.support.OpenSessionInViewInterceptor">
                <property name="sessionFactory"><ref bean="sessionFactory"/></property>
        </bean>
</beans>

Filter的配置


<web-app>

        <filter>
                <filter-name>hibernateFilter</filter-name>
                        <filter-class>
                                org.springframework.orm.hibernate.support.OpenSessionInViewFilter
                        </filter-class>
        </filter>

        <filter-mapping>
                <filter-name>hibernateFilter</filter-name>
                <url-pattern>*. spring </url-pattern>
        </filter-mapping>

</web-app>


实现Hibernate的Dao接口来使用打开的会话是很容易的。事实上,如果你已经使用了Spring框架来实现你的Hibernate Dao,很可能你不需要改变任何东西。方便的HibernateTemplate公用组件使访问数据库变成小菜一碟,而DAO接口只有通过这个组件才可以访问到数据库。下面是一个示例的DAO:


public class HibernateProductDAO extends HibernateDaoSupport implements ProductDAO {

        public Product getProduct(Integer productId) {
                return (Product) getHibernateTemplate().load(Product.class, productId);
        }

        public Integer saveProduct(Product product) {
                return (Integer) getHibernateTemplate().save(product);
        }

        public void updateProduct(Product product) {
                getHibernateTemplate().update(product);
        }
}


在业务逻辑层中使用延迟加载

即使在视图外面,Spring框架也通过使用AOP 拦截器 HibernateInterceptor来使得延迟加载变得很容易实现。这个Hibernate 拦截器透明地将调用配置在Spring应用程序上下文中的业务对象中方法的请求拦截下来,在调用方法之前打开一个Hibernate会话,然后在方法执行完之后将会话关闭。让我们来看一个简单的例子,假设我们有一个接口BussinessObject:


public     interface    BusinessObject     {
        public     void    doSomethingThatInvolvesDaos();
}

类BusinessObjectImpl实现了BusinessObject接口:

public     class    BusinessObjectImpl    implements    BusinessObject     {
        public     void    doSomethingThatInvolvesDaos()     {
                //    lots of logic that calls
                //    DAO classes Which access
                //    data objects lazily  
        }  
}  



通过在Spring应用程序上下文中的一些配置,我们可以让将调用BusinessObject的方法拦截下来,再令它的方法支持延迟加载。看看下面的一个程序片段:



<beans>
        <bean id="hibernateInterceptor"
                class="org.springframework.orm.hibernate.HibernateInterceptor">
                <property name="sessionFactory">
                        <ref bean="sessionFactory" />
                </property>
        </bean>
        <bean id="businessObjectTarget"
                class="com.acompany.BusinessObjectImpl">
                <property name="someDAO">
                        <ref bean="someDAO" />
                </property>
        </bean>
        <bean id="businessObject"
                class="org.springframework.aop.framework.ProxyFactoryBean">
                <property name="target">
                        <ref bean="businessObjectTarget" />
                </property>
                <property name="proxyInterfaces">
                        <value>com.acompany.BusinessObject</value>
                </property>
                <property name="interceptorNames">
                        <list>
                                <value>hibernateInterceptor</value>
                        </list>
                </property>
        </bean>
</beans>

当businessObject被调用的时候,HibernateInterceptor打开一个Hibernate会话,并将调用请求传递给BusinessObjectImpl对象。当BusinessObjectImpl执行完成后,HibernateInterceptor透明地关闭了会话。应用层的代码不用了解任何持久层逻辑,还是实现了延迟加载。


在单元测试中测试延迟加载

最后,我们需要用J-Unit来测试我们的延迟加载程序。我们可以轻易地通过重写TestCase类中的setUp和tearDown方法来实现这个要求。我比较喜欢用这个方便的抽象类作为我所有测试类的基类。


public abstract class MyLazyTestCase extends TestCase {

        private SessionFactory sessionFactory;
        private Session session;

        public void setUp() throws Exception {
                super.setUp();
                SessionFactory sessionFactory = (SessionFactory) getBean("sessionFactory");
                session = SessionFactoryUtils.getSession(sessionFactory, true);
                Session s = sessionFactory.openSession();
                TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(s));

        }

        protected Object getBean(String beanName) {
                // Code to get objects from Spring application context
        }

        public void tearDown() throws Exception {
                super.tearDown();
                SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
                Session s = holder.getSession();
                s.flush();
                TransactionSynchronizationManager.unbindResource(sessionFactory);
                SessionFactoryUtils.closeSessionIfNecessary(s, sessionFactory);
        }
}

闲看庭前花开花落

      
           漫随天外云卷云舒
      
大饼先生

版主

Rank: 16Rank: 16Rank: 16Rank: 16

重返江湖

帖子
2519 
青韶币
4703  
魅力
18  
威望
9  
注册时间
2003-10-7 

元老奖章

  • 个人空间
  • 发短消息
  • 加为好友
  • 当前离线

TOP

QQ
UID
1166 
帖子
2519 
精华
14 
积分
12621 
青韶币
4703  
魅力
18  
威望
9  
阅读权限
100 
性别
男 
在线时间
743 小时 
注册时间
2003-10-7 
最后登录
2008-10-14 

查看详细资料

12楼 大 中 小 发表于 2008-4-22 10:44  只看该作者

在HibernateTemplate里使用分页。

public List getListForPage(final String hql, final int offset, final int length) {

                List list = getHibernateTemplate().executeFind(new HibernateCallback() {
                        public Object doInHibernate(Session session) throws HibernateException, SQLException {
                                Query query = session.createQuery(hql);
                                query.setFirstResult(offset);
                                query.setMaxResults(length);
                                List list = query.list();
                                return list;
                        }
                });
                return list;
        }

闲看庭前花开花落

      
           漫随天外云卷云舒
      
大饼先生

版主

Rank: 16Rank: 16Rank: 16Rank: 16

重返江湖

帖子
2519 
青韶币
4703  
魅力
18  
威望
9  
注册时间
2003-10-7 

元老奖章

  • 个人空间
  • 发短消息
  • 加为好友
  • 当前离线

TOP

QQ
UID
1166 
帖子
2519 
精华
14 
积分
12621 
青韶币
4703  
魅力
18  
威望
9  
阅读权限
100 
性别
男 
在线时间
743 小时 
注册时间
2003-10-7 
最后登录
2008-10-14 

查看详细资料

13楼 大 中 小 发表于 2008-4-29 11:28  只看该作者
ejb3.0
网络幽灵

风云使者

Rank: 10Rank: 10Rank: 10

帖子
1289 
青韶币
1949  
魅力
0  
威望
0  
注册时间
2003-7-16 

元老奖章

  • 个人空间
  • 发短消息
  • 加为好友
  • 当前离线

TOP

QQ
UID
492 
帖子
1289 
精华
0 
积分
7368 
青韶币
1949  
魅力
0  
威望
0  
阅读权限
50 
性别
男 
在线时间
479 小时 
注册时间
2003-7-16 
最后登录
2008-10-13 

查看详细资料

14楼 大 中 小 发表于 2008-4-30 11:14  只看该作者
Java EE without ejb..哈哈
EJB很少用到。不建议学。。需要用的时候才会学吧,学起来很快的

闲看庭前花开花落

      
           漫随天外云卷云舒
      
大饼先生

版主

Rank: 16Rank: 16Rank: 16Rank: 16

重返江湖

帖子
2519 
青韶币
4703  
魅力
18  
威望
9  
注册时间
2003-10-7 

元老奖章

  • 个人空间
  • 发短消息
  • 加为好友
  • 当前离线

TOP

QQ
UID
1166 
帖子
2519 
精华
14 
积分
12621 
青韶币
4703  
魅力
18  
威望
9  
阅读权限
100 
性别
男 
在线时间
743 小时 
注册时间
2003-10-7 
最后登录
2008-10-14 

查看详细资料

15楼 大 中 小 发表于 2008-4-30 15:16  只看该作者
ejb3很不错的,和以往版本比
网络幽灵

风云使者

Rank: 10Rank: 10Rank: 10

帖子
1289 
青韶币
1949  
魅力
0  
威望
0  
注册时间
2003-7-16 

元老奖章

  • 个人空间
  • 发短消息
  • 加为好友
  • 当前离线

TOP

QQ
UID
492 
帖子
1289 
精华
0 
积分
7368 
青韶币
1949  
魅力
0  
威望
0  
阅读权限
50 
性别
男 
在线时间
479 小时 
注册时间
2003-7-16 
最后登录
2008-10-13 

查看详细资料

16楼 大 中 小 发表于 2008-5-15 21:24  只看该作者
嘿嘿....原来都在研究这东西啊
太好胜ぉ使我对泪哭泣,太倔强あ让我朝血冷 笑
    哭泣的孩子说:“我很坚强,因为任性的哭。”我就是那个哭泣的孩子,肩上 停着我鬼魅的小妖精,它的名字叫放肆
雪舞漫天飞

版主

Rank: 16Rank: 16Rank: 16Rank: 16

狩猎Ж妖精

帖子
4668 
青韶币
1676  
魅力
278  
威望
4  
注册时间
2003-11-4 

元老奖章

  • 个人空间
  • 发短消息
  • 加为好友
  • 当前离线

TOP

QQ
UID
2328 
帖子
4668 
精华
3 
积分
15627 
青韶币
1676  
魅力
278  
威望
4  
阅读权限
100 
性别
女 
来自
联建 
在线时间
625 小时 
注册时间
2003-11-4 
最后登录
2008-10-8 

查看详细资料

‹‹ 上一主题 | 下一主题 ››
发新话题
::专栏区::
  • 『 新生专区』
  • 『合作商家』
  • 湘潭大学招聘求职专版
::大学时代::
  • 『 校园生活 』
  • 『 学在湘大 』
  • 『 毕业情怀 』
::贴心交流::
  • 『 灌水厚道点 』
  • 『 贴图精美点 』
  • 『 百味人生 』
  • 『 个人秀场 』
::休闲娱乐::
  • 『 女生部落 』
  • 『 体坛风云 』
  • 网羽天地
  • 『 文学人文 』
  • 『 旋梯诗社』
  • 作品珍藏馆
  • 『 品味音乐 』
  • 『 车友乐园 』
  • 『 动漫一族 』