Hibernate 框架学习——映射主键属性

本文我们学习映射文件中的主键属性,废话不多说,直接开干。
我们首先在cn.itcast.d_hbm_id包下创建一个持久化类——User.java。

public class User {
    private Integer id; // 如果是数字,建议使用包装类型。
    private String name;

    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;
    }
}

注意:在User类中,字段id使用的类型是包装类型(java.lang.Integer)。
使用基本数据类型和包装类型的区别:
基本数据类型和包装类型对应的hibernate映射类型相同(映射是一样的)。例:

<property name="price" type="double" column="PRICE" />
  • 基本类型可直接运算、无法表达null、数字类型的默认值为0。
  • 包装类默认值是null,当对于默认值有业务意义的时候需要使用包装类。

例如,Student类有一个int类型的scope属性,表示学生的考试分数。int类型的scope属性无法表达这样的业务需求:

  • 如果scope的属性为null,表示该学生的成绩是未知的,有可能得了100分,也有可能得了0分,只是暂时还不知道成绩。
  • 如果scope属性为0,表示学生考试成绩为0分。

在上面的情况中必须使用包装类型。

接下来我们就要在cn.itcast.d_hbm_id包中编写与持久化类相对应的映射文件——User.hbm.xml了。

id和generator元素配置说明

配置示例:

<id name="id" type="long" column="ID">
      <generator class="native" />
</id>

<id>元素说明:
设定持久化类的OID和表的主键的映射,可以有以下属性:

  • name:标识持久化类OID的属性名。
  • column:设置标识属性所映射的数据列的列名(主键字段的名字)。
  • type:指定Hibernate映射类型。Hibernate映射类型是Java类型与SQL类型的桥梁。如果没有为某个属性显式设定映射类型,Hibernate会运用反射机制先识别出持久化类的特定属性的Java类型,然后自动使用与之对应的默认的Hibernate映射类型。

Java的基本数据类型和包装类型对应相同的Hibernate映射类型。基本数据类型无法表达null,所以对于持久化类的OID推荐使用包装类型。

<generator>元素说明:
为持久化类设定标识符生成器,说白了就是用于指定主键生成策略(某种方式生成主键的值),可以有一个class属性:

  • class:指定使用的标识符生成器全限定类名或其缩写名。

<generator>元素的class属性可以指定的值说明(主键生成策略):

主键生成器 描述
increment 适用于代理主键。由Hibernate自动以递增的方式生成标识符,每次增量为1
identity 适用于代理主键。由底层数据库生成标识符。条件是数据库支持自动增长数据类型
sequence 适用于代理主键。Hibernate根据底层数据库序列生成标识符。条件是数据库支持序列
hilo 适用于代理主键。Hibernate根据hign/low算法生成标识符。Hibernate把特定表的字段作为”hign”值。默认情况下,采用hibernate_unique_key表的next_hi字段
uuid 适用于代理主键。Hibernate采用128位的UUID算法来生成标识符。该算法能够在网络环境中生成唯一的字符串标识符,这种策略并不流行,因为字符串类型的主键比整数类型的主键占用更多的数据库空间
assigned 适用于自然主键。由java程序负责生成标识符。不能把setID()方法声明为private的。尽量避免使用自然主键

以上class属性可以指定的值,我们也可以从官方文档中查阅到,查询目录为:{hibernate_home}/ldocumentation/manual/en-US/html_single/index.html。

下面我们来一一讲解class属性的值。

identity

这里写图片描述

identity标识符生成器由底层数据库来负责生成标识符,它要求底层数据库把主键定义为自动增长字段类型。

适用范围:

  • 由于identity生成标识符的机制依赖于底层数据库系统,因此,要求底层数据库系统必须支持自动增长字段类型。支持自动增长字段类型的数据库包括:DB2、MySql、MS
    SQLServer、Sybase等。
  • OID必须为long、int或short类型,如果把OID定义为byte类型,在运行时会抛出异常。

示例代码:

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

