为domain object注入service对象.

原理:利用Hibernate3提供的PostLoadEventListener在loadHibernate实体类的时候触发PostLoadEvent事件,编写一个自定义的事件监听器,注入依赖的Spring Bean对象.此方法来自于ThoughtWorksPerrynFowler

import org.hibernate.event.PostLoadEvent;
import org.hibernate.event.PostLoadEventListener;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;

public class SpringHibernateInjector implements PostLoadEventListener, BeanFactoryAware{

    AutowireCapableBeanFactory beanFactory;
   
    
public void onPostLoad(PostLoadEvent event) {
        Object hibernateObject 
= event.getEntity();
        beanFactory.autowireBeanProperties(hibernateObject, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, 
false);   
    }


    
public void setBeanFactory(BeanFactory factory)  {
        beanFactory 
= (AutowireCapableBeanFactory) factory;
    }


}
<bean id="sessionFactory"
        class
="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        
<property name="dataSource">
            
<ref bean="dataSource" />
        
</property>
        
<property name="mappingResources">
            
<list>
                domains.hbm.xml here
            
</list>
        
</property>
        
<property name="hibernateProperties">
            
<props>
                
<prop key="hibernate.dialect">
                    org.hibernate.dialect.Oracle9Dialect
                
</prop>
                
<prop key="hibernate.query.substitutions">
                    true 1, false 0
                
</prop>
                
<prop key="hibernate.show_sql">false</prop>
            
</props>
        
</property>
       
<property name="eventListeners">
          
<map>
            
<entry key="post-load">
              
<!-- This hibernate interceptor allows us to use Spring to inject services
 into Hibernate managed domain objects 
-->   
              
<bean class="yourpackage.SpringHibernateInjector"/>
            
</entry>        
           
</map>
    
</property>
    
</bean>

domain object

 

package hibernate;

import java.util.List;

public class User {

    
private UserManager userManager;

    
public List getArticles() {
        
return userManager.getArticleByUser(this);
    }


    
public void save() {
        userManager.save(
this);
    }


    
public void delete() {
        userManager.delete(
this);
    }


    
public UserManager getUserManager() {
        
return userManager;
    }


    
public void setUserManager(UserManager userManager) {
        
this.userManager = userManager;
    }


}

package hibernate;

public class Article {
    
private User user;

    
public User getUser() {
        
return user;
    }


    
public void setUser(User user) {
        
this.user = user;
    }

    
}


service object
package hibernate;

import java.util.List;

public interface UserManager {
    
public void save(User user);
    
public void delete(User user);
    
public List getArticleByUser(User user);
}

在web层可以这样用
user.save();
user.delete();

最有用的地方是下面所描述的
user.getArticles(),实际调用的是userManager.getArticleByUser(User user);
只需要在Article端配置many-to-one到User,而不需要User端的one-to-many到Article,利用这个单向的关联来查询得到列表
1.是可以实现延迟加载的效果,并且不用open session in view
2.可以分页,分页这个方式也比较特别,由javaeye的Prentice网友提出来的(一种传递分页参数的方法),使用ServletFilter或Interceptor在WEB层截获分页的参数,
封装成一个对象,然后保存在threadlocal中,Service进行查询的时候可以按需从threadlocal中获得分页参数。