我正在使用Spring + Hibernate。我所有的HibernateDAO都直接使用sessionFactory。
我有应用程序层->服务层-> DAO层,所有集合都被缓慢加载。
因此,问题在于,有时在应用程序层(包含GUI /
swing)中,我会使用服务层方法(包含@Transactional批注)加载实体,并且我想使用此对象的惰性属性,但忽略了会话已经关闭。
解决此问题的最佳方法是什么?
编辑
我尝试使用MethodInterceptor,我的想法是为我的所有实体编写一个AroundAdvice并使用注释,因此,例如:
// Custom annotation, say that session is required for this method
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SessionRequired {
// An AroundAdvice to intercept method calls
public class SessionInterceptor implements MethodInterceptor {
public Object invoke(MethodInvocation mi) throws Throwable {
bool sessionRequired=mi.getMethod().isAnnotationPresent(SessionRequired.class);
// Begin and commit session only if @SessionRequired
if(sessionRequired){
// begin transaction here
}
Object ret=mi.proceed();
if(sessionRequired){
// commit transaction here
}
return ret;
}
}
// An example of entity
@Entity
public class Customer implements Serializable {
@Id
Long id;
@OneToMany
List<Order> orders; // this is a lazy collection
@SessionRequired
public List<Order> getOrders(){
return orders;
}
}
// And finally in application layer...
public void foo(){
// Load customer by id, getCustomer is annotated with @Transactional
// this is a lazy load
Customer customer=customerService.getCustomer(1);
// Get orders, my interceptor open and close the session for me... i hope...
List<Order> orders=customer.getOrders();
// Finally use the orders
}
您认为这行得通吗?问题是,如何为我所有的实体注册此拦截器,而不在xml文件中进行注册?有办法用注解吗?
Hibernate最近推出了获取配置文件(除了性能调整之外)对于解决此类问题也是理想的选择。它允许您(在运行时)在不同的加载和初始化策略之间进行选择。
http://docs.jboss.org/hibernate/core/3.5/reference/en/html/performance.html#performance-
fetching-
profiles
编辑 (添加了有关如何使用拦截器设置获取配置文件的部分):
开始之前:检查获取配置文件实际上是否对您有用。我还没有亲自使用过它们,而是看到它们目前仅限于加入访存。在浪费时间实现和连接拦截器之前,请尝试手动设置获取配置文件,以查看它实际上可以解决您的问题。
有很多方法可以在Spring中设置拦截器(根据偏好),但是最直接的方法是实现MethodInterceptor(请参阅http://static.springsource.org/spring/docs/3.0.x/spring-
framework-reference / html / aop-api.html#aop-api-advice-
around)。让它具有所需的获取配置文件的设置器和Hibernate Session工厂的设置器:
public class FetchProfileInterceptor implements MethodInterceptor {
private SessionFactory sessionFactory;
private String fetchProfile;
... setters ...
public Object invoke(MethodInvocation invocation) throws Throwable {
Session s = sessionFactory.openSession(); // The transaction interceptor has already opened the session, so this returns it.
s.enableFetchProfile(fetchProfile);
try {
return invocation.proceed();
} finally {
s.disableFetchProfile(fetchProfile);
}
}
}
最后,在Spring配置中启用拦截器。这可以通过几种方式完成,您可能已经具有可以将其添加到的AOP设置。参见http://static.springsource.org/spring/docs/3.0.x/spring-
framework-reference/html/aop.html#aop-
schema。
如果您不熟悉AOP,建议您先尝试使用“旧的”
ProxyFactory方法(http://static.springsource.org/spring/docs/3.0.x/spring-
framework-reference/html/aop-api .html#aop-api-proxying-
intf),因为它更容易理解其工作原理。这是一些示例XML,可以帮助您入门:
<bean id="fetchProfileInterceptor" class="x.y.zFetchProfileInterceptor">
<property name="sessionFactory" ref="sessionFactory"/>
<property name="fetchProfile" ref="gui-profile"/>
</bean>
<bean id="businessService" class="x.y.x.BusinessServiceImpl">
<property name="dao" .../>
...
</bean>
<bean id="serviceForSwinGUI"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces" value="x.y.z.BusinessServiceInterface/>
<property name="target" ref="businessService"/>
<property name="interceptorNames">
<list>
<value>existingTransactionInterceptorBeanName</value>
<value>fetchProfileInterceptor</value>
</list>
</property>
</bean>
问题内容: 我正在使用Hibernate的延迟加载,并且即使在web.xml中定义了一个使用OpenSessionInViewFilter的过滤器后,也正在获取sessionFactory缺少的异常 我的servlet-context.xml具有以下会话和事务管理器定义: 我仍然收到以下异常: 我尝试定义一个sessionFactoryBeanName属性,但结果没有改变。我究竟做错了什么? 问题
问题内容: 这就是我想要做的。 创建具有与孩子的OneToOne关系的父母 父母必须使用延迟加载来获取孩子 如果父母被删除,孩子也被删除 如果孩子被移走,父母不应该受到影响 级联更新和删除必须转换为DDL 班级家长 班级儿童 我的第1、3、4 点 完全正常工作,而 第5点则 部分正常工作,仍然需要解决如何翻译更新部分indo DDL。 第2点 是这里的大问题,对于我目前的解决方案,父级不会延迟加载
我有一个模型如下的项目(伪代码): 现在,如果我尝试获取类似的内容(get(0)只是一个示例): 我get LazyInitializationException未能延迟初始化角色的集合:ClientVersion。客户端,没有会话或会话已关闭 若我更改ClientVersion和客户端之间的关系上的FetchType以使其工作正常,但我当然更希望延迟加载它。 我知道如果我有权访问hibernat
有很多关于“懒惰”的例子和文档。也许我没有明白,但为什么要用它呢?实例化bean成本
问题内容: 我以这样一种方式进行了JPA设置:如果我不使用延迟加载,则几乎将加载整个数据库。我也直接在模型上使用序列化,因此有时我需要初始化代理。 我只想在集合上使用延迟加载。急切地获取一些奇异实体的事实就很好了。但是,无论我如何尝试设置集合,我都永远不会得到代理集合,而我总是会得到完全加载的集合。 这是一些示例代码: 所以这里的问题是,当我检查调试器时,答复的persistantBag-list
我需要从Rest控件获取一个实体及其集合,但我对spring data JPA有一个非常奇怪的行为。 我对带有懒惰加载的实体有一种莫名其妙的关系。