could not initialize proxy - the owning Session was closed
2010-12-04 22:33
537 查看
could not initialize proxy - the owning
Session was closed
关键字
:
异常引起的
其实这个异常写的非常之清楚,就是会话关闭,无法对
Hibernate
实体进行操作。造成这样的情况有很多,什么书写错误啊,逻辑错误啊
,
等等
.
不过
,
偶是因为
LAZY.
关于
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
属性:
Transaction 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>
Filter
的配置
实现
Hibernate
的
Dao
接口来使用打开的会话是很容易的。事实上,如果你已经使用了
Spring
框架来实现你的
Hibernate Dao,
很可能你不需要改变任何东西。方便的
HibernateTemplate
公用组件使访问数据库变成小菜一碟,而
DAO
接口只有通过这个组件才可以访问到数据库。下面是一个示例的
DAO
:
在业务逻辑层中使用延迟加载
即使在视图外面,
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
的方法拦截下来,再令它的方法支持延迟加载。看看下面的一个程序片段:
当
businessObject
被调用的时候,
HibernateInterceptor
打开一个
Hibernate
会话,并将调用请求传递给
BusinessObjectImpl
对象。当
BusinessObjectImpl
执行完成后,
HibernateInterceptor
透明地关闭了会话。应用层的代码不用了解任何持久层逻辑,还是实现了延迟加载。
在单元测试中测试延迟加载
最后,我们需要用
J-Unit
来测试我们的延迟加载程序。我们可以轻易地通过重写
TestCase
类中的
setUp
和
tearDown
方法来实现这个要求。我比较喜欢用这个方便的抽象类作为我所有测试类的基类。
http://lz726.javaeye.com/blog/116616
Session was closed
关键字
:
异常引起的
其实这个异常写的非常之清楚,就是会话关闭,无法对
Hibernate
实体进行操作。造成这样的情况有很多,什么书写错误啊,逻辑错误啊
,
等等
.
不过
,
偶是因为
LAZY.
关于
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
属性:
Transaction 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
方法来实现这个要求。我比较喜欢用这个方便的抽象类作为我所有测试类的基类。
import junit.framework.TestCase; import org.hibernate.Session; import org.hibernate.SessionFactory; 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); }
http://lz726.javaeye.com/blog/116616
相关文章推荐
- LazyInitializationException: could not initialize proxy-the owning Session was closed 异常
- spring.net Could not initialize proxy - the owning Session was closed 解决
- 异常:could not initialize proxy - the owning Session was closed
- Could not initialize proxy - the owning Session was closed
- Could not initialize proxy - the owning Session was closed ---Hibernate与延迟加载:
- Could not initialize proxy - the owning Session was closed
- Could not initialize proxy - the owning Session was closed
- LazyInitializationException:could not initialize proxy - the owning Session was closed
- 异常:could not initialize proxy - the owning Session was closed(转自kekemao1)
- Could not initialize proxy - the owning Session was closed
- 异常:could not initialize proxy - the owning Session was closed(转自kekemao1)
- 异常:could not initialize proxy - the owning Session was closed
- could not initialize proxy - the owning Session was closed
- SHH could not initialize proxy - the owning Session was closed 和延迟加载问题
- Could not initialize proxy - the owning Session was closed[转]
- Could not initialize proxy - the owning Session was closed
- 异常:could not initialize proxy - the owning Session was closed
- Spring+Hibernate出错: could not initialize proxy - the owning Session was closed
- 异常:could not initialize proxy - the owning Session was closed
- could not initialize proxy - the owning Session was closed