Hibernate的ID主键生成策略

ID生成策略(一)
  • 通过XML配置实现ID自动生成(测试uuid和native)

之前我们讲了除了通过注解的方式来创建一个持久化bean外,也可以在需要持久化的bean的包路径下创建一个与bean相同名字的hbm.xml文件来实现相同的功能!
例如:

User.hbm.xml文件配置:

我们可以通过在id下指定<generator>来实现ID自动生成:
<generator>的使用:

       
       
    
        
        
    
        
        

       
       
class指向一个标识生成器,用于生成主键字段,以下是hibernate提供的几种常用的生成器:
identity
对DB2,MySQL, MS SQL Server, Sybase和HypersonicSQL的内置标识字段提供支持。 返回的标识符是long, short 或者int类型的。
sequence
在DB2,PostgreSQL, Oracle, SAP DB, McKoi中使用序列(sequence), 而在Interbase中使用生成器(generator)。返回的标识符是long, short或者 int类型的。
uuid(一个世界上唯一的字符串)
uses a 128-bit UUID algorithm to generate identifiers of type string that are unique within a network (the IP address is used). The UUID is encoded as a string of 32 hexadecimal digits in length.
native(根据数据库的不同将会选择不同的方式)
selects identity, sequence or hilo depending upon the capabilities of the underlying database.
实验(uuid的使用):
package org.jacq.hibernate.model;

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

	public User(){}

	public User(String name,int age){
		this.name = name;
		this.age = age;
	}
    // getter setter
}


     
     


     
     

     
     

    
      
      
    
      
      
        
       
       
        
       
       
            
        
        
        
       
       
        
       
       
        
       
       
        
       
       
    
      
      


     
     
测试,不需要为主键ID设置值:
package org.jacq.hibernate.sample;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.Session;
import org.jacq.hibernate.model.User;

public class UserTest {
	public static void main(String[] args){
		User user = new User("meng",18);

		Configuration configuration = new Configuration();

		SessionFactory sessionFactory = configuration.configure().buildSessionFactory();

		Session session = sessionFactory.openSession();

		session.beginTransaction();

		session.save(user);

		session.getTransaction().commit();

		session.close();

		sessionFactory.close();

	}
}
查看建表语句以及数据库数据:


实验(native的使用):
使用native生成的主键是一个数字,这个时候User的id属性应该是int类型的。
package org.jacq.hibernate.model;

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

	public User(){}

	public User(String name,int age){
		this.name = name;
		this.age = age;
	}
    //getter setter ...
}

查看建表语句以及数据库数据:

ID生成策略(二)

  • 通过注解配置实现ID自动生成

通过给主键字段添加@GeneratedValue注解也可以指定主键的自动生成策略。
查看注解源码,该注解默认值为AUTO,它的作用其实就相当于xml配置中的native。

package org.jacq.hibernate.model;

import javax.persistence.*;
import java.util.Date;

//@Entity 注解说明Event是一个实体,默认对应表名也为event
@Entity
public class Event {
	private Long id;

	private String title;
	private Date date;

	public Event() {}

	public Event(String title, Date date) {
		this.title = title;
		this.date = date;
	}

	//@Id 注解指定表event的主键
	@Id
	@GeneratedValue
	public Long getId() {
		return id;
	}

	private void setId(Long id) {
		this.id = id;
	}

	@Temporal(TemporalType.TIMESTAMP)
	public Date getDate() {
		return date;
	}

	public void setDate(Date date) {
		this.date = date;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}
}
查看建表语句以及数据库数据


查看源码,@GeneratedValue注解还有其他3种取值:

  • AUTO – 可以是identity column类型,或者sequence类型或者table类型,取决于不同的底层数据库。
  • TABLE – 使用表保存id值。
  • IDENTITY – identity column,指定支持IDENTITY的数据库使用,不支持使用SEQUENCE的数据库,比如MYSQL。

  • SEQUENCE – sequence指定支持SEQUENCE的数据库使用,不支持使用IDENTITY的数据库,比如ORACLE。

