将Hibernate和iBatis两Orm框架整合,取长补短
程序员文章站
2022-07-12 18:34:06
...
由于Hibernate比较适合对数据进行增,删,改的操作,而iBatis适合进行数据 查询,批量操作,而且方便利用DB底层的功能,因此我尝试着持久层同时使用Hibernate和iBatis。
以下是我BaseDaoImpl的代码:
代码
package mypack.dao;
import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.orm.ibatis.SqlMapClientTemplate;
import com.ibatis.sqlmap.client.SqlMapClient;
public abstract class BaseDaoImpl implements BaseDAO
{
//iBatis的Template
private SqlMapClientTemplate sqlMapClientTemplate ;
//Hibernate的Template
private HibernateTemplate hibernateTemplate ;
//设置Hibernate
public final void setSessionFactory(SessionFactory sessionFactory) {
if(this.hibernateTemplate == null){
this.hibernateTemplate = new HibernateTemplate(sessionFactory);
}else{
this.hibernateTemplate.setSessionFactory(sessionFactory);
}
}
//设置ibatis
public final void setSqlMapClient(SqlMapClient sqlMapClient) {
if(this.sqlMapClientTemplate == null){
this.sqlMapClientTemplate = new SqlMapClientTemplate();
}
this.sqlMapClientTemplate.setSqlMapClient(sqlMapClient);
}
//获取Hibernate的模板
protected HibernateTemplate getHibernateTemplate(){
return hibernateTemplate
}
//获取iBatis的模板
protected SqlMapClientTemplate getSqlMapClientTemplate() {
return sqlMapClientTemplate;
}
//一些Hibernate 的通用方法,
//当然也可不必声明,子类通过hibernateTemplate来操作
protected void save(Object object) {
hibernateTemplate.save(object);
}
protected void saveOrUpdate(Object object) {
hibernateTemplate.saveOrUpdate(object);
}
protected void update(Object object) {
hibernateTemplate.update(object);
}
protected void delete(Object object){
hibernateTemplate.delete(object);
}
protected Object getObject(Class clazz, Serializable id){
return hibernateTemplate.get(clazz, id);
}
//子类通过iBatis 的sqlMapClientTemplate来操作
}
即以组合方式,将HibernateTemplate和sqlMapClientTemplate集成起来,完成类似SqlMapClientDaoSupport和HibernateDaoSupport的工作,由于Java无法多类继承,所以只得以组合方式来做。不过Spring的两个Support代码不多,自己做满好,满好--记得这是梁家辉在《棋王》上最爱说说的:)
在Spring中的主要配置是这样的:
首先配置Hibernate的SessionFactory:
代码
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<!-- 引用上述定义的数据源 -->
<property name="dataSource">
<ref local="dataSource"/>
</property>
<!-- 定义Hibernate映射文件(资源) -->
<property name="mappingDirectoryLocations">
<list>
<value>classpath:/mypack</value>
</list>
</property>
<!-- 定义Hibernate配置属性 -->
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.cglib.use_reflection_optimizer">${hibernate.cglib.use_reflection_optimizer}</prop>
</props>
</property>
<property name="useTransactionAwareDataSource" value="true"></property>
</bean>
再是iBatis的sqlMapClient
代码
<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="configLocation" value="sql-map-config.xml"/>
<property name="dataSource" ref="dataSource"/>
<property name="useTransactionAwareDataSource" value="true"></property>
</bean>
两者是useTransactionAwareDataSource属性都设置为ture,看Spring的Javadoc,说这可以在多Orm框架中保持事务的一致性,即通过DataSource关联,果真如此否?我还没有确定出来。
事务管理器,用Hibernate的
代码
<!-- 事务处理的AOP配置 -->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory"/>
</property>
</bean >
<bean id="txProxyTemplate" abstract="true"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<!-- 指定事务管理器 -->
<property name="transactionManager" >
<ref local="transactionManager"/>
</property>
<!-- 指定业务策略 -->
<property name="transactionAttributes">
<props>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="add*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
然后做两个Dao,一个是CustomerDao,这个走Hibernate,直接看其实现:
代码
package mypack.dao;
import mypack.Customer;
public class CustomerDaoImpl extends BaseDaoImpl implements CustomerDao {
public void update(Customer customer) {
super.save(customer);
}
}
再看OrderDao的实现,这个走iBatis(先分道扬镳,再殊途同归):
代码
package mypack.dao;
import java.sql.SQLException;
import org.springframework.orm.ibatis.SqlMapClientCallback;
public class OrderDaoImpl extends BaseDaoImpl implements OrderDao {
/**
* update ibatis
*/
public void updateOrderPrice(float rate)
{
getSqlMapClientTemplate().update("updateOrderPrice",null);
}
}
再在一个Service中同时用这两上Dao完成一个事务:
代码
package mypack.service;
import mypack.Customer;
import mypack.dao.CustomerDao;
import mypack.dao.OrderDao;
public class CustomerServiceImpl implements CustomerService {
private CustomerDao customerDao;
private OrderDao orderDao;
public void updateCustomerAndOrder(Customer customer, float rate) {
customerDao.update(customer);
orderDao.updateOrderPrice(rate);
}
public CustomerDao getCustomerDao() {
return customerDao;
}
public void setCustomerDao(CustomerDao customerDao) {
this.customerDao = customerDao;
}
public OrderDao getOrderDao() {
return orderDao;
}
public void setOrderDao(OrderDao orderDao) {
this.orderDao = orderDao;
}
}
插入一条Customer记录,再Update所有Order(纯粹研究,没有实际意义)
走:
代码
package test.service;
import org.apache.log4j.PropertyConfigurator;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SysInit
{
public static ApplicationContext factory = null;
private static String[] filepath = {"applicationContext_service.xml"};
public static void init()
{
PropertyConfigurator.configure("D:\\personalWork\\proGroup\\hiTestPro\\src\\log4j.properties");
if (factory == null)
{
try
{
factory = new ClassPathXmlApplicationContext(filepath);
} catch (Exception e)
{
e.printStackTrace();
}
}
try
{
} catch (Exception e)
{
e.printStackTrace();
}
}
public static Object getBean(String name)
{
if (factory == null)
{
init();
}
return factory.getBean(name);
}
public static void main(String[] args)
{
SysInit.init();
}
}
package test.service;
import junit.framework.TestCase;
import mypack.Customer;
import mypack.service.CustomerService;
public class CustomerServiceTest extends TestCase {
protected void setUp() throws Exception {
super.setUp();
SysInit.init();
}
protected void tearDown() throws Exception {
super.tearDown();
}
public void testupdateCustomerAndOrder()
{
CustomerService customerService = (CustomerService)SysInit.getBean("customerService");
Customer customer = new Customer();
customer.setId(3L);
customer.setFirstname("xiong");
customer.setLastname("hua");
customer.setSex('F');
customerService.updateCustomerAndOrder(customer, 2);
}
}
我测试了一下,如果iBatis的操作有问题,Customer也是没有办法插入了,所以基本上判断,这两个框架是可以做事务的。
各位看客以为如何?引玉中....
以下是我BaseDaoImpl的代码:
代码
package mypack.dao;
import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.orm.ibatis.SqlMapClientTemplate;
import com.ibatis.sqlmap.client.SqlMapClient;
public abstract class BaseDaoImpl implements BaseDAO
{
//iBatis的Template
private SqlMapClientTemplate sqlMapClientTemplate ;
//Hibernate的Template
private HibernateTemplate hibernateTemplate ;
//设置Hibernate
public final void setSessionFactory(SessionFactory sessionFactory) {
if(this.hibernateTemplate == null){
this.hibernateTemplate = new HibernateTemplate(sessionFactory);
}else{
this.hibernateTemplate.setSessionFactory(sessionFactory);
}
}
//设置ibatis
public final void setSqlMapClient(SqlMapClient sqlMapClient) {
if(this.sqlMapClientTemplate == null){
this.sqlMapClientTemplate = new SqlMapClientTemplate();
}
this.sqlMapClientTemplate.setSqlMapClient(sqlMapClient);
}
//获取Hibernate的模板
protected HibernateTemplate getHibernateTemplate(){
return hibernateTemplate
}
//获取iBatis的模板
protected SqlMapClientTemplate getSqlMapClientTemplate() {
return sqlMapClientTemplate;
}
//一些Hibernate 的通用方法,
//当然也可不必声明,子类通过hibernateTemplate来操作
protected void save(Object object) {
hibernateTemplate.save(object);
}
protected void saveOrUpdate(Object object) {
hibernateTemplate.saveOrUpdate(object);
}
protected void update(Object object) {
hibernateTemplate.update(object);
}
protected void delete(Object object){
hibernateTemplate.delete(object);
}
protected Object getObject(Class clazz, Serializable id){
return hibernateTemplate.get(clazz, id);
}
//子类通过iBatis 的sqlMapClientTemplate来操作
}
即以组合方式,将HibernateTemplate和sqlMapClientTemplate集成起来,完成类似SqlMapClientDaoSupport和HibernateDaoSupport的工作,由于Java无法多类继承,所以只得以组合方式来做。不过Spring的两个Support代码不多,自己做满好,满好--记得这是梁家辉在《棋王》上最爱说说的:)
在Spring中的主要配置是这样的:
首先配置Hibernate的SessionFactory:
代码
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<!-- 引用上述定义的数据源 -->
<property name="dataSource">
<ref local="dataSource"/>
</property>
<!-- 定义Hibernate映射文件(资源) -->
<property name="mappingDirectoryLocations">
<list>
<value>classpath:/mypack</value>
</list>
</property>
<!-- 定义Hibernate配置属性 -->
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.cglib.use_reflection_optimizer">${hibernate.cglib.use_reflection_optimizer}</prop>
</props>
</property>
<property name="useTransactionAwareDataSource" value="true"></property>
</bean>
再是iBatis的sqlMapClient
代码
<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="configLocation" value="sql-map-config.xml"/>
<property name="dataSource" ref="dataSource"/>
<property name="useTransactionAwareDataSource" value="true"></property>
</bean>
两者是useTransactionAwareDataSource属性都设置为ture,看Spring的Javadoc,说这可以在多Orm框架中保持事务的一致性,即通过DataSource关联,果真如此否?我还没有确定出来。
事务管理器,用Hibernate的
代码
<!-- 事务处理的AOP配置 -->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory"/>
</property>
</bean >
<bean id="txProxyTemplate" abstract="true"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<!-- 指定事务管理器 -->
<property name="transactionManager" >
<ref local="transactionManager"/>
</property>
<!-- 指定业务策略 -->
<property name="transactionAttributes">
<props>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="add*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
然后做两个Dao,一个是CustomerDao,这个走Hibernate,直接看其实现:
代码
package mypack.dao;
import mypack.Customer;
public class CustomerDaoImpl extends BaseDaoImpl implements CustomerDao {
public void update(Customer customer) {
super.save(customer);
}
}
再看OrderDao的实现,这个走iBatis(先分道扬镳,再殊途同归):
代码
package mypack.dao;
import java.sql.SQLException;
import org.springframework.orm.ibatis.SqlMapClientCallback;
public class OrderDaoImpl extends BaseDaoImpl implements OrderDao {
/**
* update ibatis
*/
public void updateOrderPrice(float rate)
{
getSqlMapClientTemplate().update("updateOrderPrice",null);
}
}
再在一个Service中同时用这两上Dao完成一个事务:
代码
package mypack.service;
import mypack.Customer;
import mypack.dao.CustomerDao;
import mypack.dao.OrderDao;
public class CustomerServiceImpl implements CustomerService {
private CustomerDao customerDao;
private OrderDao orderDao;
public void updateCustomerAndOrder(Customer customer, float rate) {
customerDao.update(customer);
orderDao.updateOrderPrice(rate);
}
public CustomerDao getCustomerDao() {
return customerDao;
}
public void setCustomerDao(CustomerDao customerDao) {
this.customerDao = customerDao;
}
public OrderDao getOrderDao() {
return orderDao;
}
public void setOrderDao(OrderDao orderDao) {
this.orderDao = orderDao;
}
}
插入一条Customer记录,再Update所有Order(纯粹研究,没有实际意义)
走:
代码
package test.service;
import org.apache.log4j.PropertyConfigurator;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SysInit
{
public static ApplicationContext factory = null;
private static String[] filepath = {"applicationContext_service.xml"};
public static void init()
{
PropertyConfigurator.configure("D:\\personalWork\\proGroup\\hiTestPro\\src\\log4j.properties");
if (factory == null)
{
try
{
factory = new ClassPathXmlApplicationContext(filepath);
} catch (Exception e)
{
e.printStackTrace();
}
}
try
{
} catch (Exception e)
{
e.printStackTrace();
}
}
public static Object getBean(String name)
{
if (factory == null)
{
init();
}
return factory.getBean(name);
}
public static void main(String[] args)
{
SysInit.init();
}
}
package test.service;
import junit.framework.TestCase;
import mypack.Customer;
import mypack.service.CustomerService;
public class CustomerServiceTest extends TestCase {
protected void setUp() throws Exception {
super.setUp();
SysInit.init();
}
protected void tearDown() throws Exception {
super.tearDown();
}
public void testupdateCustomerAndOrder()
{
CustomerService customerService = (CustomerService)SysInit.getBean("customerService");
Customer customer = new Customer();
customer.setId(3L);
customer.setFirstname("xiong");
customer.setLastname("hua");
customer.setSex('F');
customerService.updateCustomerAndOrder(customer, 2);
}
}
我测试了一下,如果iBatis的操作有问题,Customer也是没有办法插入了,所以基本上判断,这两个框架是可以做事务的。
各位看客以为如何?引玉中....