为domain object注入service对象.
原理:利用Hibernate3提供的PostLoadEventListener在loadHibernate实体类的时候触发PostLoadEvent事件,编写一个自定义的事件监听器,注入依赖的Spring Bean对象.此方法来自于ThoughtWorks
的 PerrynFowler
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中获得分页参数。