Hibernate之主键生成策略

Posted psyu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hibernate之主键生成策略相关的知识,希望对你有一定的参考价值。

 

hibernate的主键生成器:
generator元素:表示了一个主键生成器,它用来为持久化类实例生成唯一的标识 。


1 程序员自己控制:assigned

2 数据库控制: identity(标识列/自动增长) sequence

3 hibernate控制:increment uuid/uuid.hex

4 其它:native

 

assigned:

主键由外部程序负责生成,在 save() 之前必须指定一个。Hibernate不负责维护主键生成。与Hibernate和底层数据库都无关,可以跨数据库。在存储对象前,必须要使用主键的setter方法给主键赋值,至于这个值怎么生成,完全由自己决定,这种方法应该尽量避免。

<id name="sid" type="java.lang.Integer" column="sid">

<generator class="assigned" />

</id>

特点:可以跨数据库,人为控制主键生成。

increment:

由Hibernate从数据库中取出主键的最大值(每个session只取1次),以该值为基础,每次增量为1,在内存中生成主键,不依赖于底层的数据库,因此可以跨数据库。

<id name="sid" type="java.lang.Integer" column="sid">

<generator class="increment" />

</id>

Hibernate调用org.hibernate.id.IncrementGenerator类里面的generate()方法,使用select max(idColumnName) from tableName语句获取主键最大值。该方法被声明成了synchronized,所以在一个独立的Java虚拟机内部是没有问题的,然而,在多个JVM同时并发访问数据库select max时就可能取出相同的值,再insert就会发生Dumplicate entry的错误。所以只能有一个Hibernate应用进程访问数据库,否则就可能产生主键冲突,所以不适合多进程并发更新数据库,适合单一进程访问数据库,不能用于群集环境。

特点:跨数据库,不适合多进程并发更新数据库,适合单一进程访问数据库,不能用于群集环境。

 

identity:

identity由底层数据库生成标识符。identity是由数据库自己生成的,但这个主键必须设置为自增长,使用identity的前提条件是底层数据库支持自动增长字段类型

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

<generator class="identity" />

例:如果使用mysql数据库,则主键字段必须设置成auto_increment。

id int(11) primary key auto_increment

特点:只能用在支持自动增长的字段数据库中使用,如MySQL。

 

sequence:

采用数据库提供的sequence机制生成主键,需要数据库支持sequence。

<generator class="sequence" >
<param name="sequence_name">aaa</param>
</generator> -->

Hibernate生成主键时,查找sequence并赋给主键值,主键值由数据库生成,Hibernate不负责维护,使用时必须先创建一个sequence,如果不指定sequence名称,则使用Hibernate默认的sequence,名称为hibernate_sequence,前提要在数据库中创建该sequence。

特点:只能在支持序列的数据库中使用。


案例演示:

1.在数据库中建好测试的表(这里用的MYSQL)

表的实体类:

package com.psy.two.entity;

import java.io.Serializable;

public class Student implements Serializable

    private Integer sid;
    private String sname;
    public Integer getSid() 
        return sid;
    
    public void setSid(Integer sid) 
        this.sid = sid;
    
    public String getSname() 
        return sname;
    
    public void setSname(String sname) 
        this.sname = sname;
    
    public Student(Integer sid, String sname) 
        super();
        this.sid = sid;
        this.sname = sname;
    
    public Student() 
        super();
        // TODO Auto-generated constructor stub
    
    @Override
    public String toString() 
        return "Student [sid=" + sid + ", sname=" + sname + "]";
    
    
package com.psy.two.entity;

public class Worker 

    private String wid;
    private String wname;
    public String getWid() 
        return wid;
    
    public void setWid(String wid) 
        this.wid = wid;
    
    public String getWname() 
        return wname;
    
    public void setWname(String wname) 
        this.wname = wname;
    
    public Worker(String wid, String wname) 
        super();
        this.wid = wid;
        this.wname = wname;
    
    public Worker() 
        super();
        // TODO Auto-generated constructor stub
    
    @Override
    public String toString() 
        return "Worker [wid=" + wid + ", wname=" + wname + "]";
    
    

