《Spring3实战》摘要(5-2)Spring中使用Hibernate

5.4 在 Spring 中集成Hibernate

随着应用程序变得越来越复杂,对持久化的需求也变得越来越复杂。我们需要将对象的属性映射到数据库的裂伤,并且需要自动生成语句和查询,这样我们就能从无休止的问号字符串中解脱出来。我们还需要一些更复杂的特性:

  • 延迟加载(Lazy loading):随着对象关系变得越来越复杂,有时候我们并不希望立即获取完整的对象间关系。借助于延迟加载,我们可以只抓取需要的数据,减少查询无用数据的开销。
  • 预先抓取(Eager fetching):这与延迟加载是相对的。借助于预先抓取,我们可以使用一个查询获取完整的关联对象。预先抓取功能可以在一个操作中将对象及其关联的对象数据全部从数据库中提取出来,这节省了多次查询的成本。
  • 级联(Cascading):有时,更改数据库中的表会勇士修改其他表。如订购单的例子,当删除 Order(订货单表) 对象时,我们希望同时在数据库中删除关联的 LineItem(订货单对应的货品明细) 。

一些可用的框架提供了这样的服务。这些服务的通用名称是对象/关系(object-relational mapping,ORM)。

Spring 对多个持久化框架都提供了支持,包括 Hibernate、IBATIS(于2010年6月16号被谷歌托管,改名为MyBatis。是一个基于SQL映射支持Java和·NET的持久层框架)、Java数据对象(Java Data Objects,JDO)以及 Java 持久化 API。

Spring 对 ORM 框架的支持提供了与这些框架的集成点以及一些附加的服务,如下所示

  • Spring 声明式事务的集成支持;
  • 透明的异常处理;
  • 线程安全的、轻量级的模板类;
  • DAO 支持类;
  • 资源管理。

5.4.1 Hibernate 概览

Spring 对 Hibernate 的支持也提供了类似的模板类来抽象 Hibernate 的持久化功能。

以前,在 Spring 应用程序中使用 Hibernate 是通过 HibernateTemplate 进行的。与 JDBC 对等的对象很类似。

HibernateTemplate 简化了使用 Hibernate 的繁琐工作,这是通过捕获 Hibernate 特定的异常,然后将其转换为 Spring 的非检查型数据访问异常并重新抛出而实现的。

HibernateTemplate 的不足之处在于存在一定程度的侵入性。不管是直接使用还是通过 HibernateDAOSupport 时,DAO 类就会与 Spring API 产生了耦合。

尽管 HibernateTemplate 还存在,但是这已经不是使用 Hibernate 的最佳方式了。Hibernate 3 所引入了上下文 Session (Contextual session)的方案,这是 Hibernate 本身所提供的保证每个事务使用同一个 session 的方案,因此没有必要再使用 HibernateTemplate 来保证这一行为了。这种方式能够让你的 DAO 类不包含特定的 Spring 代码。

5.4.2 声明 Hibernate 的 Session 工厂

使用 Hibernate 的主要接口是 org.hibernate.Session。 该Session接口提供了基本的数据访问功能。应用程序的 DAO 通过 Session 接口能够满足所有的持久化需求。

获取 Hibernate Session 对象的标准方式是借助于 Hibernate 的 SessionFactory 接口的实现类。除了一些其他的任务,SessionFactory 主要负责 Hibernate Session 的打开、关闭以及管理。

在 Spring 中,我们要通过 Spring 的某一个 Hibernate Session 工厂 Bean 来获取 Hibernate 的 SessionFactory 。

注:需要添加 spring-orm.jar

