Hibernate框架学习之三:深入映射文件的配置

前言

这里主要是对XML版的Hibernate框架的开发进行说明,Annotation版会在另外的文章中在说明。由于Hibernate是一个全方位的ORM框架,那么要实现从Object到Record的完全过渡,实现的桥梁就是这里要讲的映射文件了。映射文件的内容繁多,主要是以开发中会使用到的为主进行说明。大体说来,映射文件主要是对class的映射,还包括属性,属性有分为主键、普通属性与集合属性,甚至还有复合类型等。每种属性都需要进行不同的配置,官方文档看得有点累,所以这里一并做一个总结。



映射文件一览

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="bean">
    <class name="Address">
    ...
    </class>
</hibernate-mapping>

以上就是映射文件的大体结构,package指定持久化类所在包,class指定具体包下的实体类,name属性指定类的名字(必须与实际的类名一致)。在class内部可以配置主键、普通属性、集合属性和复合类型,以下就对这几种类型的配置进行叙述。



主键

主键就是持久化类中标识属性,用于唯一标识这个对象,在映射文件中需要通过<id.../>元素为主键进行设置。在id标签的内部可以使用以下三个常用属性属性:namecolumntypename属性与持久化类中标识属性的名称是一致的,column指定在数据库中主键对应的列名。type属性指定主键的数据类型,这里需要注意的有两点:1,type属性指定的数据类型必须是数据库所支持的数据类型(不过Hibernate已经常用的8中基本数据类型提供类型识别,能够与数据库中的数据类型对上号);2,column属性与type属性都不是必须的,name属性则是必须要指定的。

在日常的开发中,对于主键的使用往往是以逻辑主键为主的,而很少使用物理主键。逻辑主键的意思就是没有任何实际意义的主键,物理主键就是有实际意义的主键。使用逻辑主键的原因在于在进行外键关联的时候能够自动关联,而不需要添加额外的配置;此外,使用物理主键会增加维护的难度(比如在多级关联的时候)。

使用主键必然会涉及到主键生成策略,Hibernate中提供以下几种主键策略:

  • increment:为int、long和short类型生成唯一标识,但是只能在只有一个进程往数据库表中插入数据的时候才能使用,在集群的情况不要使用
  • identity:主要是针对类似Mysql等有自增主键的数据库使用
  • sequence:主要是针对需要使用序列才能使用主键的数据库使用,比如oracle
  • uuid:使用128位的UUID算法生成字符串类型的唯一标识,这个标识在网络中是唯一的。
  • hilo:使用高/低位算法高效生成的long、int或者short类型的唯一标识
  • native:根据底层数据库选择identity、sequence和hilo中的一种

以上主键生成策略是使用比较多的,还有guid、select等策略,感兴趣的可以研究下官方文档。



普通属性

映射普通属性需要使用<property.../>标签完成。该标签必须制定name属性,标识持久化类的属性名称。除了name属性,还可以配置以下常用属性:

  • type:类型,标识属性名称的类型
  • column:指定在数据库中列名
  • not-null:表明是否可以为空,true表示不能为空
  • formula:该属性可以指定SQL表达式,该属性的值是根据表达生成的,但是在数据库中并没有该column
  • lazy:表示是否需要延迟加载,默认为false,表示在实例属性被访问的立即被加载
  • generated:设置该属性映射的数据库列是否由数据库生成,可以选择never(表示不由数据库生成)、always(表示在执行insert和update的时候生成)、insert(在执行insert操作的时候生成)。

以上就是比较常用的属性配置了,下面是对formula属性的一个例子:

package bean;

public class News {

    private Integer id;
    private String title;
    private String content;
    private String fullcontent;
    //省略set和get方法
}

下面是News.hbm.xml的配置:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="bean">
    <!-- 为News类设置一个持久化类 -->
    <class name="News">
        <!-- 设置News的对象标识属性 -->
        <id name="id">
            <!-- 主键生成策略 -->
            <generator class="native" />
        </id>
        <!-- 普通属性 -->
        <property name="title" not-null="true"/>
        <property name="content" not-null="true"/>
        <property name="fullcontent" column="fullcontent" type="string" formula="(select concat(nt.title,nt.content) from news nt where nt.id=id)"/>
    </class>

</hibernate-mapping>

测试程序:

@Test
    public void testNews(){
        Session session = HibernateUtil.getSessionFactory(1).getCurrentSession();
        session.beginTransaction();

//      News news = new News();
//      news.setTitle("MongoDB教程");
//      news.setContent("8天学同MongoDB系列之CRUD操作");
//      session.save(news);

        News n = (News) session.get(News.class, 1);
        //这里了并没有设置fullcontent的属性,但是仍然调用get方法,看看会输出什么
        System.out.println(n.getFullcontent());
        session.getTransaction().commit();
    }

可以在控制台中看到fullcontent是内容title和content属性拼接起来的字符串。有一点的需要注意的是,formula属性sql语句必须使用小括号括起来。其他的普通属性已经在第一篇文章中使用过,这里不再重复。



