整合其他ORM框架

使用Spring所提供的ORM整合方案, 可以获得许多好处:

  1. 方便基础设施的搭建

    Spring中, 对不同的ORM框架, 首先, 始终可以采用相同的方式配置数据源; 其次, Spring为不同的ORM框架提供了相应的FactoryBean, 用以初始化ORM框架基础设施

  2. 异常封装

    Spring能够转换各种ORM框架所抛出的异常, 转换为Spring DAO异常体系中的标准异常.

  3. 统一的事务管理

    只要遵循Spring所提出的很少的编程要求, 就可以使用Spring提供的事务管理功能.

  4. 允许混合使用多个ORM框架

    由于Spring在DAO异常, 事务, 资源等高级层次建立了抽象, 因而可以让业务层对DAO具体实现的技术不敏感.

  5. 方便单元测试

在Spring中使用Hibernate

配置SessionFactory

使用Hibernate框架的首要工作是编写Hibernate配置文件, 其次是如何使用这些配置文件实例化SessionFactory, 创建Hibernate的基础设施

Spring为创建SessionFactory提供类LocalSessionFactoryBean, 通过配置一些必要的属性, 就可以获取一个SessionFactoryBean

  1. 零过渡障碍的配置方式

    1
    <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean" p:configLocaiton="classpath: hiberante.cfg.xml" />

    configLocation属性指定一个Hibernate配置未见

    configLocations属性指定多个配置文件, 用逗号分隔

    LocalSessionFactoryBean利用Hibernate配置文件创建一个SessionFactory代理对象, 以便和Spring的事务管理机制配合工作: 当数据访问代码使用SessionFactory时, 可以获取线程绑定的Session, 不管工作在本地或全局的事务, 都能正确参与到当前的事务管理中

  2. 更具Spring风格的配置

    可以在Spring容器中定义数据源, 指定映射文件, 设置Hibernate控制属性等信息, 完成集成组装工作, 完全抛开hibernate.cfg.xml配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    <context:property-placeholder location="classpath:jdbc.properties"/>
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" p:driverClassName="${jdbc.driverClassName}" p:url="${jdbc.url}" p:username="${jdbc.username}" p:password="${jdbc.password}"/>
    <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean" p:dataSource-ref="dataSource"> <property name="mappingLocations">
    <list>
    <value>classpath*:/com/smart/org/domain/Forum.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>

使用HibernateTemplate

Spring提供了使用模板的支持类HibernateDapSupport, 并通过getHibernateTemplate()方法向子类开发模板类实例的调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 保存实体对象
getHibernateTemplate().save(forum); // 更改实体对象
getHibernateTemplate().update(forum); // 获取实体对象
getHibernateTemplate().get(Forum.class, forumId); // 使用HQL查询
getHibernateTemplate().find("from Forum f where f.forumName like ?", forumName + "%"); // 使用Iterate返回结果
getHibernateTemplate().iterate("select count(f.forumId) from Forum f").next();
  1. 常用的API方法

    • Serializable save(Object entity): 保存实体对象, 并返回主键值. void persist(Object entity)方法类似
    • void update(Object entity): 更新实体对象
    • void saveOrUpdate(Object entity): 保存或更新一个实体. 与<T> T merge(T entity)方法类似
    • void delete(Object entity): 删除一个实体
    • List find(String queryString): 根据HQL查询实体.
    • List findByNamedQuery(String queryName): 执行命名查询
    • List findByCriteria(DetachedCriteria criteria): Criteria版本查询.
  2. 使用回调接口

    Spring定义了一个回调接口HibernateCallback, 该接口有唯一方法:

    1
    T (Session session) throws HibernateException, SQLException

    该接口配合HibernateTemplate进行工作, 无须关系Hibernate Session的打开/关闭操作, 仅需要定义数据访问逻辑即可.

    • T execute(HibernateCallback action): 执行更新, 新增等炒作
    • List executeFind(HibernateCallback<?> action): 执行数据查询操作, 返回的结果是List
    1
    2
    3
    4
    5
    6
    getHibernateTemplate().execute(new HibernateCallback<Long>() {
    public Long (Session session) throws HibernateException, SQLException {
    Object obj = session.createQuery("select count(f.forumId) from Forum f").list.interator().next();
    return (Long) obj;
    }
    });
  3. 在Spring中配置DAO

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    <context:component-scan base-package="com.smart"/>
    <context:property-placeholder location="classpath:jdbc.properties"/>
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" p:driverClassName="${jdbc.driverClassName}" p:url="${jdbc.url}" p:username="${jdbc.username}" p:password="${jdbc.password}"/>
    <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean" p:dataSource-ref="dataSource"> <property name="mappingLocations">
    <list>
    <value>classpath*:/com/smart/org/domain/Forum.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>
    <!-- 配置HibernateTemplate Bean -->
    <bean id="hibernateTemplate" class="org.springframework.orm.hibernate5.HibernateTemplate" p:sessionFactory-ref="sessionFactory"/>
    <!-- 配置Hibernate事务管理器 -->
    <bean id="transactionManager" class="org.srpingframework.orm.hibernate5.HibernateTrancactionManager" p:sessionFactory-ref="sessionFactory"/>
    <tx:annotation-driven transaction-manager="transactionManager"/>

