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方法。
Dream 包含主键实体的引用: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; } }
XML配置联合主键: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; } }
运行:
- 通过注解配置实现联合主键(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; } }
将类注解为@IdClass,并将该实体中所有属于主键的属性都注解为@Id: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; } }
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; } } ________________________________________