Spring与Hibernate的整合与解耦
2006-03-21 10:19
351 查看
Hibernate与Spring整合后,就可以使用IoC及AOP的功能了,好处不在多言。另外一个好处,就是可以通过使用Spring的HibernateTemplate来简化数据库CRUD代码。然而,正是这个HibernateTemplate,存在着以下的缺点:
一是功能不全,不如Hibernate的储如createQuery()等方法方便、灵活与强大,使用颇受限制;
二是HibernateTemplate中的SessionFacotry封装得太死,且session常常会自动过早关闭,使用上颇多不便;
三是Spring1.2.7实际上只支持Hibernate3.0.5,HibernateTemplate无法使用Hibernate3.1以后新加的功能。
正是由于这三点,使我抵制住了使用HibernateTemplate的诱惑,在将Spring与Hibernate整合后,通过简单的配置,在Spring程序中自由地使用Hibernate3.1.2的功能。这样既可以实现强强联手,又可以在Hibernate新版本出来后,马上进行重新整合,无需等着新版的Spring出来。
在实现上,主要有三点。
一是在Spring的配置文件中,无需定义长长的hibernateTemplate,只需定义sessionFacotry就行了。
例如,设有一"组织DaoImpl",实现了"组织Dao"及"HibernateDao"两个接口。而"组织Service"通过将"组织DaoImpl"封装起来,对外提供相应的数据库功能服务。
public interface HibernateDao {
public void setSessionFactory(SessionFactory sessionFactory);
}
public interface 组织Dao {
public void 增加组织(组织 组织);
public void 删除组织(Long 组织编号);
public 组织 get组织By名称(String 组织名称);
......
}
public class 组织DaoImpl implements 组织Dao, HibernateDao {
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public 组织 get组织By名称(String 组织名称) {
......
}
}
public interface 组织Service {
public 组织 get组织By名称(String 组织名称);
......
}
(实际代码中,组织Service与组织DaoI的接口是一样的)
先在Spring的配置文件中定义"组织Service"与"组织Dao":
<bean id="组织Service"
class="com.sarkuya.service.组织ServiceImpl">
<property name="组织Dao">
<ref bean="组织Dao" />
</property>
</bean>
<bean id="组织Dao"
class="com.sarkuya.model.dao.hibernate.组织DaoImpl">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
这一步比较好理解。问题是如何将我们所需的sessionFactory传过来。Hibernate的sessionFactory不是一个可以用构造方法或setter方法就可以直接生成的类,而是需要进行一定的"运算"后才得出的类,典型的形式如:
sessionFactory = new Configuration().buildSessionFactory();
因此,简单地在Spring中如下配置行不通。
<bean id="sessionFactory"
class="org.hibernate.SessionFactory">
<property name="xxx">
<value>xxx</valu>
</property>
</bean>
所幸,Spring提供了一种可定义由工厂方法所产生的bean的方式。
<bean id="sessionFactory"
class="com.sarkuya.hibernate.util.HibernateUtil"
factory-method="getSessionFactory" />
这种方式,当我们需要得到sessionFacotry的bean时,Spring就会从com.sarkuya.hibernate.util.HibernateUtil的getSessionFactory()方法中获得。这种方式,我们最熟悉不过了:
public class HibernateUtil {
private static final SessionFactory sessionFactory;
static {
try {
sybaseSessionFactory = new Configuration()
.addClass(com.sarkuya.model.cfg.hibernate.组织.class)
.configure("/hibernate_hsql.cfg.xml")
.buildSessionFactory();
} catch (Throwable ex) {
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}
好了,以上步骤,我们已经成功地将sessionFactory注入组织Dao中,再注入组织Service中,根据测试先行原则,看看如何在TestCase中获取组织Service这个bean。
二,在代码中获取组织Service。
public class 组织ServiceTest extends TestCase {
private 组织Service 组织Service;
protected void setUp() throws Exception {
String[] configLocation = new String[] {
"/web/WEB-INF/training-service.xml",
"/web/WEB-INF/training-data.xml"
};
ApplicationContext ac = new FileSystemXmlApplicationContext(configLocation);
组织Service = (组织Service)ac.getBean("组织Service");
}
public void testGet组织By名称() {
System.out.println("get组织By名称");
组织 组织 = 组织Service.增加组织(new 组织("aaa"));
组织 = 组织Service.get组织By名称("aaa");
assertEquals("aaa", 组织.get名称());
组织 = 组织Service.get组织By名称("abc");
assertNull(组织);
}
}
三,组织DaoImpl的代码:
/*
* @param 组织名称
* @return 组织 或者 null
*/
public 组织 get组织By名称(String 组织名称) {
Session session = sessionFactory.getCurrentSession();
session.beginTransaction(); //Hiberante3.1以后的代码
组织 组织 = (组织)session.createQuery("from 组织 c where c.名称 = '" + 组织名称 + "'")
.uniqueResult();
session.getTransaction().commit();
return 组织;
}
由上可见,Hibernate的核心代码一点未变,从而在与Spring整合的基础上,实现了与Spring的解耦。
一是功能不全,不如Hibernate的储如createQuery()等方法方便、灵活与强大,使用颇受限制;
二是HibernateTemplate中的SessionFacotry封装得太死,且session常常会自动过早关闭,使用上颇多不便;
三是Spring1.2.7实际上只支持Hibernate3.0.5,HibernateTemplate无法使用Hibernate3.1以后新加的功能。
正是由于这三点,使我抵制住了使用HibernateTemplate的诱惑,在将Spring与Hibernate整合后,通过简单的配置,在Spring程序中自由地使用Hibernate3.1.2的功能。这样既可以实现强强联手,又可以在Hibernate新版本出来后,马上进行重新整合,无需等着新版的Spring出来。
在实现上,主要有三点。
一是在Spring的配置文件中,无需定义长长的hibernateTemplate,只需定义sessionFacotry就行了。
例如,设有一"组织DaoImpl",实现了"组织Dao"及"HibernateDao"两个接口。而"组织Service"通过将"组织DaoImpl"封装起来,对外提供相应的数据库功能服务。
public interface HibernateDao {
public void setSessionFactory(SessionFactory sessionFactory);
}
public interface 组织Dao {
public void 增加组织(组织 组织);
public void 删除组织(Long 组织编号);
public 组织 get组织By名称(String 组织名称);
......
}
public class 组织DaoImpl implements 组织Dao, HibernateDao {
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public 组织 get组织By名称(String 组织名称) {
......
}
}
public interface 组织Service {
public 组织 get组织By名称(String 组织名称);
......
}
(实际代码中,组织Service与组织DaoI的接口是一样的)
先在Spring的配置文件中定义"组织Service"与"组织Dao":
<bean id="组织Service"
class="com.sarkuya.service.组织ServiceImpl">
<property name="组织Dao">
<ref bean="组织Dao" />
</property>
</bean>
<bean id="组织Dao"
class="com.sarkuya.model.dao.hibernate.组织DaoImpl">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
这一步比较好理解。问题是如何将我们所需的sessionFactory传过来。Hibernate的sessionFactory不是一个可以用构造方法或setter方法就可以直接生成的类,而是需要进行一定的"运算"后才得出的类,典型的形式如:
sessionFactory = new Configuration().buildSessionFactory();
因此,简单地在Spring中如下配置行不通。
<bean id="sessionFactory"
class="org.hibernate.SessionFactory">
<property name="xxx">
<value>xxx</valu>
</property>
</bean>
所幸,Spring提供了一种可定义由工厂方法所产生的bean的方式。
<bean id="sessionFactory"
class="com.sarkuya.hibernate.util.HibernateUtil"
factory-method="getSessionFactory" />
这种方式,当我们需要得到sessionFacotry的bean时,Spring就会从com.sarkuya.hibernate.util.HibernateUtil的getSessionFactory()方法中获得。这种方式,我们最熟悉不过了:
public class HibernateUtil {
private static final SessionFactory sessionFactory;
static {
try {
sybaseSessionFactory = new Configuration()
.addClass(com.sarkuya.model.cfg.hibernate.组织.class)
.configure("/hibernate_hsql.cfg.xml")
.buildSessionFactory();
} catch (Throwable ex) {
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}
好了,以上步骤,我们已经成功地将sessionFactory注入组织Dao中,再注入组织Service中,根据测试先行原则,看看如何在TestCase中获取组织Service这个bean。
二,在代码中获取组织Service。
public class 组织ServiceTest extends TestCase {
private 组织Service 组织Service;
protected void setUp() throws Exception {
String[] configLocation = new String[] {
"/web/WEB-INF/training-service.xml",
"/web/WEB-INF/training-data.xml"
};
ApplicationContext ac = new FileSystemXmlApplicationContext(configLocation);
组织Service = (组织Service)ac.getBean("组织Service");
}
public void testGet组织By名称() {
System.out.println("get组织By名称");
组织 组织 = 组织Service.增加组织(new 组织("aaa"));
组织 = 组织Service.get组织By名称("aaa");
assertEquals("aaa", 组织.get名称());
组织 = 组织Service.get组织By名称("abc");
assertNull(组织);
}
}
三,组织DaoImpl的代码:
/*
* @param 组织名称
* @return 组织 或者 null
*/
public 组织 get组织By名称(String 组织名称) {
Session session = sessionFactory.getCurrentSession();
session.beginTransaction(); //Hiberante3.1以后的代码
组织 组织 = (组织)session.createQuery("from 组织 c where c.名称 = '" + 组织名称 + "'")
.uniqueResult();
session.getTransaction().commit();
return 组织;
}
由上可见,Hibernate的核心代码一点未变,从而在与Spring整合的基础上,实现了与Spring的解耦。
相关文章推荐
- Spring与Hibernate的整合与解耦
- Spring与Hibernate的整合与解耦
- Spring整合Hibernate笔记
- spring 学习之三(spring 与hibernate, struts2整合)
- spring和hibernate整合时异常(详解): getFlushMode is not valid without active transaction
- 【SSH】Spring与Hibernate整合
- spring和hibernate整合
- spring整合hibernate完整版
- Struts2+Hibernate+Spring 整合示例==》Spring整合Struts2简单示例==》Spring整合Hibernate简单示例
- Spring学习笔记六:Spring整合Hibernate
- 12月1日struts、spring、hibernate等框架的整合培训日记
- 基于Struts 2.x + Spring 2.x + Hibernate 3.x整合开发
- 使用struts、hibernate、spring进行框架整合流程详细说明(完整版)附:开发规范
- spring+springMVC+hibernate整合
- spring hibernate struts整合开发实例
- 4000 Hibernate--与Spring整合及增删改查
- struts整合spring整合hibernate
- Spring+Hibernate+Jersey整合
- SSH2(Struts2、Spring3与Hibernate3)的整合
- Spring声明式事务管理、Spring整合Hibernate