默认情况下,在使用SEQUENCE的情况下,不同的表使用同一个SEQUENCE:hibernate_sequence,若我们需要为表指定单独的sequence,我们需要使用注解 @SequenceGenerator !
name属性是sequence生成器的名字,sequenceName是生成的sequence的名字。

然后我们可以在实体类中指定主键使用该生成器生成sequence:

通过注解@TableGenerator生成主键(跨数据库平台):
这个注解的作用是生成一张中间表来为其他业务表创建主键,当业务表从中获取了一个主键,它将创建一个新的主键等待获取。
name:该生成器的名字。
table:生成的表的表名(id_create_table),这个表包含字段(table_name,table_id),table_name做为键值对的键值,存pkColumnValue的值(EVENT),allocationSize指定主键自增1;

使用:

package org.jacq.hibernate.model;

import javax.persistence.*;
import java.util.Date;

//@Entity 注解说明Event是一个实体,默认对应表名也为event
@Entity
@TableGenerator(
		name = "id_generator",
		table = "id_create_table",
		pkColumnName = "table_name",
		valueColumnName = "table_id",
		pkColumnValue = "EVENT",
		allocationSize=20
)
//@SequenceGenerator(name="eventGenerator",sequenceName = "EVENT_SEQ")
public class Event {
	private int id;

	private String title;
	private Date date;

	public Event() {}

	public Event(String title, Date date) {
		this.title = title;
		this.date = date;
	}

	//@Id 注解指定表event的主键
	@Id
	@GeneratedValue(strategy = GenerationType.TABLE, generator = "id_generator")
	public int getId() {
		return id;
	}

	private void setId(int id) {
		this.id = id;
	}

	@Temporal(TemporalType.TIMESTAMP)
	public Date getDate() {
		return date;
	}

	public void setDate(Date date) {
		this.date = date;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}
}



ID生成策略(三)

  • 通过XML配置实现联合主键

有的时候我们需要将一个实体的2个或多个字段联合起来作为主键,就是说,不能有2个或多个对象的这几个字段值都相同的情况发生。
现在我们要将Dream字段的id和name字段联合作为主键:
作为主键的字段需单独放到一个实体中,该实体须实现java.io.Serializable,重写equals和hashCode方法。
package org.jacq.hibernate.model;

import java.io.Serializable;

public class DreamPk implements Serializable{
	private int id;
	private String name;

	public DreamPk() {}

	public DreamPk(int id, String name) {
		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;
	}

	@Override
	public boolean equals(Object o) {
		if (this == o) return true;
		if (o == null || getClass() != o.getClass()) return false;

		DreamPk dreamPk = (DreamPk) o;

		if (id != dreamPk.id) return false;
		if (name != null ? !name.equals(dreamPk.name) : dreamPk.name != null) return false;

		return true;
	}

	@Override
	public int hashCode() {
		int result = id;
		result = 31 * result + (name != null ? name.hashCode() : 0);
		return result;
	}
}
Dream 包含主键实体的引用:
package org.jacq.hibernate.model;

public class Dream {

	private int age;

	private DreamPk dreamPk;

	public Dream() {}

	public Dream(int age,DreamPk dreamPk) {
		this.age = age;
		this.dreamPk = dreamPk;
	}

	public DreamPk getDreamPk() {
		return dreamPk;
	}

	public void setDreamPk(DreamPk dreamPk) {
		this.dreamPk = dreamPk;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

}
XML配置联合主键:


     
     


     
     

     
     

    
      
      
        
       
       
            
        
        
            
        
        
        
       
       
        
       
       
    
      
      


     
     
运行:



  • 通过注解配置实现联合主键(3种方式)
将组件类注解为@Embeddable,并将组件的属性注解为@Id:
package org.jacq.hibernate.model;

import javax.persistence.Embeddable;
import java.io.Serializable;

@Embeddable
public class DreamPk implements Serializable{
	private int id;
	private String name;