<hibernate-mapping package="cn.itcast.d_hbm_id">
    <class name="User" table="t_user">
        <!-- 
            id元素用于映射主键
            子元素generator是用于指定主键生成策略(某种方式生成主键的值)的。
        -->
        <id name="id">
            <!-- 
                identity:使用数据库自己的主键生成策略(MySQL——自动增长)
                使用数据库的自动增长策略,不是所有数据库都支持,比如Oracle就不支持
            -->
            <generator class="identity"/>
        </id>
        <property name="name" /> 
    </class>
</hibernate-mapping>

sequence

这里写图片描述

sequence标识符生成器利用底层数据库提供的序列来生成标识符。

Hibernate在持久化一个News对象时,先从底层数据库的news_seq序列中获得一个唯一的标识号,再把它作为主键值。

适用范围:

  • 由于sequence生成标识符的机制依赖于底层数据库系统的序列,因此,要求底层数据库系统必须支持序列。支持序列的数据库包括:DB2、Oracle等。
  • OID必须为long、int或short类型,如果把OID定义为byte类型,在运行时会抛出异常。

示例代码:

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

<hibernate-mapping package="cn.itcast.d_hbm_id">
    <class name="User" table="t_user">
        <!-- 
            id元素用于映射主键
            子元素generator是用于指定主键生成策略(某种方式生成主键的值)的。
        -->
        <id name="id">
             <!-- 
                sequence:在DB2、PostgreSQL、Oracle、SAP DB、McKoi中使用序列(sequence) 
                在使用Oracle数据库时可以使用这一个。
            -->
            <generator class="sequence"/>
        </id>
        <property name="name" /> 
    </class>
</hibernate-mapping>

hilo

这里写图片描述

hilo标识符生成器由Hibernate按照一种high/low算法生成标识符,它从数据库的特定表的字段中获取high值。

Hibernate在持久化一个News对象时,由Hibernate负责生成主键值。hilo标识符生成器在生成标识符时,需要读取并修改HI_TABLE表中的NEXT_VALUE值。

适用范围:

  • 由于hilo生成标识符机制不依赖于底层数据库系统,因此它适合所有的数据库系统。
  • OID必须为long、int或short类型,如果把OID定义为byte类型,在运行时会抛出异常。

示例代码:

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

<hibernate-mapping package="cn.itcast.d_hbm_id">
    <class name="User" table="t_user">
        <!-- 
            id元素用于映射主键
            子元素generator是用于指定主键生成策略(某种方式生成主键的值)的。
        -->
        <id name="id">
            <!-- 
                hilo:使用高低位算法来生成的主键值
                只需要一张额外的表,所有的数据库都支持。
            -->
            <generator class="hilo">
                <param name="table">hi_value</param>
                <param name="column">next_value</param>
                <param name="max_lo">100</param>
            </generator>
        </id>
        <property name="name" /> 
    </class>
</hibernate-mapping>

native

这里写图片描述

native标识符生成器依据底层数据库对自动生成标识符的支持能力来选择使用identity、sequence或hilo标识符生成器。

适用范围:

  • 由于native能根据底层数据库系统的类型,自动选择合适的标识符生成器,因此很适合于跨数据库平台开发。
  • OID必须为long、int或short类型,如果把OID定义为byte类型,在运行时会抛出异常。

示例代码:

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

<hibernate-mapping package="cn.itcast.d_hbm_id">
    <class name="User" table="t_user">
        <!-- 
            id元素用于映射主键
            子元素generator是用于指定主键生成策略(某种方式生成主键的值)的。
        -->
        <id name="id">
            <!-- 根据底层数据库的能力选择identity、sequence或者hilo中的一个 -->
            <generator class="native"></generator>
        </id>
        <property name="name" /> 
    </class>
</hibernate-mapping>

我们就以上面的映射配置文件为例来进行测试,在测试之前,我们还需在cn.itcast.d_hbm_id包下创建一个单元测试类——App.java。

public class App {
    private static SessionFactory sessionFactory = new Configuration() //
            .configure() //
            .addClass(User.class) // 添加Hibernate实体类(加载对应的映射文件)
            .buildSessionFactory();