处理LOB类型数据

Hibernate定义了一个接口: org.hibernate.usertype.UserType

Spring提供了几个UserType的实现类, 可以在Hinerbate的映射文件中直接使用这些实现类轻松处理了LOB类型的数据

  • BlobByteArrayType: 将BLOB数据映射为byte[]类型的属性
  • BlobStringType: 将BLOB数据映射为String类型的属性
  • BlobSerializableType: 将BLOB数据映射为Serializable类型的属性
  • ClobStringType: 将CLOB数据映射为String类型的属性

添加Hibernate事件监听器

LocalSessionFactoryBean允许通过eventListeners属性向Hibernate注册事件监听器

Spring本身提供了一个Hibernate事件监听器IdTransferringMergeEventListen 大专栏  Blue的博客er

1
2
3
4
5
6
7
8
9
10
11
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="eventListeners">
<map>
<!-- 事件监听器类型 -->
<entry key="merge">
<!-- 事件监听器实现类 -->
<bean class="org.springframework.orm.hibernate5.support.IdTransferringMergeEventListener" />
</entry>
</map>
</property>
</bean>

Hibernate预定义的类型: auto-flush, mrege, create, delete, dirty0check, evict, flush, flush-entity, load, load-collectioin, lock, refresh, replicate, save-update

使用注解配置

使用注解对Forum进行ORM配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Table(name="t_forum")
public class Forum implements Serializable {
@Id
@Column(name="forum_id")
private int forumId; @Column(name="forum_name")
prvate String forumName; @Column(name="forum_desc")
private String forumDesc; // setter, getter
}

Hiberante通过AnnotationConfiguration的addAnnotatedClass()或addPackage()方法加载使用JPA注解的实体类, 获取映射的元数据信息, 并在此基础上创建SessionFactory实例.

addPackage并不是价值类包下所有标注了ORM注解的实体类, 而是加载类包下package-info.java文件中定义的Annotation

使用AnnotationSessionFactoryBean创建基于JPA注解的SessionFactory

1
2
3
4
5
6
7
8
9
<!-- 通过AnnotationSessionFactoryBean定义SessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.annotation.AnnotationSessionFactoryBean" p:dataSource-ref="dataSource">
<property name="packagesToScan" value="com.smart.orm.domain" />
<property name="annotatedClasses">
<list>
<value>com.smart.orm.domain.Forum</value>
</list>
</property>
</bean>

延迟加载问题

Hibernate允许对关联对象, 属性进行延迟加载, 但必须保证延迟加载的操作限于同一个Hibernate Session范围内.

Spring为此专门提供了一个OpenSessionInViewFilter过滤器, 主要功能是使每个请求过程绑定一个HibernateSession, 即使最初的事务已经完成, 也可以在Web层进行延迟加载操作.

OpenSessionInViewFilter将Hibernate Session绑定到请求线程中, 它将自动被Spring的事务管理器探测到

在Spring中使用MyBatis

MyBatis要求开发者编写具体的SQL语句.

配置SqlMapClient

每个MyBatis应用程序都以一个SqlSessionFactory对象的实例为核心.

SqlSessionFactory对象的实例可以通过SqlSessionFactoryBuilder对象来获取.

SqlSessionFactoryBuilder对象可以从XML配置文件或Configuration类的实例中构建SqlSessionFactory对象