实体映射文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.psy.two.entity.Student" table="t_hibernate_student">
        <id name="sid" type="java.lang.Integer" column="sid">
            <generator class="assigned" /><!-- 由程序员控制 -->
<!--             <generator class="increment" /> --><!--  hibernate控制-->
            <!-- <generator class="sequence" /> --> <!--  由数据库控制-->
            <!-- <generator class="identity" > 
            <param name="sequence_name">aaa</param> 
                </generator> -->
            <!-- <generator class="com.javaxl.two.id.Myts" /> -->
        </id>
        <property name="sname" type="java.lang.String" column="sname">
        </property>
    </class>
</hibernate-mapping>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.psy.two.entity.Worker" table="t_hibernate_worker">
        <id name="wid" type="java.lang.String" column="wid">
            <!-- <generator class="assigned" /> -->
            <!-- <generator class="uuid" />  -->
            <!-- <generator class="sequence" > <param name="sequence_name">aaa</param> 
                </generator> -->
            <generator class="com.psy.two.id.Myts" />
        </id>

        <property name="wname" type="java.lang.String" column="wname">
        </property>
    </class>
</hibernate-mapping>

SessionFactoryUtils工具类(用来检测所写映射文件是否正确)

package com.psy.two.util;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

/**
 * 
 * 
 * 
 * 作用:
 * 可以用来检测所写的映射文件是否正确
 * @author Admin
 *
 */
public class SessionFactoryUtils 
    private static SessionFactory sessionFactory;
//    存放当前会话
    private static ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
    static 
        Configuration cfg = new Configuration();
        Configuration configure = cfg.configure("/hibernate.cfg.xml");
        sessionFactory = configure.buildSessionFactory();
    
    
    public static Session openSession() 
        Session session = threadLocal.get();
        if (null == session) 
            session = sessionFactory.openSession();
            threadLocal.set(session);
        
        return session;
    

    public static void closeSession() 
        Session session = threadLocal.get();
        if (null != session) 
            if (session.isOpen()) 
                session.close();
            
            threadLocal.set(null);
        
    

    public static void main(String[] args) 
        Session session = openSession();
        System.out.println(session.isConnected());
        closeSession();
    
    

主配置文件hibernate.cfg.xml

 

<!-- 讲解主键生成策略 -->
        <mapping resource="com/psy/two/entity/Worker.hbm.xml" />
        <mapping resource="com/psy/two/entity/Student.hbm.xml" />
        

 

 

测试类:

package com.psy.two.dao;

import java.io.Serializable;

import org.hibernate.Session;
import org.hibernate.Transaction;

import com.psy.two.entity.Student;
import com.psy.two.entity.Worker;
import com.psy.two.util.SessionFactoryUtils;

public class DemoDao 

    /**
     * |添加学生
     * @param stu
     * @return
     */
    public Serializable addStudent(Student stu) 
        Session session = SessionFactoryUtils.openSession();
        Transaction transaction = session.beginTransaction();
        Serializable saveId = session.save(stu);
        
        transaction.commit();
        session.close();
        
        return saveId;
    
    
    
    /**
     * 添加工人
     * @param worker
     * @return
     */
    public Serializable addWorker(Worker worker) 
        Session session = SessionFactoryUtils.openSession();
        Transaction transaction = session.beginTransaction();
        Serializable saveId = session.save(worker);
        
        transaction.commit();
        session.close();
        
        return saveId;
    
    
    
    public static void testStudent(String[] args) 
        DemoDao dao=new DemoDao();
        Student stu =new Student();
        stu.setSid(22);
        stu.setSname("辣鸡");
        System.out.println(dao.addStudent(stu));
    
    
    public static void main(String[] args) 
        DemoDao dao=new DemoDao();
        Worker worker=new Worker();
        worker.setWname("enh");
        
        System.out.println(dao.addWorker(worker));
    
    
    
    

 

以上是关于Hibernate之主键生成策略的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate之主键生成策略

Hibernate 之主键生成策略小总结

hibernate之主键生成策略

hibernate之主键生成策略

mybatisplus之主键生成策略

flea-db使用之主键生成器表介绍