Java – spring, @ transactional and Hibernate lazy loading

I'm using spring hibernation All my hibernatedao directly use sessionfactory

I have application layer - > service layer - > Dao layer and all collections are loaded

Therefore, the problem is that at some point in the application layer (including GUI / swing), I use the service layer method (including @ transactional annotation) to load an entity. I want to use an inert attribute of this object, but I can visually see that the session has been closed

What is the best way to solve this trouble?

edit

I try to use methodinterceptor. My idea is to write an aroundadvice for all entities and use comments, such as:

// 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
}

Do you think this can work? The question is, how do I register this interceptor for all entities in the XML file? Is there an annotation method?

Solution

Hibernate recently introduced extracting configuration files (in addition to performance tuning), which is an ideal choice to solve this kind of problem It allows you to choose between different load and initialization strategies (at run time)

http://docs.jboss.org/hibernate/core/3.5/reference/en/html/performance.html#performance -fetching-profiles

Edit (added section on how to use interceptor settings to grab configuration files):

Before you start: check whether the captured profile is actually suitable for you I don't use them myself and see that they are currently limited to join extraction Before wasting time implementing and wiring interceptors, try manually setting up the grab profile and see that it can actually solve your problem

There are many ways to set up interceptors in spring (according to preferences), but the most direct way is to implement a methodinterceptor (see http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/aop-api.html#aop -api-advice-around). Let it have a setter for the profile you want to get and set it as a hibernation session factory:

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);
        }
    }
}

Finally, enable interceptors in the spring configuration This can be done in several ways, and you may already have an AOP setting that you can add to see http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/aop.html#aop -schema.

If you are new to AOP, it is recommended to try the "old" proxyfactory method first( http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/aop-api . HTML #aop - API - proxying - INTF) because it makes it easier to understand how it works Here are some sample XML to get you started:

<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>
The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>