zoukankan      html  css  js  c++  java
  • [Hibernate] Hibernate 5.4 Getting Started Guide 官方入门文档

      前言

    最近的精力主要集中在Hibernate上,在意识到Hibernate 5 的中文资料并不多的时候,我不得不把目光转向Hibernate的官方doc,学习之余简要翻一下入门文档。

    原文地址:https://docs.jboss.org/hibernate/orm/5.4/quickstart/html_single/,勘误请在评论区留言

    原文序

    使用面向对象软件和关系型数据库可能既麻烦且耗时。开发成本往往会因数据在软件和数据库中的数据范式(paradigm)表现不一而显著地增长,Hibernate就是一种Java语言环境下的一个对象/关系映射 解决方案(ORM框架),对象/关系映射(ORM)的概念,则代指一种将数据的对象模型形式,即在软件中的表现形式,和数据模型形式,即数据库中的表现形式,这两种形式的数据相映射的技术。可以参照Wikipedia上的ORM词条以获得更详细的了解。

    虽然Hibernate并不要求用户需要有非常丰富的SQL编程经验,但是对于一些概念的基本理解着实可以让你更快更全面的理解Hibernate,特别是对数据建模原理的理解就显得尤为重要,这两篇文章可以帮助你快速开始理解这些原理dataModeling101 、DataModeling(wiki)

    Hibernate负责Java class和数据库表的映射工作,同时也会处理两者间数据格式的映射。另外,它还提供了数据查询和获取功能。它可以节省开发者原本需要的手动数据处理时间(如果你使用SQL和JDBC这些原生手段的话)Hibernate的设计目标是将开发者从95%的日常持久化编程步骤中解放出来,开发者再无需手册来通过SQL和JDBC手动处理数据。同时,不像其他持久化方案,Hibernate并不会将原生SQL的优点隐藏起来,你依旧可以使用它,意味着你之前所付出的学习和相关知识依然十分有价值。

    HIbernate可能不是那些以数据为中心的,重度依赖存储过程的应用的最佳解决方案。它更适合于对于数据相关的应用中间层,这种情况下,它的确可以去除掉那些针对特定数据库而写的SQL,流水化查询的数据集转译到对象表(对于编程语言而言)。

    See http://hibernate.org/orm/contribute/ for information on getting involved.

    本文章中涉及的项目代码可以从这里下载: hibernate-tutorials.zip

      

    1. 获取 Hibernate

    1.1. Hibernate Modules/Artifacts

    Hibernate’s 的功能被分成一些不同的 modules/artifacts 用来隔离依赖关系(模块化).

    hibernate-core

    Hibernate 核心module. 定义了ORM功能和API,还有不同的集成SPIs(方便第三方进行自定义扩展).

    hibernate-envers

    Hibernate历史实体版本控制功能

    hibernate-spatial

    Hibernate空间数据集和GIS(地理信息系统)数据类型支持

    hibernate-osgi

    Hibernate对在OSGi容器中运行的支持。

    hibernate-agroal

    Hibernate Agroal 连接池支持

    hibernate-c3p0

    Hibernate  C3P0 连接池支持

    hibernate-hikaricp

    Hibernate  HikariCP 连接池支持

    hibernate-vibur

    Hibernate  Vibur DBCP 连接池支持

    hibernate-proxool

    Hibernate  Proxool 连接池支持

    hibernate-jcache

    Hibernate JCache 缓存支持 , 使得任何兼容的组件成为二级缓存的提供者。

    hibernate-ehcache

    Hibernate Ehcache 缓存支持。使得Ehache成为二级缓存提供者。

     1.2. 发行包下载

    Hibernate发行包存放在 SourceForge File Release System, 有 TGZ 和 ZIP 两种格式,两种都包含了JAR文件、文档、源代码和其他一些东西。

    你可以从这里下载:https://sourceforge.net/projects/hibernate/files/hibernate-orm/. 以下是发行包目录结构:

    • lib/required/ 目录包含 hibernate-core jar包和它的依赖。所有的jar包都需要在在classpath下,不论那些功能有没有被用到。

    • lib/envers 目录包含 hibernate-envers jar包和它的依赖 (先包含lib/required/ 和 lib/jpa/).

    • lib/spatial/ 目录包含 hibernate-spatial jar包和它的依赖 (先包含 lib/required/)

    • lib/osgi/ 目录包含 hibernate-osgi jar包和它的依赖 (先包含 lib/required/ 和lib/jpa/)

    • lib/jpa-metamodel-generator/ 目录包含 生成Criteria API类型安全的元模型(Criteria API type-safe Metamodel)所需的jar。

    • lib/optional/ 目录包含 Hibernate提供的各种连接池和第二级缓存集成所需的jar及其依赖。

    1.3. Maven Repository Artifacts

    Hibernate artifacts的权威仓库为the JBoss Maven repository. Hibernate artifacts会自动同步到这上面(可能会延迟发布).

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

    Hibernate ORM artifacts发布在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_classconnection.urlconnection.username 和connection.password <property/> 元素定义了JDBC连接信息这些示例使用内置的H2 in-memory 数据库,所以所有的属性被设置成H2数据库以在内存中运行connection.pool_size 用来配置内置连接池的大小。

      内置的Hibernate连接池并不能用于实际应用中,对比实际应用中的的连接池它缺乏一些基本功能

    dialect元素定义了Hibernate会使用的特定SQL类型

      绝大多数情况下, Hibernate 能够自动选择数据库的方言(dialect),当你使用多种数据库时这点尤其有用(注:3.x版本不清楚)

    hbm2ddl.auto 属性开启自动生成数据库schema,也即自动建表功能。

    最后,添加映射文件到配置文件中, 位于 <mapping/> 元素中的resource 使得Hibernate会尝试去使用用java.lang.ClassLoader 在classpath下进行查找。

    有许多方式可以用于启动SessionFactory,详见the Native Bootstrapping topical guide. 

    2.2. Java类

    本示例中的实体类为示例代码中的: org.hibernate.tutorial.hbm.Event

    关于实体类:
    • 实体类使用标准JavaBean的命名规范,包括getter/setter和私有的变量,虽然这是推荐的用法,但并不强制

    • 无参构造函数,同样作为JavaBean的规范,则要求必须实现,Hibernate需要通过反射机制(Java Reflection)为你创建实体类(即查询结果时),构造函数不能是私有的,同时,包可见性也要保证,这样才能通过java运行时代理机制(runtime proxy)生成以保证无需通过 字节码检测(bytecode instrumentation)进行代理。

    2.3. 映射文件

    本示例中的映射文件位于 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中映射的表甚至不需要定义主键。但是,强烈建议所有schema都定义适当的参照完整性。如此一来,id和主键在整个Hibernate中可以互换使用 。

    此处的<id/> 元素将EVENT_ID列命名为EVENTS表的主键。它还将Event类的id属性标识为包含标识符值的属性。

     generator 元素通知Hibernate使用哪种策略为该实体生成主键值。本示例使用简单的递增计数。(注,在其他相关性能调优指南文章中,有提及不要使用id生成器,会那样会阻止批量插入)

    示例 3. 属性映射元素
    <property name="date" type="timestamp" column="EVENT_DATE"/>
    <property name="title"/>

    这两个 <property/>元素声明了Event 类的其余两个持久属性:date 和title 。date 属性映射包括列属性,但title 不包含。在没有列属性的情况下,Hibernate默认使用属性名称作为列名称。这适用于title,但是由于date 是大多数数据库中的保留关键字,因此您需要为列名指定一个非保留字。 

    title映射也缺少类型属性。映射文件中声明和使用的类型既不是Java原生数据类型也不是SQL数据库类型。相反,它们是Hibernate映射类型,它们是在Java和SQL数据类型之间转换的转换器。如果未在映射中指定type属性,则Hibernate尝试自动确定正确的转换和映射类型,方法是使用Java反射来确定已声明属性的Java类型,并使用该Java类型的默认映射类型(注:如,BigInteger->Integer)。

    在某些情况下,如date 属性所示,此自动检测可能未选择您期望或需要的默认值。 Hibernate无法知道类型为java.util.Date的属性是否应映射到SQL DATE,TIME或TIMESTAMP数据类型。通过将属性映射到timestamp转换器(timestamp converter)来保存完整的日期和时间信息,该转换器标识转换器类org.hibernate.type.TimestampType

      处理映射文件时,Hibernate使用反射来确定映射类型。此过程增加了时间和资源方面的开销。如果启动性能( startup performance)很重要,请考虑明确定义要使用的类型。

     

    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!
        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
            // so destroy it manually.
            StandardServiceRegistryBuilder.destroy( registry );
        }
    } 

    setUp方法首先创建org.hibernate.boot.registry.StandardServiceRegistry实例,该实例将配置信息合并到服务(Services,有特指)的工作集中以供SessionFactory使用。在本教程中,我们在hibernate.cfg.xml中定义了所有配置信息。

    使用StandardServiceRegistry我们创建org.hibernate.boot.MetadataSources,这是向Hibernate告知您的Domain模型的起点。再一次,因为我们在hibernate.cfg.xml中定义了它,所以这边没什么东西好讲的。 org.hibernate.boot.Metadata表示SessionFactory将基于的应用程序域模型的完整,部分验证的视图。

    引导程序的最后一步是构建SessionFactory。 SessionFactory是一个线程安全的对象,实例化一次即可服务整个应用程序。

    SessionFactory充当org.hibernate.Session实例的工厂,应将其视为“工作单元”的必然(corollary )结果。

    示例 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() 首先使用save() 方法创建一些新的Event对象并将其交给Hibernate进行管理。 Hibernate现在负责为每个Event在数据库上执行INSERT。 

    示例 6. 获取List结果集
    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对象来从数据库加载所有现有的Event对象。

    2.5. 下一步!

    练习
    • 重新配置示例以连接到您自己的持久关系数据库。 

    •  Add an association to the Event entity to model a message thread.

    3. 使用 Hibernate 原生API 和 注解式映射

      本示例位于您下载的压缩包中的 annotations/.
     
     
    目标:
    • 启动 Hibernate SessionFactory

    • 使用 Java注解来提供映射信息

    • 使用Hibernate原生API

    3.1. Hibernate配置文件

    内容与上文的Hibernate配置文件相同,但有一个重要区别...最后的<mapping />元素使用class属性命名带注释的实体类。

    3.2. 注解的Java类

    本示例中的实体类是遵循JavaBean约定的org.hibernate.tutorial.annotations.Event。实际上,该类本身与实体Java类中的类相同,只不过注释用于提供元数据而不是单独的映射文件。

    示例7.将类标识为实体
    @Entity
    @Table( name = "EVENTS" )
    public class Event {
        ...
    }

     @ javax.persistence.Entity注释用于将类标记为实体。它的功能与映射文件中讨论的<class />映射元素相同。此外,@ javax.persistence.Table注释显式指定了表名。如果没有此规范,默认表名称将为EVENT。

    示例8. 标记id属性

    @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的增量生成策略。

    示例9. 标记基本属性
    public String getTitle() {
        return title;
    }
    
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "EVENT_DATE")
    public Date getDate() {
        return date;
    }

    与映射文件中一样,日期属性需要进行特殊处理以考虑其特殊命名和SQL类型。 带有注释的映射默认情况下将实体的属性视为持久化属性(与数据库字段相同),这就是为什么我们看不到任何与title相关的映射信息的原因。 

    3.3. 示例代码

    org.hibernate.tutorial.annotations.AnnotationsIllustrationTest本质上与示例代码中讨论的org.hibernate.tutorial.hbm.NativeApiIllustrationTest相同。

    3.4. 下一步!

    练习
    • 向事件实体添加关联以对消息线程进行建模。有关更多详细信息,请使用《用户指南》。 

    • 添加回调以在创建,更新或删除事件时接收通知。使用事件监听器尝试相同的操作。有关更多详细信息,请使用《用户指南》。

    4. 使用 Java Persistence API (JPA)

      本示例位于您下载的压缩包中的 entitymanager/.
     
     
    目标:
    • 启动JPA EntityManagerFactory 

    • 使用 Java注解来提供映射信息

    • 使用JPA API 

    4.1. persistence.xml

    之前的教程使用了特定于Hibernate的hibernate.cfg.xml配置文件。但是,JPA定义了一个不同的引导过程,该过程使用其自己的名为persistence.xml的配置文件。该引导过程由JPA规范定义。在Java SE环境中,需要持久性提供程序(在这种情况下为Hibernate)通过META-INF / persistence.xml资源名称的类路径查找来定位所有JPA配置文件。

    示例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文件应为每个“持久性单元”提供唯一的名称。在获取javax.persistence.EntityManagerFactory引用时,应用程序使用此名称来引用配置。

    Hibernate配置文件中讨论了<properties />元素中定义的设置。这里尽可能使用javax.persistence前缀的变体。请注意,其余特定于Hibernate的配置设置名称现在以hibernate前缀。

    此外,<class />元素的功能与我们在Hibernate配置文件中看到的相同。

    4.2. 注解的Java类

    实体与上节注解的的Java类中的完全相同。

    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();

    该代码类似于上文的保存实体类。使用javax.persistence.EntityManager接口代替org.hibernate.Session接口。 JPA将此操作称为“持久化”(persistence)而不是“保存”(save)。

    示例13. 获取List结果集
    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();

    同样,该代码与我们在获取上文的 获取List结果集看到的非常相似。

    4.4. 下一步!

    练习
    • 开发一个EJB Session bean来研究使用容器管理的持久性上下文的含义。尝试无状态(stateless )和有状态(stateful )两种情况。 

    • 将事件监听器(listeners)与基于CDI的注入(CDI-based injection)结合使用,以开发基于JMS的事件消息中心 

    5. 使用 Envers

      本示例位于您下载的压缩包中的 envers/.
     
     
    目标
    • 将实体注释为历史对象
    •  配置 Envers

    • 使用Envers API查看和分析历史数据

    5.1. persistence.xml

    这个文件在JPA 示例中已提过 persistence.xml, 而且基本是一样的

    5.2. 注解的Java类

    同样,该实体与上文:注释的Java类中的相同。主要区别在于添加了@ org.hibernate.envers.Audted注释,该注释告诉Envers自动跟踪对此实体的更改。

    5.3. 示例代码

    该代码保存了一些实体,对其中一个实体进行了更改,然后使用Envers API来查询初始修订(revision)以及更新的修订。修订是指实体的历史快照(snapshot )。

    示例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.AuditReaderFactory获得了一个org.hibernate.envers.AuditReader,它包装了javax.persistence.EntityManager。 

    接下来,find 方法检索实体的特定修订版。第一次调用找到ID为2的事件的修订版本1。第二次调用找到ID为2的事件的修订版本2。

    5.4.下一步!

    练习
    • 提供自定义修订版本实体,以额外获取进行更改的人员。 

    •  写一个只取回符合条件历史数据的查询。 使用 User Guide 查看 Envers 查询如何创建。(Envers用于在自动生成记录更改信息的数据表,用于审计)

    • 尝试使用具有各种关系(多对一,多对多等)的审计实体(auditing entities)。尝试查找此类实体的历史版本(修订版)并浏览对象树。
  • 相关阅读:
    CSP2019滚粗记
    [总结] wqs二分学习笔记
    [总结] 圆方树学习笔记
    [CF960G] Bandit Blues
    [总结] 第一类斯特林数
    [EOJ629] 两开花
    [CF286E] Ladies' shop
    [总结] 动态DP学习笔记
    [BZOJ3879] SvT
    [总结] 替罪羊树学习笔记
  • 原文地址:https://www.cnblogs.com/easy-tech/p/11462593.html
Copyright © 2011-2022 走看看