    @Test
    public void testSave() {
        Session session = sessionFactory.openSession();
        session.beginTransaction();
        // -------------------------------------------

        // 构建对象
        User user = new User();
        user.setName("张三");

        // 保存
        session.save(user);

        // -------------------------------------------
        session.getTransaction().commit();
        session.close();
    }
}

increment

这里写图片描述

increment标识符生成器由Hibernate以递增的方式为代理主键赋值。Hibernate会先读取表中的主键的最大值,向表中插入记录时,就在 max(id)的基础上递增,增量为1。

适用范围:

  • 由于increment生成标识符机制不依赖于底层数据库系统,因此它适合所有的数据库系统。
  • 适用于只有单个Hibernate应用进程访问同一个数据库的场合,在多线程情况下会有问题。
  • OID必须为long、int或short类型,如果把OID定义为byte类型,在运行时会抛出异常。

示例代码:

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

<hibernate-mapping package="cn.itcast.d_hbm_id">
    <class name="User" table="t_user">
        <!-- 
            id元素用于映射主键
            子元素generator是用于指定主键生成策略(某种方式生成主键的值)的。
        -->
        <id name="id">
            <!-- 
                increment:由Hibernate维护的自动增长。
                先查询当前最大的id值,再加1使用,
                不推荐使用,因为在多线程下会有问题。 
            -->
            <generator class="increment"></generator>
        </id>
        <property name="name" /> 
    </class>
</hibernate-mapping>

assigned

表示手工指定主键的值。

示例代码:

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

<hibernate-mapping package="cn.itcast.d_hbm_id">
    <class name="User" table="t_user">
        <!-- 
            id元素用于映射主键
            子元素generator是用于指定主键生成策略(某种方式生成主键的值)的。
        -->
        <id name="id">
            <!-- assigned:手工指定主键值 -->
            <generator class="assigned"></generator> 
        </id>
        <property name="name" /> 
    </class>
</hibernate-mapping>

我们以上面的映射配置文件为例来进行测试,在测试之前,我们打算修改User类的代码为:

public class User {
    private String id;
    private String name;

    public String getName() {
        return name;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }
}

接着我们就要修改App类的代码为:

public class App {
    private static SessionFactory sessionFactory = new Configuration() //
            .configure() //
            .addClass(User.class) // 添加Hibernate实体类(加载对应的映射文件)
            .buildSessionFactory();

    @Test
    public void testSave() {
        Session session = sessionFactory.openSession();
        session.beginTransaction();
        // -------------------------------------------

        // 构建对象
        User user = new User();
        user.setId(UUID.randomUUID().toString());
        // user.setId("bb");
        user.setName("张三");

        // 保存
        session.save(user);

        // -------------------------------------------
        session.getTransaction().commit();
        session.close();
    }
}

uuid

由Hibernate自动生成UUID并指定为主键值。

示例代码:

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

<hibernate-mapping package="cn.itcast.d_hbm_id">
    <class name="User" table="t_user">
        <!-- 
            id元素用于映射主键
            子元素generator是用于指定主键生成策略(某种方式生成主键的值)的。
        -->
        <id name="id">
            <!-- uuid:由Hibernate自动生成UUID并指定为主键值。  -->
            <generator class="uuid"></generator>  
        </id>
        <property name="name" /> 
    </class>
</hibernate-mapping>

我们以上面的映射配置文件为例来进行测试,在测试之前,我们应修改App类的代码为:

public class App {
    private static SessionFactory sessionFactory = new Configuration() //
            .configure() //
            .addClass(User.class) // 添加Hibernate实体类(加载对应的映射文件)
            .buildSessionFactory();

    @Test
    public void testSave() {
        Session session = sessionFactory.openSession();
        session.beginTransaction();
        // -------------------------------------------

        // 构建对象
        User user = new User();
        user.setName("张三");

        // 保存
        session.save(user);

        // -------------------------------------------
        session.getTransaction().commit();
        session.close();
    }
}

猜你喜欢

转载自blog.csdn.net/qq_38977097/article/details/81347618