集合属性

集合属性就包括List、Set、数组和Map四种,下面分别对这四种集合属性的配置进行叙述:
以下的持久化类都以下面的类为模板:

package bean;
public class Person2 {

    private Integer id;
    private String name;
    private Integer age;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public Integer getAge() {
        return age;
    }
}

List
在上面Person2类中添加List<String> schools属性,并添加set和get方法(后面不再重复)。Person2.hbm.xml配置文件如下:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="bean">

    <class name="Person2" table="person2">
        <id name="id">
            <generator class="native" />
        </id>
        <property name="name" type="string"></property>
        <property name="age" type="integer"></property>
        </class>
        <list name="schools" table="school">
            <!-- 映射集合属性的外键列 ,这里之所以需要制定notnull属性,是因为在Hibernate中外键列的默认值是false-->
            <key column="personid" not-null="true"></key>
            <!-- 映射集合索引列,这里没有指定type属性的原因在于Hibernate直到其属性的值是int类型 -->
            <list-index column="list_index"></list-index>
            <!-- 映射需要保存的数据列 -->
            <element column="school_name" type="string"></element>
        </list>
</hibernate-mapping>

需要说明的在list标签中需要添加list-index标签,主要是List集合的索引列(从0开始)。

数组
把Person2类中schools属性改成数组类型,修改配置文件如下:

<array name="schools" table="school">
            <key column="personid" not-null="true"></key>
            <list-index column="list_index"></list-index>
            <element column="school_name" type="string"></element>
        </array>

可以看到,使用数组仅仅把标签改成array而已。因为数组本质上也是元素列表。

Set
修改schools类型为Set类型,修改配置文件如下:

<set name="schools" table="school">
            <key column="person_id" not-null="true"></key>
            <element column="school_name" type="string" not-null="true"></element>
        </set>

在使用Set的时候,并没有list-index标签,而是在element标签中多添加not-null属性,并设置为true。这样做的结果是,Set类型的schools属性将使用person_id和school_name作为联合主键。如果不添加这个属性,那么主键是空的,会抛FieldNotFoundException异常。

Map
添加Map<String,Float> scores属性,修改配置文件如下:

<map name="scores" table="score">
            <key column="person_id" not-null="true"></key>
            <map-key column="subject" type="string"></map-key>
            <element column="grade" type="float" not-null="true"></element>
        </map>

有序集合
在有些时候,有序集合也可能需要使用到,首先需要添加SortedSet<String> names属性。修改配置文件如下:

<set name="names" table="name" sort="natural">
            <key column="person_id" not-null="true"></key>
            <element column="nickname" not-null="true" type="string"></element>
        </set>

可以看到,与Set(Set是无序无重复的集合)不同的地方在于,多了sort属性,这里使用natural排序策略,表示element的排序使用字母排序的规则进行排序。

组件(复合类型)
比如在Person2类型添加Address2属性,由于Address2也是一个持久化类,所以在数据库中是无法存储的,这里就需要使用组件的配置了。首先需要创建Address2类,如下:

package bean;

import java.util.Map;

public class Address2 {

    private int id;
    private String province;
    private String city;

    private Person2 owner;
    //省略set和get方法
}

修改配置文件如下:

<component name="address" class="Address2" unique="true">
            <!-- 指定owner属性代表容器实体 -->
            <parent name="owner"/>
            <property name="province"></property>
            <property name="city"></property>
            <!-- 添加集合属性 -->
            <map name="power" table="address_power">
                <!-- 外键 -->
                <key column="person_address_id" not-null="true"></key>
                <!-- 映射map的key -->
                <map-key column="address_aspect" type="string"></map-key>
                <!-- 映射map的value -->
                <element column="address_power" type="integer"></element>
            </map>
        </component>

组件为集合
在Person2类中添加属性Map<String,Address2> adds
修改配置文件如下:

<map name="adds" table="adds_inf">
            <!-- 外键 -->
            <key column="person_id" not-null="true"></key>
            <!-- key -->
            <map-key type="string" column="phrase"></map-key>
            <composite-element class="Address2">
                <parent name="owner"/>
                <property name="province" type="string"></property>
                <property name="city" type="string"></property>
            </composite-element>
        </map> 

注意到当组件是集合的时候,需要使用composite-element标签。

以上就是对各种属性类型配置文件的详细配置与叙述,当然使用注解会非常简单,后面还会提到。

时间: 2024-10-31 08:05:00

Hibernate框架学习之三:深入映射文件的配置的相关文章

Java的Hibernate框架中的继承映射学习教程_java

一.继承映射继承是面向对象很重要的特性,它实现了代码的服用,在关系模型中同样也有继承关系,这种继承关系其实可以看做是一种枚举关系,一种类型中可以枚举出很多子类型,这些子类型和父对象形成了继承关系,能够对其进行枚举的大部分都可以看做是一种继承映射,所以这种枚举关系可以看做是继承映射,例如动物就是一种抽象类,它是其它动物猪.猫等的父类,它们之间就是一种继承关系,如下图: 这种继承映射在转化为关系模型后会生成一张表,那么这张表是如何区分这两种类型的呢?用的是关系字段,需要在表中添加类型字段,使用关键字

