翻译 - Hibernate入门指南

原文连接 http://docs.jboss.org/hibernate/orm/current/quickstart/html_single/#hibernate-gsg-tutorial-basic-entity吐舌头

Hibernate入门指南

    1 获得Hibernate
        1.1 Hibernate Modules/Artifacts
        1.2 发布包下载
        1.3 Maven存储库工件
    2 使用原生Hibernate api和hbm.xml映射教程
        2.1 Hibernate配置文件
        2.2 Java实体类
        2.3 映射文件
        2.4 示例代码
        2.5 更进一步!
    3 使用原生Hibernate api和注解映射教程
        3.1 Hibernate配置文件
        3.2 带注解的Java类实体
        3.3 示例代码
        3.4 更进一步!
    4 使用Java Persistence API(JPA)教程
        4.1 persistence.xml
        4.2 带注解的Java类实体
        4.3 示例代码
        4.4 更进一步!
    5 使用Envers教程
        5.1 persistence.xml
        5.2 带注解的Java类实体
        5.3 示例代码
        5.4 更进一步!

前言

使用面向对象的软件和关系数据库进行开发可以说是繁琐又费时。 开发成本明显高于由于解决范式不匹配(即基本的Bean对象与关系数据库之间)的成本。 Hibernate是一个Object/Relational(对象/关系) Mapping (ORM)Java开发环境下的解决方案。 术语:对象/关系映射(ORM)是指在对象模型和关系数据模型之间相互转化的数据映射技术。 参见 http://en.wikipedia.org/wiki/Object-relational_mapping 有着更高层次讨论。 同时, Martin Fowler’s OrmHate文章可以看到许多不能进行匹配的问题 https://martinfowler.com/bliki/OrmHate.html 。

对数据建模概念有一个基本的理解,可以帮助您更快更完全的理解Hibernate。 这两个 http://www.agiledata.org/essays/dataModeling101.html 和 http://en.wikipedia.org/wiki/Data_modeling 可以帮助你理解数据建模原则。

Hibernate负责从Java类映射到数据库中的表,从java数据类型的SQL数据类型的工作。 另外,它还提供了数据查询和检索功能。 它可以显著降低开发时间,因为SQL和JDBC中的手动处理数据非常浪费时间。 Hibernatea的设计目标是减少开发人员负担,处理与数据库访问相关的事情中(95%类似管理数据库资源和处理异常的烦人操作)脱离出来。 然而与许多其他持久性解决方案不同的是Hibernate不隐藏SQL,并且你在关系数据库方面的拥有的知识还是有效的。

Hibernate可能不是以数据为中心的应用程序(只使用存储过程实现数据库中的业务逻辑)的最好解决方案,在基于java逻辑的中间层(面向对象领域模型和业务逻辑之间)Hibernate是最有用的。 然而Hibernate可以帮助你删除或封装特定于供应商的SQL代码还可以把sql执行的结果集合转换为对象集合。

参见 http://hibernate.org/orm/contribute/ 为Hibernate ORM奉献的信息。
    教程的项目和代码在 docs.jboss.org/hibernate/orm/current/quickstart/html_single/hibernate-tutorials.zip
1 获得Hibernate
1.1 Hibernate Modules/Artifacts

Hibernatea的功能分为若干Modules/Artifacts意味着不需要相互依赖(模块化)。

hibernate core:    主(核心)Hibernate模块。 定义它的ORM特性和api以及各种集成spi。
hibernate-envers:    Hibernatea历史版本特征
hibernate-spatial:    Hibernate的Spatial/GIS data-type(数据类型)的支持
hibernate-osgi:    Hibernate支持运行在OSGi容器。
hibernate-c3p0:    整合了 C3P0 库连接池进入Hibernate
hibernate-hikaricp:    整合了 HikariCP 库连接池进入Hibernate
hibernate-proxool:    整合了 Proxool 库连接池进入Hibernate
hibernate-jcache:     整合了 JCache 缓存规范进入Hibernate, 使任何兼容兼容规范的实现都可以成为二级缓存提供者。
hibernate-ehcache:    整合了 Ehcache 缓存库为Hibernate二级缓存提供者。
hibernate-infinispan:    整合了 Infinispan 缓存库作为Hibernate二级缓存提供者。

1.2  发布包下载

