读书人

将Hibernate跟iBatis两Orm框架整合取

发布时间: 2012-09-08 10:48:07 作者: rapoo

将Hibernate和iBatis两Orm框架整合,取长补短

?


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来操作 ??
}??

?

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:

Java代码 将Hibernate跟iBatis两Orm框架整合,取长补短

?


????<bean?id="sessionFactory"?value="true"></property> </bean>

??? 再是iBatis的sqlMapClient

Java代码 将Hibernate跟iBatis两Orm框架整合,取长补短

?


<bean?id="sqlMapClient"?value="sql-map-config.xml"/> <property name="dataSource" ref="dataSource"/> <property name="useTransactionAwareDataSource" value="true"></property> </bean>

???? 两者是useTransactionAwareDataSource属性都设置为ture,看Spring的Javadoc,说这可以在多Orm框架中保持事务的一致性,即通过DataSource关联,果真如此否?我还没有确定出来。

??? 事务管理器,用Hibernate的

Java代码 将Hibernate跟iBatis两Orm框架整合,取长补短

?


????????<!--?事务处理的AOP配置?--> ??
<bean?id="transactionManager"?abstract="true" > <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,直接看其实现:

Java代码 将Hibernate跟iBatis两Orm框架整合,取长补短

?


???package?mypack.dao; ??
??
import?mypack.Customer; ??
??
public?class?CustomerDaoImpl?extends?BaseDaoImpl?implements?CustomerDao?{ ??
??
????public?void?update(Customer?customer);?{ ??
????????super.save(customer);; ??
????} ??
}??

?

package mypack.dao;import mypack.Customer;public class CustomerDaoImpl extends BaseDaoImpl implements CustomerDao { public void update(Customer customer); { super.save(customer);; }}

???? 再看OrderDao的实现,这个走iBatis(先分道扬镳,再殊途同归):

Java代码 将Hibernate跟iBatis两Orm框架整合,取长补短

?


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

?

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完成一个事务:

Java代码 将Hibernate跟iBatis两Orm框架整合,取长补短

?


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

?

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(纯粹研究,没有实际意义)

?? 走:

Java代码 将Hibernate跟iBatis两Orm框架整合,取长补短

?


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

?

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也是没有办法插入了,所以基本上判断,这两个框架是可以做事务的。

?

Hibernate的缓存确实是一个问题,不过可以通过合理分配两者的工作来解决,比如Hibernate负责增删改,而ibatis只负责查询。
?? 目前我的应用就是简要列表查询的数据由iBatis负责获取,从简要列表进入后的操作由Hibernate负责。
?? 不过,如果这样限定后,也就没有必须管事务的事了。整合的目的只是为了提高Dao的内聚性并屏蔽掉具体实现。

?

? iBatis主要是可以将Sql和代码解耦,使Java代码更纯一些,而Hibernate有在查询数据时有一个不好的地方是,结果集中的记录要对应Domain Class,这就限制了结果集字段的灵活性,数据库中的结果集构造是很灵活的,而不是仅对应Domain Classs。另外Hibernate还要为每条结果集构造对象,数据缓存等工作,如果仅是查询,这种工作是没有必要而费时的。
?? 总之,我觉得Hibernate不太适合于构造简要列表时的查询,它的强项在于对一个Domain Class的增,删,改,查,而非业务数据查询。

读书人网 >软件架构设计

热点推荐