• Hibernate —— Entity.hbm.xml


    一、简述

    1.对象关系映射文件,用于映射实体类和关系数据库数据表之间的一个 xml 文件。

    2.通过 Entity.hbm.xml 映射文件,Hibernate 可以理解持久化类和数据表之间的对应关系,也可以理解持久化类属性与数据表列之间的对应关系。

    3.映射主键、映射关联关系。

    二、各个节点

    <hibernate-mapping>
        <class>
            <id></id>
            <property name=""></property>
            <many-to-one name=""></many-to-one>
            <one-to-one name=""></one-to-one>
            <set name="">
                <key></key>
                <one-to-many></one-to-many>
                <many-to-many></many-to-many>
            </set>
            <subclass></subclass>
            <joined-subclass>
                <key></key>
            </joined-subclass>
            <component name=""></component>
            <any id-type="" name="">
                <column name=""></column>
                <column name=""></column>
            </any>
        </class>
    </hibernate-mapping>

    说明:在一个 Entity.hbm.xml 可以定义多个 class 节点,但是通常情况下只定义一个。

    1.<hibernate-mapping>

    (1)package

    如果 hibernate-mapping 节点内存在多个 class 节点,可以通过这个属性来简化开发。相当于一个命名空间。

    单个 class 节点的情况下:

    <hibernate-mapping >
        <class name="com.nucsoft.hibernate.News" table="news" schema="hibernate">
        </class>
    </hibernate-mapping>

    多个 class 节点的情况下:

    <hibernate-mapping package="com.nucsoft.hibernate">
        <class name="News" table="news" schema="hibernate">
        </class>
        <class name="Users" table="users" schema="hibernate">
        </class>
    </hibernate-mapping>

    2.<class>

    (1)name:类名,如 com.nucsoft.hibernate.News。

    (2)table:表明,如 news。类名和表名不一定一致。

    (3)schema:库名。如 hibernate 。

    (4)dynamic-insert:动态插入。默认为 false。若设置为 true,表示当插入一个对象时,会动态生成 insert 语句,insert 语句仅包含所有取值不为 null 的字段。

    ①默认

    @Test
    public void testDynamicInsert() {
        News news = new News("bb", null, new java.util.Date());
        session.save(news);
    }

    控制台打印:

    Hibernate: 
        insert 
        into
            hibernate.news
            (title, author, date) 
        values
            (?, ?, ?)

    ②设置 dynamic-insert="true" 

    @Test
    public void testDynamicInsert() {
        News news = new News("cc", null, new java.util.Date());
        session.save(news);
    }

    控制台打印:

    Hibernate: 
        insert 
        into
            hibernate.news
            (title, date) 
        values
            (?, ?)

    注意:设置为 null 的字段不存在 非空约束。

    (5)dynamic-update:动态更新。默认为 false。若设置为 true,表示当更新一个对象时,会动态生成 update 语句,update 语句中仅包含所有取值需要更新的字段。

    ①默认

    @Test
    public void testDynamicUpdate() {
        News  news = (News) session.get(News.class, 205);
        news.setAuthor("BB");
    }

    控制台打印:

    Hibernate: 
        update
            hibernate.news 
        set
            title=?,
            author=?,
            date=? 
        where
            id=?

    ②设置 dynamic-update="true"

    @Test
    public void testDynamicUpdate() {
        News  news = (News) session.get(News.class, 206);
        news.setAuthor("CC");
    }

    控制台打印:

    Hibernate: 
        update
            hibernate.news 
        set
            author=? 
        where
            id=? 

    (6)select-before-update:设置某个持久化对象在更新前是否执行一次查询。如,对一个游离对象的更新,再更新前先查询使游离对象变为持久化对象,

    若该对象和数据库中对应记录状态一致,则不再发送 UPDATE 语句。但是会影响性能。

    3.<id>

    说明:

    • Hibernate 通过 OID 来建立内存中的对象和数据表中记录的对应关系。对象的 OID 和数据表的主键对应。Hibernate 通过标识符生成器来为主键赋值。
    • Hibernate 推荐在数据表中使用代理主键,即不具备任何业务含义的字段。代理主键通常为整型。
    • <id> 节点用来设置对象标识符,<generator> 子元素用来设定标识符生成器。Hibernate 提供了标识符生成器接口:IdentifierGenerator,提供了内置的实现,我们也可以通过实现这个接口来定义我们自己的生成器。

    (1)name:持久化类的属性名。

    (2)column:对应数据表的列名。

    (3)type:Hibernate 的映射类型。

    (4)unsaved-value:如果存在一个对象的 id 和 unsaved-value 值相同,会被认为成一个临时对象。

    (4)子节点:<generator>。为持久化类设定标识符生成器。

    • class 属性,生成器的全限定类名或缩写。一般使用缩写。

    • increment:会存在并发问题,会出现主键重复。只适用于测试。
    • hilo:在Hibernate 4.2.2 版本中,已过时。org.hibernate.id.enhanced.SequenceStyleGenerator 替代了它。

    4.<property>

    (1)name:指定该持久化类的属性名称。

    (2)type:Hibernate 映射类型。(Hibernate 映射类型,是 Java 类型和 SQL 类型的桥梁)

    (3)column:指定映射的表的字段名,可以定义为子节点的形式。

    (4)access:指定 Hibernate 的默认的属性访问策略。默认为 property,即使用 getter/setter。若指定 field,则通过反射来访问成员变量。

    (5)unique:是否添加一个唯一约束。

    (6)update:这一列的值是否可以被修改。

    (7)index:指定一个索引名称。

    (8)scale:指定该属性所映射数据列的小数位。对 double/float/decimal 等有效。

    (9)formula:设置一个 Sql 表达式,Hibernate 将根据它来计算出派生属性的值。

    注意:

    • 派生属性:并不是持久化类的所有属性都直接和表的字段匹配,持久化类的有些属性的值必须在运行时才能计算出来。
    • formula="(sql)" 括号不能少。
    • sql 语句中的列名和表名应与数据库中的列名和表名对应,而不是和持久化类名和属性名对应。

    e:在 News 中添加了 String 类型的 desc 字段。

    News.hbm.xml 配置:

    <property name="desc" formula="(SELECT concat(title, ': ', author) FROM news n WHERE n.id = id)"/>

    测试:

    @Test
    public void testFormula() {
        News news = (News) session.get(News.class, 1);
        System.out.println(news.getDesc());
    }

    控制台打印:

    Hibernate: 
        select
            news0_.id as id1_0_0_,
            news0_.title as title2_0_0_,
            news0_.author as author3_0_0_,
            news0_.date as date4_0_0_,
            (SELECT
                concat(news0_.title,
                ': ',
                news0_.author) 
            FROM
                news n 
            WHERE
                n.id = news0_.id) as formula0_0_ 
        from
            hibernate.news news0_ 
        where
            news0_.id=?
    dd: DD

    可以发现,是以子查询的方式来设置派生属性的。

    三、映射时间、日期类型

    1.基础知识

    (1)在 Java 中,代表日期和时间的类型有:java.util.Date 和 java.util.Calendar。此外,JDBC 提供了 3 个扩展:java.sql.Date、java.sql.Time、java.sql.Timestamp。

    分别和标准 SQL 的 date 、time、timestamp 类型对应。

    (2)在标准 SQL 中,DATE 类型表示日期,TIME 类型表示时间,TIMESTAMP 类型表示时间戳,同时包含日期和时间信息。

    (3)因为 java.util.Date 是 java.sql.Date,java.sql.Time 和 java.sql.Timestamp 的父类,所以 java.util.Date 可以对应标准 SQL 的Date、Time、Timestamp 类型。

    基于上述所说,可以将实体类的 Date 类型设置为 java.util.Date 类型。

    (4)如何将 java.util.Date 映射为 Date,Time,Timestamp?

    ①在 Eclipse 下,是根据实体和映射文件去生成数据表。

    可以通过 property 的 type 属性来进行映射。

    例如:

    <property name="date" type="timestamp">
        <column name="DATE" />
    </property>
    
    <property name="date" type="data">
        <column name="DATE" />
    </property>
    
    <property name="date" type="time">
        <column name="DATE" />
    </property>

    其中 timestamp, date, time 既不是 Java 类型, 也不是标准 SQL 类型, 而是 hibernate 映射类型。

    ②在 Intellij Idea 下,是根据表去生成 Entity.hbm.xml 和实体类。

    生成的实体日期类型为具体的 java.sql.date 或 java.sql.time 或 java.sql.timestamp。

    这里需要对其更改为其父类:java.util.date。

    经过测试发现,对应 property 的 type 属性写与不写都不会影响最终结果。如:

    <property name="birthday">
        <column name="birthday" sql-type="timestamp"/>
    </property>

    插入的结果也是带有日期和时间的时间戳。

    ③小结:在 Eclipse 下,必须要显式的指定 property 的 type 属性,来进行日期时间的精确映射。而在 Intellij Idea 下,需要将实体类的日期和时间类型改为 java.util.Date 类型。

    (5)Java 类型、Hibernate 类型、标准 SQL 类型对应表

    四、关于 Blob,Clob 这里不进行说明。在项目中处理二进制和大数据类型的对象很少通过 Blob和 Clob进行存储。

    五、总结

    介绍了实体类和数据表是如何映射的,主键是怎么生成的,是怎么映射的,属性和列是怎么映射的。也介绍了日期时间的映射。

  • 相关阅读:
    Python Xcode搭建Python环境以及使用PyCharm CE
    Python 集体智慧编程PDF
    Swift tableview自带的刷新控件
    iOS 类似朋友圈的图片浏览器SDPhotoBrowser
    程序员应掌握的算法
    C++ 知识点总结复习
    iOS 图片的拉伸,取固定区域显示
    iOS 获取一个不变的UDID
    iOS 应用中加载文档pdf/word/txt
    LeetCode-Design Snake Game
  • 原文地址:https://www.cnblogs.com/solverpeng/p/5945896.html
Copyright © 2020-2023  润新知