zoukankan      html  css  js  c++  java
  • SSH学习-Hibernate下的主键ID生成规则

    Hibernate下主键id生成策略,需要考虑到数据库使用类型和自己需求进行配置,参考大牛博文发现有很多种生成策略,限于时间只记录课程中的三种生成策略,如果想查看学习其他生成策略参考文末博文。本文将记录三种生成策略在id标签下如何配置,主要是在id标签下使用<generator class=“主键生成策略”>来进行配置。

    identity

    identity是数据库自己生成,主键在数据库建表时需设定为自增长,因此需要数据库支持自增长,目前学习的MySql是支持的,其他还有DB2,SQL Server也支持。其中MySql需使用AUTO_INCREMENT来设定自增类型。

    <id name="" column="" type="">

        <generator class="identity" />

    </id>

    sequence

    sequence是需要提供序列的数据库才可以使用,如学习的oracle,另外还有DB,SAP,SAP DB等。MySql则不支持了。

    <id name="" column="" type="">
        <generator class="sequence">
            <param name="sequence">seq_name</param>
        </generator>
    </id>

    其中 <param name="sequence">seq_name</param>的seq_name是使用的序列名称,如果不指定序列名称将使用Hibernate框架默认的序列名hibernate_sequence(需要提前创建这个序列)。

    uuid

    UUID算法:Universally Unique Identifier,是指在一台机器上生成的字符串,其保证在同一时空对所有的机器都是独一无二的,按照开放基金会(OSF)指定的标准,其用到了以太网地址、纳秒级时间、芯片ID码和许多可能的数字,标准格式如下:

    xxxxxxxx-xxxx-xxxx-xxxxxx-xxxxxxxxxx(8-4-4-4-12),x是0-9或a-f范围内的一个十六进制数字。

    <id name="" column="" type="">
        <generator class='uuid" />
    </id>

    测试Hibernate下自动生成主键id

    新建立student类和teacher类,并在MySql中建立对应表,分别在映射文件中使用identity策略和uuid策略来生成主键id。

    (1)使用identity测试

    建立student类

    package Entity;
    
    import java.io.Serializable;
    
    /**
     * 用于测试ID生成规则的实体类,使用MySql自增
     * @author yangchaolin
     *
     */
    public class Student implements Serializable{
    
        private static final long serialVersionUID = 4625674206340889226L;
        
        private int id;
        private String name;
        
        public Student() {
            super();
        }
    
        public Student(int id, String name) {
            super();
            this.id = id;
            this.name = name;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public static long getSerialversionuid() {
            return serialVersionUID;
        }
    
        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + id;
            return result;
        }
    
        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            Student other = (Student) obj;
            if (id != other.id)
                return false;
            return true;
        }
    
        @Override
        public String toString() {
            return "Student [id=" + id + ", name=" + name + "]";
        }
        
    }
    View Code

    对应数据库建立表,可以看出id是auto_increment

    映射文件中配置,配置完映射文件后还需要在hibernate.cft.xml中将映射文件添加Mapping,这里不展示了。

    <?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">    
    <!-- 配置映射文件,名字一般用实体类类名.hbm.xml -->
    <hibernate-mapping>
    
       <!-- 创建实体类和表的映射关系 -->
       <class name="Entity.Student" table="student">
          <!-- 设置主键映射 -->
          <id name="id" column="id" type="int">
            <!-- ID生成规则-MySql自增 -->
            <generator class="identity"></generator>
          </id>
          <!-- 设置其他非主键映射 -->
          <property name="name" column="name" type="string"></property>
       </class>
     
    </hibernate-mapping>  

    使用测试类插入一条student,并查看数据库中情况。

          //测试hibernate id自动生成,使用MySql自增
          @Test
          public void test1() {
              //读取hibernate.cfg.xml配置文件
              Configuration cfg=new Configuration();
              cfg.configure("hibernate.cfg.xml");
              //创建sessionfactory
              SessionFactory factory=cfg.buildSessionFactory();
              //创建session
              Session session=factory.openSession();
              //创建事务并开启
              Transaction trans=session.beginTransaction();
              trans.begin();
              //开始执行持久层操作,插入一个学生信息到数据表
              Student stu=new Student();
              stu.setName("Alex");
              System.out.println(stu);
              //保存
              session.save(stu);
              System.out.println(stu);    
              //提交事务
              trans.commit();
              //关闭session
              session.close();
          }

    可以看出插入一条数据后再次打印student实体类对象发现id变成了7,这个跟MyBatis返回自增类型类似,可以参考以前博客进行理解。此外数据库中数据也说明id自增,另外输出的sql语句可以看出Hibernate只插入了name,说明id自动生成。

    (2)使用uuid进行测试

    建立teacher类

    package Entity;
    
    import java.io.Serializable;
    
    /**
     * 用于ID生成规则的测试类,使用UUID算法
     * @author yangchaolin
     *
     */
    public class Teacher implements Serializable{
    
        private static final long serialVersionUID = 2414068435933751684L;
        
        private String id;
        private String name;
        
        public Teacher() {
            super();
        }
    
        public Teacher(String id, String name) {
            super();
            this.id = id;
            this.name = name;
        }
    
        public String getId() {
            return id;
        }
    
        public void setId(String id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "Teacher [id=" + id + ", name=" + name + "]";
        }
        
    }
    View Code

    对应数据库中建表

    映射文件中配置,配置完映射文件后还需要在hibernate.cft.xml中将映射文件添加Mapping。

    <?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">    
    <!-- 配置映射文件,名字一般用实体类类名.hbm.xml -->
    <hibernate-mapping>
    
       <!-- 创建实体类和表的映射关系 -->
       <class name="Entity.Teacher" table="teacher">
          <!-- 设置主键映射 -->
          <id name="id" column="id" type="string">
            <!-- ID生成规则-UUID生成 -->
            <generator class="uuid"></generator>
          </id>
          <!-- 设置其他非主键映射 -->
          <property name="name" column="name" type="string"></property>
       </class>
     
    </hibernate-mapping>  

    使用测试类插入一条teacher,并查看数据库中情况。

      //测试hibernate id自动生成,使用uuid
          @Test
          public void test2() {
              //读取hibernate.cfg.xml配置文件
              Configuration cfg=new Configuration();
              cfg.configure("hibernate.cfg.xml");
              //创建sessionfactory
              SessionFactory factory=cfg.buildSessionFactory();
              //创建session
              Session session=factory.openSession();
              //创建事务并开启
              Transaction trans=session.beginTransaction();
              trans.begin();
              //开始执行持久层操作,插入一个老师信息到数据表
              Teacher t=new Teacher();
              t.setName("clyang");
              System.out.println(t);
              //保存
              session.save(t);
              System.out.println(t);    
              //提交事务
              trans.commit();
              //关闭session
              session.close();
          }

    可以看出插入的是id和name,其中插入数据成功后id为一个uuid生成的字符串,被Hibernate返回。

     (3)使用sequence进行测试

    使用sequence进行测试前,需要修改configuration.cfg.xml中dialect标签内容,需对应oracle,此外还需要修改连接数据库的相关信息,具体配置如下: 

    <?xml version="1.0" encoding="GBK"?>
    <!-- 指定Hibernate配置文件的DTD信息 -->
    <!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
    <!-- 配置主配置文件-->
    <hibernate-configuration>
       <session-factory>
           
           <!-- 指定数据库方言,用这个可以切换连接不同的数据库 -->
           <!--  <property name="dialect">org.hibernate.dialect.MySQLDialect</property>-->
           <!-- 测试连接oracle -->
           <property name="dialect">org.hibernate.dialect.Oracle10gDialect</property>
           <!-- 连接数据库 -->      
           <!-- 驱动,url,用户名和密码 -->
           <!--  
           <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
           <property name="connection.url">jdbc:mysql://localhost:3306/ssh</property>
           <property name="connection.username">root</property>
           <property name="connection.password">2688</property>-->
           
           <!-- 连接oracle测试 -->
           <property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
           <property name="connection.url">jdbc:oracle:thin:@localhost:1521:orcl</property>
           <property name="connection.username">SCOTT</property>
           <property name="connection.password">密码</property>
           
           
           <!-- 显示Hibernate持久层操作所使用的SQL -->
           <property name="show_sql">true</property>
           <!-- 将脚本格式化后再进行输出 -->
           <property name="hibernate.format_sql">true</property>
           
           
           <!-- 设置Mapping映射资源文件位置 -->
           <mapping resource="User.hbm.xml"/>
           <mapping resource="Student.hbm.xml"/>
           <mapping resource="Teacher.hbm.xml"/>
           <mapping resource="Star.hbm.xml"/>
    
       </session-factory>
    </hibernate-configuration>

    参考前面两个测试,建立一个实体类Star,数据表中建立star表,并配置映射文件后进行测试。

     实体类Star

    package Entity;
    
    import java.io.Serializable;
    /**
     * 用于测试Hibernate下ID自增,采用oracle序列的方式
     * @author yangchaolin
     *
     */
    public class Star implements Serializable{
        
        private int id;
        private String name;
        
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        
        @Override
        public String toString() {
            return "Star [id=" + id + ", name=" + name + "]";
        }
        
        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + id;
            return result;
        }
        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            Star other = (Star) obj;
            if (id != other.id)
                return false;
            return true;
        }
        
        public Star(int id, String name) {
            super();
            this.id = id;
            this.name = name;
        }
        
        public Star() {
            
        }
        
    
    }
    View Code

    对应数据库中建表,和创建序列MY_SEQUENCE

    CREATE SEQUENCE MY_SEQUENCE INCREMENT BY 1 START WITH 1;

    映射文件中配置,需使用序列,将上面创建的序列名添加到param标签下。

    <?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">    
    <!-- 配置映射文件,名字一般用实体类类名.hbm.xml -->
    <hibernate-mapping>
    
       <!-- 创建实体类和表的映射关系 -->
       <class name="Entity.Star" table="star">
          <!-- 设置主键映射 -->
          <id name="id" column="id" type="int">
            <!-- ID生成规则-采用oracle的序列 -->
            <generator class="sequence">
               <!-- oracle中创建的序列名为MY_SEQUENCE -->
               <param name="sequence">MY_SEQUENCE</param>
            </generator>
          </id>
          <!-- 设置其他非主键映射 -->
          <property name="name" column="name" type="string"></property>
       </class>
     
    </hibernate-mapping>  

    使用测试类插入一条Star,并查看数据库中情况。

          //测试hibernate id自动生成,使用oracle下的sequence
          @Test
          public void test3() {
              //读取hibernate.cfg.xml配置文件
              Configuration cfg=new Configuration();
              cfg.configure("hibernate.cfg.xml");
              //创建sessionfactory
              SessionFactory factory=cfg.buildSessionFactory();
              //创建session
              Session session=factory.openSession();
              //创建事务并开启
              Transaction trans=session.beginTransaction();
              trans.begin();
              //开始执行持久层操作,插入一个Star信息到数据表
              Star t=new Star();
              t.setName("clyang");
              System.out.println(t);
              //保存
              session.save(t);
              System.out.println(t);    
              //提交事务
              trans.commit();
              //关闭session
              session.close();
          }

    可以看出来oracle会先查询序列,然后将序列中的数字插入到star表中,如果连接oracle,使用序列也可以实现ID的自增长,需要注意的是测试连接oracle时不要忘记导包ojdbc。

    结论

    Hibernate下主键生成策略不仅仅是以上几种,通过对映射文件下id的配置,可以在数据库中生成所需要的id。

    参考博文:https://www.cnblogs.com/hoobey/p/5508992.html

  • 相关阅读:
    深入浅出TCP之listen
    indexing and hashing
    c++四种强制类型转化
    c++实现web服务框架
    MVC、MVP、MVVM概念解析
    常用设计模式
    [React]虚拟DOM
    防抖和节流
    函数柯里化
    apply, bind, call方法剖析
  • 原文地址:https://www.cnblogs.com/youngchaolin/p/10897248.html
Copyright © 2011-2022 走看看