Hibernate团队在SourceForge(托管文件发布系统)上提供发布包,在有 TGZ 和 ZIP 两种格式。 每个版本包包含 JAR 文件、文档、源代码和其他有用的东西。

你可以从列表中选择你喜欢的格式下载对应版本的Hibernate, https://sourceforge.net/projects/hibernate/files/hibernate-orm/ 。 发布包的结构如下:

    lib/required/ 目录包含 hibernate core jar和它的所有依赖项。 所有这些罐子 需要在类路径中使用Hibernate的无论哪一个特性。

    lib/envers 目录包含 hibernate-envers jar和它的所有依赖项(除了 lib/required/ 和 lib/jpa/ )。

    lib/spatial/ 目录包含 hibernate-spatial jar和它的所有依赖项(除了 lib/required/ )

    sgi/lib/ 目录包含 hibernate-osgi jar和它的所有依赖项(除了lib/required/和lib/jpa/ )

    lib/jpa-metamodel-generator/目录包含生成标准API类型安全元模型所需的JAR

    lib /可选目录包含由Hibernate提供各种连接池和二级缓存集成所需的jar,连同他们的依赖的jar。

1.3 Maven存储库工件

权威的Hibernate构件库是JBoss Maven存储库。 Hibernate构件会自动同步到Maven中央仓库(可能发生一些小的延迟)。

负责JBoss Maven仓库的团队维护一批包含重要信息的Wiki页面:

    http://community.jboss.org/docs/doc - 14900 ——关于仓库的一般信息。

    http://community.jboss.org/docs/doc - 15170 ——建立JBoss仓库来存放JBoss项目开发工作的信息。

    http://community.jboss.org/docs/doc - 15169 ——使用JBoss项目设置访问仓库信息。

Hibernate ORM构件是在org.hibernate groupId下发表的。

2.  教程使用原生Hibernate api和hbm.xml映射
    本教程是位于下载包下basic/目录。
本节目标

    引导Hibernate使用SessionFactory

    使用Hibernate映射(hbm.xml)文件提供映射信息

    使用Hibernate的原生api

2.1. Hibernate配置文件

hibernate.cfg.xml 文件定义了Hibernate配置信息。

connection.driver_class , connection.url , connection.username 和 connection.password <property/ > 元素定义JDBC连接信息。 这些教程基于H2内存数据库,所以这些属性的值 都是特定于H2内存模式下运行的。 connection.pool_size 用于配置连接Hibernatea中内置的连接池的数量。
    内置的Hibernate连接池决不适合生产使用。 它缺乏生产环境下就绪连接池上发现的几个功能。

dialect 属性指定了Hibernate能够和多种SQL数据库进行交流
    在大多数情况下,Hibernate是能够正确确定使用哪个dialect(方言)。如果您的应用程序的目标多个数据库这将会特别有用。

hbm2ddl.auto 属性允许自动生成database schemas直接的插入到数据库中。

最后,添加持久化类的映射文件配置。 resource 属性的 <mapping/> 元素使Hibernate试图使用 java.lang.ClassLoader 找到映射类路径的资源。

有很多方法和选项引导Hibernate的SessionFactory。 有关更多细节,请参见Native Bootstrapping topical 指南参见 https://docs.jboss.org/hibernate/orm/current/userguide/html_single/Hibernate_User_Guide.html 。
2.2 Java的实体类

本教程色实体类是 org.hibernate.tutorial.hbm.Event
Notes About the Entity
    这个类使用标准的JavaBean命名约定,用于属性获取和设置( getter and setter)方法,以及私有字段的可见性。虽然这是推荐的设计,它不是必需的。

    无参数的构造函数,这也是一个JavaBean惯例,是所有持久化类都需要的部分。 Hibernate使用Java反射为你创建需要的对象。 构造函数可以是私有的。 然而,package or public可见性是必须的,在运行时代理的生成和高效的数据检索是没有字节码植入的。

2.3 映射文件

本教程是映射文件是 classpath的资源 org/hibernate/tutorial/hbm/Event.hbm.xml (如上所述)。

Hibernate使用映射元数据来决定如何加载和存储持久化类的对象。 Hibernate映射文件是一个提供元数据的选择。
例1 类映射元素

<class name="Event" table="EVENTS">
    ...
</class>