	public DreamPk() {}

	public DreamPk(int id, String name) {
		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;
	}

	@Override
	public boolean equals(Object o) {
		if (this == o) return true;
		if (o == null || getClass() != o.getClass()) return false;

		DreamPk dreamPk = (DreamPk) o;

		if (id != dreamPk.id) return false;
		if (name != null ? !name.equals(dreamPk.name) : dreamPk.name != null) return false;

		return true;
	}

	@Override
	public int hashCode() {
		int result = id;
		result = 31 * result + (name != null ? name.hashCode() : 0);
		return result;
	}
}
package org.jacq.hibernate.model;

import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class Dream {

	private int age;

	private DreamPk dreamPk;

	public Dream() {}

	public Dream(int age,DreamPk dreamPk) {
		this.age = age;
		this.dreamPk = dreamPk;
	}

	@Id
	public DreamPk getDreamPk() {
		return dreamPk;
	}

	public void setDreamPk(DreamPk dreamPk) {
		this.dreamPk = dreamPk;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

}

将组件的属性注解为@EmbeddedId:
package org.jacq.hibernate.model;

import javax.persistence.Embeddable;
import java.io.Serializable;

//@Embeddable
public class DreamPk implements Serializable{
	private int id;
	private String name;

	public DreamPk() {}

	public DreamPk(int id, String name) {
		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;
	}

	@Override
	public boolean equals(Object o) {
		if (this == o) return true;
		if (o == null || getClass() != o.getClass()) return false;

		DreamPk dreamPk = (DreamPk) o;

		if (id != dreamPk.id) return false;
		if (name != null ? !name.equals(dreamPk.name) : dreamPk.name != null) return false;

		return true;
	}

	@Override
	public int hashCode() {
		int result = id;
		result = 31 * result + (name != null ? name.hashCode() : 0);
		return result;
	}
}
package org.jacq.hibernate.model;

import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class Dream {

	private int age;

	private DreamPk dreamPk;

	public Dream() {}

	public Dream(int age,DreamPk dreamPk) {
		this.age = age;
		this.dreamPk = dreamPk;
	}

	//@Id
	@EmbeddedId
	public DreamPk getDreamPk() {
		return dreamPk;
	}

	public void setDreamPk(DreamPk dreamPk) {
		this.dreamPk = dreamPk;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

}
将类注解为@IdClass,并将该实体中所有属于主键的属性都注解为@Id:
package org.jacq.hibernate.model;

import javax.persistence.Embeddable;
import java.io.Serializable;

//@Embeddable
public class DreamPk implements Serializable{
	private int id;
	private String name;

	public DreamPk() {}

	public DreamPk(int id, String name) {
		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;
	}

	@Override
	public boolean equals(Object o) {
		if (this == o) return true;
		if (o == null || getClass() != o.getClass()) return false;

		DreamPk dreamPk = (DreamPk) o;

		if (id != dreamPk.id) return false;
		if (name != null ? !name.equals(dreamPk.name) : dreamPk.name != null) return false;

		return true;
	}

	@Override
	public int hashCode() {
		int result = id;
		result = 31 * result + (name != null ? name.hashCode() : 0);
		return result;
	}
}
package org.jacq.hibernate.model;

import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;

@Entity
@IdClass(DreamPk.class)
public class Dream {

	private int id;
	private String name;
	private int age;

	@Id
	public int getId() {
		return id;
	}

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

	@Id
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
//private DreamPk dreamPk;

	public Dream() {}

	public Dream(int id, String name, int age) {
		this.id = id;
		this.name = name;
		this.age = age;
	}
/*public Dream(int age,DreamPk dreamPk) {
		this.age = age;
		this.dreamPk = dreamPk;
	}*/

	//@Id
	//@EmbeddedId
	/*
	public DreamPk getDreamPk() {
		return dreamPk;
	}*/

	/*public void setDreamPk(DreamPk dreamPk) {
		this.dreamPk = dreamPk;
	}*/

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

}
________________________________________

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值