Spring整合ORM技术
使用Spring所提供的ORM整合方案,我们可以获得许多好处:
- 方便基础设施的搭建:不同的ORM技术都有一套自己的方案以初始化框架、搭建基础设施等。在Spring中对于不同的ORM框架,首先,始终可以采用相同方式配置数据源;其次,Spring为不同的ORM框架提供相应的FactoryBean,用以初始化ORM框架的基础设施,可以将它们当做普通的Bean对待,唯一的差别只是属性的不同而已。
- 异常封装:Spring能够转换各种ORM框架所抛出的异常,将ORM框架专有的或检查型异常转换为SpringDAO异常体系中的标准异常。
- 统一的事务管理:Spring为不同的ORM框架提供了对应的事务管理器,可用声明的方式进行事务管理,并且可以透明地实现本地事务管理到全局JTA事务管理的切换。
- 允许混合使用多个ORM框架:一般的增删改查使用Hibernate,而数据查询使用iBatis或Spring JDBC,强强联合。
- 方便单元测试:Spring容器使得替换不同的实现和配置变得非常简单,这些内容包括:Hibernate SessionFactory的位置、JDBC DataSource、事务管理器以及映射对象的实现等,这样也就很容易隔离并测试不同的DAO类。
在Spring中使用Hibernate
Hibernate配置文件
......
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="classpath:xxx/xxxx/xxx/jdbc.properties"
p:fileEncoding="utf-8"/>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close"
p:driverClassName="${driverClassName}"
p:url="${url}"
p:username="${userName}"
p:password="${password}"/>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"
p:dataSource-ref="dataSource">
<!-- 指定hibernate实体类映射文件-->
<property name="mappingLocations">
<list>
<value>classpath*:/xxx/xxx/xxx/xxx.hbm.xml</value>
<value>classpath*:/xxx/xxx/xxx/xxx.hbm.xml</value>
<value>classpath*:/xxx/xxx/xxx/xxx.hbm.xml</value>
</list>
</property>
<!-- 指定hibernate配置属性-->
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</prop>
<prop key="hibernate.show_sql">
true
</prop>
</props>
</property>
</bean>
....
数据源、映射文件以及Hibernate属性这三方面的信息在LocalSessionFactoryBean中得到了完美集成。
使用HibernateTemplate
.....
public class BaseDao{
@Autowired
private HibernateTemplate hibernateTemplate;
.....
}
扩展这个BaseDao基类创建一个使用HibernateTemplate的Dao:
.........
@Repository
public class HibernateDao extends BaseDao{
public void updateForum(Forum forum){
getHibernateTemplate().update(forum);
}
.....
}
Spring中配置DAO
<context:component-scan base-package="xxx.xxx"/>
....
<!-- 配置HibernateTemplate Bean-->
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate"
p:sessionFactory-ref="sessionFactory"/>
<!-- 配置Hibernate的事务管理器-->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"
p:sessionFactory-ref="sessionFactory"/>
<tx:annotation-driven transaction-manager="transactionManager"/>
....
在Spring配置文件中首先配置一个HibernateTemplate Bean,它基于SessionFactory工作,使用<context:component-scan>扫描特定的类包以启用注解驱动的Bean,这样@Repository和@Autowired注解就可以起作用,将HibernateDao装配为Spring容器中的Bean了。
Spring中使用MyBatis
配置SqlMapClient
每一个MyBatis的应用程序都以一个SqlSessionFactory对象的实例为核心。SqlSessionFactory对象的实例可以通过SqlSessionFactoryBuilder对象来获得。SqlSessionFactoryBuilder对象可以从XML配置文件或Configuration类的实例中构建SqlSessionFactory对象。
mybatisConfig.xml
......
<configuration>
<settings>
<setting name="lazyLoadingEnabled" value="false"></setting>
</settings>
<typeAliases>
<typeAliase alias="Forum" type="xxx.xxx.xxx.Forum"/>
<typeAliase alias="Xxx" type="xxx.xxx.xxx.Xxx"/>
<typeAliase alias="Xxx" type="xxx.xxx.xxx.Xxx"/>
</typeAliases>
<mappers>
<mapper resource="xxx/xxx/xxx/mybatis/Forum.xml"/>
<mapper resource="xxx/xxx/xxx/mybatis/Xxx.xml"/>
<mapper resource="xxx/xxx/xxx/mybatis/Xxx.xml"/>
</mappers>
</configuration>
<settings>控制mybatis框架运行行为的属性信息,<typeAliases>标签定义全限定类名的别名,在映射文件中可以通过别名代替具体的类名。<mappers>将所有mybatis的映射文件组装起来。
Forum.xml
.....
<mapper namespace="xxx.xxx.xxx.mybatis.MybatisDao">①
<select id="getForum" resultType="Forum" parameterType="int">
SELECT
forum_id forumId,
forum_name forumName,
forum_desc forumDesc
FROM t_forum
WHERE forum_id=#{forumId}
</select>
<insert id="addForum" parameterType="Forum">
INSERT INTO t_forum(forum_id,forum_name,forum_desc)
VALUES(#{forumId},#{forumName},#{forumDesc})
</insert>
<update id="updateForum" parameterType="Forum">
UPDATE t_forum f
SET forum_name=#{forumName},forum_desc=#{forumDesc}
WHERE f.forum_id = #{forumId}
</update>
</mapper>
该文件定义了对Forum实体类进行数据操作时所需要的SQL语句,同时还定义了查询结果和对象属性的映射关系。在①处指定了映射所在的命名空间,每个具体的映射项都有一个id,可以通过命名空间和映射项的id定位具体的映射项,如通过如下语句可以调用getForum的映射语句:
SqlSession session = sqlMapper.openSession();
try{
Forum forum = (Forum)session.selectOne("xxx.xxx.xxx.mybatis.MybatisDao.getForum",1);
}finally{
session.close();
}
在Forum.xml中定义了一条SELECT、INSERT以及UPDATE语句映射项,映射项的parameterType指定传入的参数对象,可以是全限定名的类,也可以是类的别名,类别名在myBatis的主配置文件中定义。如果映射项的入参是基础类型或String类型,则可以使用如int、long、string的基础类型名。SELECT映射项拥有返回类型对象。通过resultType指定。映射项中通过#{xxx}绑定parameterType指定参数类的属性,支持级联属性,如#{topic.forumId}。
在Spring配置myBatis
......
<beans>
<context:component-scan base-package="xxx.xxx.dao.mybatis"/>
<context:component-scan base-package="xxx.xxx.service.mybatis"/>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="classpath:xxx/xxxx/xxx/jdbc.properties"
p:fileEncoding="utf-8"/>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close"
p:driverClassName="${driverClassName}"
p:url="${url}"
p:username="${userName}"
p:password="${password}"/>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"
p:dataSource-ref="dataSource"
p:configLocation="classpath:mybatisConfig.xml"/>
</beans>
如果在mybatis配置文件mybatisConfig.xml中指定SQL映射文件,必须逐个列出所有的SQL映射文件,比较繁琐。我们可以先将映射文件匹配从mybatisConfig.xml中移除,然后通过<mapperLocations>加载SQL映射文件:
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"
p:dataSource-ref="dataSource"
p:configLocation="classpath:mybatisConfig.xml"
p:mapperLocations="classpath:xxx/xxx/xxx/mybatis/*.xml"/>
这样,SqlSessionFactoryBean将扫描xxx/xxx/xxx/mybatis类路径并加载所有以xml为后缀的映射文件。
使用SqlSessionTemplate
首先在Spring中配置好SqlSessionTemplate Bean:
<bean class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg ref="sqlSessionFactory"/>
</bean>
.......
@Repository
public class MybatisTemplateDao{
@Autowired
private SqlSessionTemplate sessionTemplate;
public Forum getForum(int forumId){
return (Forum)sessionTemplate.selectOne("xxx.xxx.xxx.mybatis.MybatisDao.getForum",forumId);
}
}
SqlSessionTemplate通过selectOne()方法调用在Forum.xml映射文件中定义的命名空间为:xxx.xxx.xxx.mybatis.MybatisDao、映射项id为:getForum的SQL映射项,并传入参数,返回映射成Forum对象的查询结果。