Java的Hibernate框架中的组合映射学习教程_java

一.组合映射组合是关联关系的一种特殊情况,是关联关系耦合度最高的一种关系,组合的主对象和子对象拥有相同的生命周期,主对像消亡的话子对象也会消亡.这里使用雇主和用户作为示例,用户和雇主都拥有联系方式属性,如果这里站在对象角度思考的话,常常会把对象模型绘制成为组合的方式,抽象出来一个共同的联系方式类,然后两种人分别包含相应的联系方式对象即可,向应的对象模型时它的对象示例如下图所示: 组合对象模型在生成相应的关系模型后会把对应的子类包含到主表中,所以对应的表结构会将相应的属性生成到对应的表中,相应的表

Hibernate框架学习之一:Hello World程序

前言 对一个框架的直观认识,往往是从一个Hello World程序开始.Hibernate是一个ORM(Object Relationship Mapping)对象映射框架.实现了JDBC轻量级的封装,使得在进行JDBC开发的时候可以直接使用面向对象的思维进行开发,说白了Hibernate框架的作用是在Java对象与关系数据库中做了一个映射,使得程序员不用再使用各种SQL了.所以总结Hibernate以下几点: 1.完成了对JDBC的封装,不用再与各种Connection打交道了 2.在业务体系

详解Java的Hibernate框架中的set映射集与SortedSet映射_java

Set集合Set是一个java集合不包含任何重复的元素.更正式地说,Set不包含任何元素对e1和e2,使得e1.equals(e2),和至多一个空元素.所以被添加到一组对象必须实现equals()和hashCode()方法,使Java可以判断任何两个元素/对象是否是相同的. 集被映射到与映射表中<set>元素,并在java.util.HashSet中初始化.可以使用Set集合在类时,有一个集合中不需要重复的元素. 定义RDBMS表: 考虑一个情况下,我们需要我们的员工记录存储在EMPLOYEE

Java的Hibernate框架中的基本映射用法讲解_java

Hibernate进行了分类整合发现其实Hibernate分为三大部分:核心对象.映射.HQL,这三大部分开发过程中最常使用,前几篇讨论了核心对象及对象之间的转换方法,接下来讨论Hibernate的映射使用方法.   Hibernate一个重要的功能就是映射,它能够在对象模型和关系模型之间转换,是面向对象编程思想提倡使用的,使用映射程序开发人员只需要关心对象模型中代码的编写.对象和关系数据库之间的映射通常是由XML文档来定义的.这个映射文档被设计为易读的,并且可以手动修改.这种映射关系我总结为下

Hibernate框架学习之二:深入理解持久化对象

前言 由于Hibernate框架是一个完全的ORM框架,所以在Hibernate开发中只涉及具体的对象与属性,所以对象在Hibernate中是很重要的方面.而持久化对象则与数据库中的记录息息相关了,可以简单把持久化类理解为普通的JavaBean,也被称为POJO(Plain Old Java Object),在Hibernate3中,持久化类的定义与普通JavaBean的定义基本一致,而不需要额外实现其他接口或者继承某个类. 但是使用要想是一个普通的POJO与数据库对应起来还需要映射的配置(这点

Hibernate框架学习之四:关联映射那些事

前言 Hibernate关联关系与客观世界中具体的映射关系很类似,在进行数据库设计的时候常常需要考虑是一对多.多对一等类似的映射关系,这其中涉及数据库设计方面的知识.映射关系可以分为单向与双向两种,具体又包括一对多.多对一.一对一以及多对多四种.所以总共有八种映射关系.这里只介绍了XML配置文件的版本. 下面的配置文件的配置方式都以下面的两个持久化类作为模板: public class Person { private int id; private String name; private i

Struts2框架学习之三:result返回结果

前言 Struts 2中的Result是作为返回结果的,时当一个action处理完之后返回字符串的结果码.框架可以根据这个返回的字符串,映射到指定的页面.result元素可以分为两部分:一是结果映射,一部分是返回结果类型. 结果映射 result有两个属性可以配置:name属性和type属性.其中的name属性主要用来指定资源的逻辑名称,实际名称在标签内部指定.type属性就是result的返回类型.要注意的是,这两个属性都不是必须的,当我们没有配置这两个属性的时候,实际上框架为我们指定了默认值

【HIBERNATE框架开发之三】搭建HIBERNATE日志(SLF4J转LOG4J)环境并搭建JUNIT单元测试环境!

本站文章均为 李华明Himi 原创,转载务必在明显处注明:  转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/hibernate/806.html 由于最新写cocos2dx动作编辑器的解析和框架所以没更新,那么从今天开始继续来学习Hibernate,那么接着第二篇文章讲解,那么首先copy,第二篇的第一个Annotation的项目改个名字"LogForHibernate":           首先搭建log4j环境: 第一步我们之前设置