函数的<varname>class</varname>元素的映射

    name 属性(从<hibernate-mapping/>元素这里的package 属性相结合) 表示该类以全限定名的方式被定义为一个实体。

    table 属性表示数据库表中包含该实体数据的表的名称。

Event类的实例 现在映射到数据库EVENTS表中的行数据。
例2。 映射id元素(表中列字段的映射)

<id name="id" column="EVENT_ID">
    ...
</id>


Hibernate使用属性名为<id/>的元素来唯一地识别表中的行。
    ID元素不需要强制映射到表的实际主键列,但它是常规约定。Hibernate中映射的表甚至不需要定义主键。 然而,强烈推荐所有框架定义适当的引用完整性。 因此在Hibernate文档中id和主键是可以互换的 。

<id/>元素命名为EVENT_ID列作为EVENTS表的主键(就是说id元素下的name属性的值"id"【这个id也就是是某个Java实体类中的名为id属性字段的数据】 被映射为表中名为"EVENT_ID"的列的数据)。 它还确定了Event类的id字作为包含标识符的值属性。

generator 元素告诉Hibernate哪些方案是用来生成这个实体的主键值。 这个例子使用一个简单的递增计数。
例3  属性映射元素

<property name="date" type="timestamp" column="EVENT_DATE"/>
<property name="title"/>

这两个 <property/> 元素声明剩下的两个持久化属性即Event类:date和title属性。date拥有column属性映射  ,但title没有。在缺乏column属性时候,Hibernate使用属性名作为列名。对title来说这是合理的 ,但由于date是大多数数据库中的保留关键字,您需要为列名指定一个非保留字(所以此处使用了column="EVENT_DATE" 而不是像title一样留空等待Hibernate指定)。

title 还缺少一个type属性映射。映射文件中声明和使用的类型既不是Java数据 类型也不是SQL数据库类型。他们是Hibernate映射类型,这是Java和SQL数据类型之间翻译的转换器。 如果 没有指定类型属性的映射,Hibernate会试图确定正确的自动转换和映射类型,利用java反射和默认映射类型确定java类型并且声明属性。

在某些情况下,这种自动检测机制可能不会选择你需要的默认,正如所看到的date属性。 Hibernate不知道这个属性是java.util.Date的哪一个类型,应该映射到SQL的DATE, TIME, or TIMESTAMP 数据类型。保存完整的日期和时间信息通过映射属性到timestamp转换器,在类 org.hibernate.type.TimestampType下。
    Hibernate使用反射处理映射文件时就确定了映射类型。 这一过程增加了时间和资源的开销。 如果启动性能是重要,考虑显式定义使用的类型。
2.4  示例代码

org.hibernate.tutorial.hbm.NativeApiIllustrationTest类演示了使用Hibernate的原生API。
    这些教程中的例子为了方便使用JUnit作为测试。这种方法的一个好处是 setUp 和 tearDown 大致说明 org.hibernate.SessionFactory 在 应用程序启动的时候创建,在应用程序生命周期结束的时候关闭。
例4  获得 org.hibernate.SessionFactory
protected void setUp() throws Exception {
    // A SessionFactory is set up once for an application!(在整个应用程序中只有一个SessionFactory)
    final StandardServiceRegistry registry = new StandardServiceRegistryBuilder()
            .configure() // configures settings from hibernate.cfg.xml
            .build();
    try {
        sessionFactory = new MetadataSources( registry ).buildMetadata().buildSessionFactory();
    }
    catch (Exception e) {
        // The registry would be destroyed by the SessionFactory, but we had trouble building the SessionFactory(SessionFactory注册将被摧毁,会导致我们很难构建SessionFactory)
        // so destroy it manually.(在此处手动摧毁)
        StandardServiceRegistryBuilder.destroy( registry );
    }
}


setUp 方法首先构建一个 org.hibernate.boot.registry.StandardServiceRegistry 实例,包含 配置信息合并到到一个使用SessionFactory服务的工作集。 在本教程中我们所有的配置信息定义在 hibernate.cfg.xml中了。

使用 StandardServiceRegistry 我们创建的 org.hibernate.boot.MetadataSources 这是告诉Hibernate你的域模型的起点。 我们所有的配置信息定义在hibernate.cfg.xml。

org.hibernate.boot.Metadata 代表完成,其中SessionFactory将基于将基于领域模型部分验证应用程序的视图。