在配置 Hibernate Session 工厂 Bean 的时候,我们需要确定持久化域对象是通过 XML 文件还是通过注解来进行配置的。如果选择在 XML 中定义对象与数据库之间的映射,那么需要在 Spring 中配置 LocalSessionFactoryBean

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="mappingResources">
        <list>
            <value>Spitter.hbm.xml</value>
        </list>
    </property>
    <property name="hibernateProperties">
        <props>
            <prop key="dialect">org.hibernate.dialect.H2Dialect</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.format_sql">true</prop>
            <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
            <prop key="hibernate.hbm2ddl.auto">update</prop>
        </props>
    </property>
</bean>

如果你更倾向于使用注解的方式来定义持久化,那需要使用 AnnotationSessionFactoryBean 来代替 LocalSessionFactoryBean:

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <!-- 配置需要扫描 JPA 注解的包 -->
    <property name="packagesToScan" value="com.habuma.spitter.domain" />

    <!-- 需要扫描的包邮多个时的配置
    <property name="packagesToScan">
        <list>
            <value>xx.xxx.xxx</value>
        </list>
    </property>
    -->

    <!-- 还可以通过使用 annotatedClasses 属性来将应用程序中所有的持久化类以全限定名的方式明确列出
    <property name="annotatedClasses">
        <list>
            <value>xxx.xxx.xxx.Spitter</value>
        </list>
    </property>
     -->
    <property name="hibernateProperties">
        <props>
            <prop key="dialect">org.hibernate.dialect.H2Dialect</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.format_sql">true</prop>
            <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
            <prop key="hibernate.hbm2ddl.auto">update</prop>
        </props>
    </property>
</bean>

5.4.3 构建不依赖于 Spring 的 Hibernate 代码

import org.hibernate.SessionFactory;
import org.hibernate.classic.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.spring.springdemo.spitter.entity.Spitter;

@Repository
public class HibernateSpitterDao implements SpitterDAO {

    private SessionFactory sessionFactory;

    @Autowired
    public HibernateSpitterDao(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    // 从 SessionFactory 中获取当前的 Session
    private Session currentSession(){
        return sessionFactory.getCurrentSession();
    }

    @Override
    public void addSpitter(Spitter spitter) {
        currentSession().save(spitter);
    }

    @Override
    public Spitter getSpitterById(long id) {
        return (Spitter) currentSession().get(Spitter.class, id);
    }
}

@Repository 在上面的示例代码中,除了帮助简化 XML 配置以外,@Repository 还可以辅助 PersistenceExceptionTranslationPostprocessor Bean。

PersistenceExceptionTranslationPostprocessor 是一个 Bean 的后置处理程序,它会在所有拥有 @Repository 注解的类上添加一个通知器(advisor),这样就会捕获任何平台相关的异常并以 Spring 的非检查型数据访问异常的形式重新抛出。

<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostprocessor" />

5.5 Spring 与 Java 持久化 API(略)

Java 持久化 API(Java Persistence API ,JPA)诞生在 EJB 2 实体 Bean 的废墟之上,并成为下一代 Java 持久化标准。JPA 是基于 POJO 的持久化机制,它从 Hibernate 和 Java 数据对象(Java Data Object,JDO)上借鉴了很多理念并加入了 Java 5 注解的特性。

5.5.1 配置实体管理器工厂

简单来说,基于 JPA 的应用程序使用 EntityManagerFactory 的实现类来获取 EntityManager 实例。JPA 定义了两种类型的实体管理器:

  • 应用程序管理类型(Application-managed):当应用程序向实体管理器工厂直接请求实体管理器时,工厂会创建一个实体管理器。在这种模式下,程序要负责打开或关闭实体管理器并在事务中对其进行控制。这种方式的实体管理器适合不运行在 Java EE 容器中的对立应用程序。
  • 容器管理类型(Container-managed):实体管理器由 Java EE创建和管理。应用程序个人呢不让你不与实体管理器工厂打交道。相反,实体管理器直接通过注入或 JNDI 来获取。容器负责配置实体管理器工厂。这种情况下会希望在 persistence.xml 指定的配置之外保持一些自己对 JPA 的控制。

。。。。下面的暂时略过。。。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值