MyBatis配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatic.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 可控制MyBatis框架允许行为的属性信息 -->
<settings>
<setting name="lazyLoadingEnabled" value="false"/>
</settings>
<!-- 定义全限定类名的别名, 在映射文件中通过别名代替具体的类名 -->
<typeAliases>
<typeAlias alias="Forum" type="com.smart.orm.domain.Forum"/>
</typeAliases>
<!-- 映射文件 -->
<mappers>
<mapper resource="com/smart/orm/domain/mybatis/Forum.xml"/>
</mappers>
</configuration>

在Spring中配置MyBatis

1
2
3
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" p:driverClassName="${jdbc.driverClassName}" p:url="${jdbc.url}" p:username="${jdbc.username}" p:password="${jdbc.password}"/>

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" p:dataSource-ref="dataSource" p:configLocation="classpath:myBatisConfig.xml"/>

SqlSessionFactoryBean提供了mapperLocations属性, 支持扫描式加载SQL映射文件

1
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" p:dataSource-ref="dataSource" p:configLocation="classpath:myBatisConfig.xml" p:mapperLocations="classpath:com/smart/orm/domain/mybatis/*.xml"/>

编写MyBatis的DAO

  1. 使用SqlSessionTemplate

    1
    2
    3
    <bean class="org.mybatis.spring.SqlSessionTemplate">
    <constructor-arg ref="sqlSessionFactory"/>
    </bean>

    使用SqlSessionTemplate调用SQL映射项完成数据访问操作

    1
    2
    3
    4
    @Autowired
    private SqlSessionTemplate sessionTemplate;
    // 通过selectOne()方法调用Forum.xml映射文件中定义的命名空间为com.smart.orm.dao.mybatic.ForumMybatisDao, 映射项id为getForum的SQL映射项, 并传入参数
    sessionTemplate.selectOne("com.smart.orm.dao.mybatic.ForumMybatisDao.getForum", forumId);

    SqlSessionTemplate模板类提供了多个方便调用的方法

    • List<?> selectList(String statement, Object parameter): 调用select映射项, 返回一个结果对象集合
    • int insert(String statement, Object parameter): 调用insert映射项, 返回插入的记录数
    • int update(String statement, Object parameter): 调用update映射项, 返回更改的记录数
  2. 使用映射接口

    MyBatis提供了一种可将SQL映射文件中的映射项通过名称匹配接口进行调用的方法: 接口名称和映射命名空间相同, 接口方法和映射元素的id相同

    为Forum.xml文件的映射项定义调用接口

    1
    2
    3
    public interface ForumMybatisDao {
    Forum getForum(int forumId);
    }

    Forum.xml文件中的每个映射项对应一个接口方法, 接口方法的签名和映射项的声明匹配

    通过SqlSessionTemplate获取接口的实例

    1
    2
    ForumMybatisDao forumMybatisDao = sessionTemplate.getMapper(ForumMybatisDao.class);
    forumMybatisDao.getForum(forumId);

    mybatis-spring提供了一个转换器MapperScannerConfigurer, 可以将映射接口直接转换为Spring容器中的Bean, 这样就可以在Service汇总注入映射接口的Bean了.

    如下配置即可将接口转换为Bean

    1
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer" p:sqlSessionFactory-ref="sqlSessionFactory" p:basePackage="com.smart.orm.dao.mybatis"/>

    MapperScannerConfigurer将扫描basePackage所指定的包下的所有接口(包括子包), 如果它们在SQL映射文件中定义过, 则将它们动态定义为一个Spring Bean, 这样就可以在Service中直接注入映射接口的Bean

Blue的博客的更多相关文章

  1. 第1章 Express MongoDB 搭建多人博客

    学习环境 Node.js : 0.10.22 + Express : 3.4.4 + MongoDB : 2.4.8 + 快速开始 安装 Express express 是 Node.js 上最流行的 ...

  2. 博客中 Flex4/Flash mp3音乐播放器实例 含演示地址

    要求 必备知识 本文要求基本了解 Adobe Flex编程知识和JAVA基础知识. 开发环境 MyEclipse10/Flash Builder4.6/Flash Player11及以上 演示地址 演 ...

  3. 使用markdown语法撰写csdn博客

    在CSDN之下写blog无疑是一件非常吃力的事情,对于非常多simple爱好者来讲,能用markdown语法来书写代码是最优雅简洁只是的了.本文主要介绍markdown语法和怎样它来撰写csdn下的b ...

  4. 基于express+mongodb+pug的博客系统——pug篇

    很久之前就想自己搭一个博客了,最开始用hexo+github,但是换电脑后总是有些麻烦.后来使用WordPress,但是用WordPress总觉得没什么技术含量,前后端都是人家写好的,而且买的垃圾虚拟 ...

  5. 基于Hexo搭建博客并部署到Github Pages

    基于Hexo搭建博客并部署到Github Pages 之前在简书上写东西,觉得自己还是太浮躁.本来打算用Flask自己写一个,以为是微框架就比较简单,naive.HTML.CSS.JS等都要学啊,我几 ...

  6. evak购物车--团队博客

    1. 团队名称.团队成员介绍(需要有照片) 团队名称:evak 团队成员介绍:陈凯欣,计算机工程学院网络工程1512,学号为201521123034:邱晓娴,计算机工程学院网络工程1512,学号为20 ...

  7. github pages + Hexo + 域名绑定搭建个人博客增强版

    概述 前面我们用github pages + Hexo 搭建了一个简单版的个人博客系统,但是里面的内容单调,很多功能不够完善,所以我们需要对yelle 的主题进行优化和完善.基本搭建请访问:http: ...

  8. HTML5中 HTML格式化/HTML样式/链表/表格-样式 韩俊强的博客

    HTML5学习从简单到复杂,循环渐进! 每日更新关注:http://weibo.com/hanjunqiang  新浪微博! 1.HTML格式化 <!DOCTYPE html> <h ...

  9. 使用github pages搭建个人博客

    一.环境准备 使用Github Pages搭建个人博客,一劳永逸,可以让我们更加专注于博客的撰写.博客的更新是通过将新建或改动的博客放在指定文件夹并推送到远程Github仓库来完成的,所以我们本地需要 ...

随机推荐

  1. LeetCode——853.车队

    N 辆车沿着一条车道驶向位于 target 英里之外的共同目的地. 每辆车 i 以恒定的速度 speed[i] (英里/小时),从初始位置 position[i] (英里) 沿车道驶向目的地. 一辆车 ...

  2. 14 微服务电商【黑马乐优商城】:day02-springcloud(理论篇一:HttpClient的简单使用)

    本项目的笔记和资料的Download,请点击这一句话自行获取. day01-springboot(理论篇) :day01-springboot(实践篇) day02-springcloud(理论篇一: ...

  3. Android之UI View与ViewGroup

    1.基本概念 View:所有可视化控件的父类,Android App屏幕上用户可以交互的对象(例如 按钮 下拉框 文本框等). ViewGroup:View的子类,存放View和ViewGroup对象 ...

  4. Educational Codeforces Round 64(Unrated for Div.1+Div. 2)

    什么垃圾比赛,A题说的什么鬼楞是没看懂.就我只会BD(其实C是个大水题二分),垃圾游戏,技不如人,肝败吓疯,告辞,口胡了E就睡觉了. B 很容易发现,存在一种方案,使得相同字母连在一起,然后发现,当字 ...

  5. idea新建maven项目后生成web.xml方法和添加到tomcat方法

    idea新建maven项目后生成web.xml方法和添加到tomcat方法 参考:https://www.cnblogs.com/Liang-Haishan216/p/9302141.html 1.首 ...

  6. Ubuntu 设置静态 IP

    一.背景 如果没有设置静态IP,由于某些情况,会导致系统的 IP 地址发生变化. 为了避免 IP 发生变化,就需要进行静态 IP 的设置. 注:这里 Ubuntu 版本为 19.10 二.解决方案 1 ...

  7. [USACO09DEC]音符Music Notes (二分、STL)

    https://www.luogu.org/problem/P2969 题目描述 FJ is going to teach his cows how to play a song. The song ...

  8. 十九、linux--RAID详解

    一.什么是RADI Raid是廉价冗余磁盘阵列,简称磁盘阵列. 运维人员就叫RAID.Raid是一种把多块独立的磁盘(物理磁盘)按不同方式组合起来形成一个磁盘组,在逻辑上看起来就是一个大的磁盘,从而提 ...

  9. python,openpyxl,读写excel文件

    import openpyxl as oxl from openpyxl.utils import get_column_letter, column_index_from_string import ...

  10. python编程常用功能(随时添加)

    1 pandas查看DataFrame列或具体值数据类型 2 left join/right join/inner join的区别 3 df_series.value_counts() 4 删除dat ...