引导过程的最后一步是建立SessionFactory。SessionFactory 是线程安全的对象并且整个应用程序只实例化一次。

SessionFactory 作为org.hibernate.Session实例的一个工厂 ,这应该被认为是一个“工作单元”的必然结果。。
例5  保存实体
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save( new Event( "Our very first event!", new Date() ) );
session.save( new Event( "A follow up event", new Date() ) );
session.getTransaction().commit();
session.close();

testBasicUsage() 首先创建一些Event对象把他们交给Hibernate管理,使用 save()方法。 Hibernate现在负责为每个事件执行数据库上的插入操作。
例6  获取实体列表
session = sessionFactory.openSession();
session.beginTransaction();
List result = session.createQuery( "from Event" ).list();
for ( Event event : (List<Event>) result ) {
    System.out.println( "Event (" + event.getDate() + ") : " + event.getTitle() );
}
session.getTransaction().commit();
session.close();

在这里我们看到的一个例子,Hibernate使用查询语言(HQL)生成适当的 SELECT SQL从数据库中加载所有存在的Event对象,将它(HQL生成的SQL)发送到数据库,再把数据库返回的结果用来填充 Event对象。
2.5 更进一步!
练习练习

    重新配置示例连接到自己的持久化关系数据库。

    向Event实体添加关联 到一个消息的线程模型。

3 使用原生Hibernate api和注解映射教程
    本教程是位于下载包下 annotations/目录。
目标

    引导一个Hibernate SessionFactory

    使用注解来提供映射信息

    使用Hibernate的原生api

3.1 Hibernate配置文件

内容与Hibernate配置文件完全相同,有一个重要的区别使用class类的属性来命名注解实体类来替代<mapping/>元素。
3.2 带注解的Java类实体

本教程中的实体类是 org.hibernate.tutorial.annotations.Event 它遵循JavaBean约定。 事实上类本身是相同的都是Java实体类(The entity Java class),除了是用注解 来提供元数据,而不是用一个单独的映射文件来提供元数据。
例7 识别类作为一个实体
@Entity
@Table( name = "EVENTS" )
public class Event {
    ...
}
 @javax.persistence.Entity 注解是用来标记一个类作为一个实体。 它的功能和映射文件中讨论的<class/>元素一样。 此外, @javax.persistence.Table 注解显式地指定表名。没有这个规范,默认表名是EVENT。
示例8 识别标识符属性

@Id
@GeneratedValue(generator="increment")
@GenericGenerator(name="increment", strategy = "increment")
public Long getId() {
    return id;
}

@javax.persistence.Id 标志着属性,定义了实体的标识符。

@javax.persistence.GeneratedValue 和 @org.hibernate.annotations.GenericGenerator 在协同工作 表明Hibernate应该使用Hibernate的increment策略来生成此实体标识符的值。
示例9 确定基本性质
public String getTitle() {
    return title;
}

@Temporal(TemporalType.TIMESTAMP)
@Column(name = "EVENT_DATE")
public Date getDate() {
    return date;
}

就像在映射文件中 date 属性一样,因为考虑到date是SQL保留关键字所以需要进行特殊处理。

当用注解映射时默认实体的属性都是可以持久化的,这就是为什么我们没有看到任何与title相关的映射信息。
3.3 示例代码

org.hibernate.tutorial.annotations.AnnotationsIllustrationTest 和 org.hibernate.tutorial.hbm.NativeApiIllustrationTest 示例代码本质上讨论的是一样的。
3.4 更进一步!
练习练习

    添加一个关联 Event 实体到一个消息的线程模型。 使用 Developer Guide 作为指南。

    添加回调以接收通知 当一个Event创建、更新或删除的时候。尝试做到与事件监听器相同的功能。 使用 Developer Guide 作为一个指南。

4 使用Java Persistence API(JPA)教程
    本教程是位于下载包下 entitymanager/目录 。
目标

    引导一个JPA EntityManagerFactory

    使用注解来提供映射信息

    使用JPA API调用

4.1 persistence.xml

前面的教程使用Hibernate-特定的hibernate.cfg.xml 配置文件。 然而,JPA使用自己的配置文件 persistence.xml定义了一个不同的引导过程。这个引导过程是由JPA规范定义。 在Java™SE环境下持久化提供者(在这种情况下Hibernate) 需要在类路径下查找所有JPA配置文件,直到找到名为META-INF/persistence.xml的资源文件。
示例10 persistence.xml
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
        version="2.0">
    <persistence-unit name="org.hibernate.tutorial.jpa">
        ...
    </persistence-unit>
</persistence>

persistence.xml 文件应该为每个"persistence unit“(持久性单元)提供一个惟一名称。 应用程序使用此名称来参考配置信息 在得到一个javax.persistence.EntityManagerFactory 引用的时候。

定义在<properties/>元素中的设置相当于Hibernate配置文件中的设置。 在可能的时候javax.persistence 前缀种类会被使用。 请注意剩下的Hibernate-specific配置 setting names以Hibernate作为前缀  。

此外,<class/>元素功能和我们在Hibernate配置文件中看到的一样。
4.2 带注解的实体Java类

The entity is exactly the same as in The annotated entity Java class.
4.3 示例代码

前面的教程使用Hibernate原生api。 本教程使用JPA api。
例11。 获得javax.persistence.EntityManagerFactory

protected void setUp() throws Exception {
    sessionFactory = Persistence.createEntityManagerFactory( "org.hibernate.tutorial.jpa" );
}

再次注意,持久性单元名称 org.hibernate.tutorial.jpa ,匹配 persistence.xml 。
示例12。 存储(保存)实体
EntityManager entityManager = sessionFactory.createEntityManager();
entityManager.getTransaction().begin();
entityManager.persist( new Event( "Our very first event!", new Date() ) );
entityManager.persist( new Event( "A follow up event", new Date() ) );
entityManager.getTransaction().commit();
entityManager.close();

和Saving entities代码很类似。使用javax.persistence.EntityManager接口替换org.hibernate.Session 接口。 JPA称这个操作是“persist”而不是“save”。
示例13 获得一个实体列表
entityManager = sessionFactory.createEntityManager();
entityManager.getTransaction().begin();
List<Event> result = entityManager.createQuery( "from Event", Event.class ).getResultList();
for ( Event event : result ) {
    System.out.println( "Event (" + event.getDate() + ") : " + event.getTitle() );
}
entityManager.getTransaction().commit();
entityManager.close();
代码非常类似于我们在Obtaining a list of entities.所看到的。
4.4 更进一步!
练习练习

    开发一个EJB Session bean研究使用容器管理的持久化上下文的影响。尝试无状态和有状态的用例。

    使用基于CDI注入的侦听器开发基于JMS的事件消息中心

5 使用Envers教程
    本教程是位于下载包下 envers/目录 。
目标

    Annotate an entity as historical

    配置Envers

    使用Envers api来查看和分析历史数据

5.1 persistence.xml

这个文件是在JPA教程所讨论的persistence.xml,在这里基本上是相同的。
5.2 带注解的Java类实体

实体在很大程度上和带注解的Java类实体是一样的。主要的区别是 添加 @org.hibernate.envers.Audited 注解,它告诉配置Envers自动跟踪实体变化。
5.3 示例代码

代码可以保存一些实体,改变的一个实体,然后使用Envers API撤回到最初的修订或者更新修订。 修订是指一个实体的历史快照。
例14 使用 org.hibernate.envers.AuditReader
public void testBasicUsage() {
    ...
    AuditReader reader = AuditReaderFactory.get( entityManager );
    Event firstRevision = reader.find( Event.class, 2L, 1 );
    ...
    Event secondRevision = reader.find( Event.class, 2L, 2 );
    ...
}

我们看到一个 org.hibernate.envers.AuditReader是从org.hibernate.envers.AuditReaderFactory这包裹 javax.persistence.EntityManager得到的。

find 方法检索实体的特定修订。 第一个调用说找到修订号1,id为2的Event。 第二个调用说找到修订号2,id为2的Event。
5.4 更进一步!
实践练习

    另外提供一个自定义实体,捕捉谁做了更改。

    写一个符合某些标准的查询来检索历史数据。 使用User Guide来看Envers查询是如何构建地。

    对具有多种形式关系(多对一、多对多等)的审查实体进行实验。 试一试 检索这些实体的历史版本(修订)和 navigating the object tree。

上次更新2017-03-20 12:16:28 + 8

当前时间2017-03-23 11:07:29 + 8



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值