Hibernate中的标识符

Hibernate中的标识符为实体的主键属性建模。 它可以帮助我们唯一地标识JPA实体。 每个实体都必须定义一个标识符。 同样,它可以是简单的也可以是复合的。

我们可以通过几种方式定义一个Hibernate标识符。 在本教程中,我们将学习如何做。

简单(单值)标识符:

如果我们有一个可以唯一标识我们实体的属性,则可以使用@Id注释对该属性进行简单注释:

Java

@Entity
public class Employee {
 
    @Id
    private Integer empId;
     
    ...
}

请记住,用@Id注释的属性应为以下类型之一:

  • 任何Java基本类型或任何原始包装器类型
  • 任何Java日期类型,或者
  • BigDecimalBigInteger

简单生成的标识符:

如果我们希望自动生成id值怎么办? 为此,我们可以更进一步,在标识符字段上使用@GeneratedValue批注:

Java

@Entity
public class Employee {
    
    @Id
    @GeneratedValue
    public Integer empId;
    ...
}

当使用@GeneratedValue时,Hibernate在保留实体的同时会为我们的id列生成值。 对我们而言,重要的是要记住,我们只能自动生成整数类型( int,shortlong )或UUID

此外,我们提供了四种不同的密钥生成策略,可自动生成标识符的值:

Hibernate使用AUTO密钥生成策略作为默认策略。 从一个JPA持久性提供程序到另一个JPA持久性提供程序, AUTO策略的行为略有不同。 对于Hibernate,如果identifier属性的类型为UUID,则它使用UUIDGenerator ,否则默认为序列生成策略。

仅在Hibernate 5和更高版本中支持UUID生成,并且长度为36个字符:

Java

@Entity
public class Employee {
 
    @Id
    @GeneratedValue
    private UUID empId;
 
    ...
}

生成的UUID的格式为“ 4ee5a777-7981-4e01-06ab-19aabb2eaa122”。

对于IDENTITY生成策略,Hibernate使用IdentityGenerator生成标识符值 这些值由数据库的标识列生成,并自动递增:

Java

@Entity
public class Employee {
 
    @Id
    @GeneratedValue (strategy = GenerationType.IDENTITY)
    private Integer empId;
 
    ...
}

使用此策略的主要缺点是它不支持批量JDBC插入。

在这里,顾名思义,数据库序列用于生成我们的标识符的值。 Hibernate内部使用SequenceStyleGenerator类来实现它。 如果我们的数据库不支持序列,它将自动切换到TABLE密钥生成策略。

SEQUENCE生成器为每个序列生成唯一的值。 我们可以指定我们希望使用的数据库顺序:

Java

@Entity
public class Employee {
    
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE,
      generator = "emp_generator")
    @SequenceGenerator(name = "emp_generator",
      sequenceName = "emp_seq", allocationSize = 100)
    public Integer empId;
    ...
}

否则,Hibernate将使用隐式命名的序列hibernate_sequence

Java

@Entity
public class Employee {
    
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    public Integer empId;
    ...
}

为我们的标识符字段生成值。

Hibernate TableGenerator使用一个能够保存标识符生成值的多个段的表。 除非指定,否则Hibernate默认使用hibernate_sequences表:

Java

@Entity
public class Employee {
    
    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    public Integer empId;
    ...
}

我们可以使用@TableGenerator来指定用于生成值的数据库表:

Java

@Entity
    public class Employee {
 
        @Id
        @GeneratedValue(strategy = GenerationType.TABLE, generator = "emp_generator") 
        @TableGenerator(name = "emp_generator",
          table = "emp_generator_tbl",
          schema = "employees")
        public Integer empId;
        
        ...
 
 }

TABLE策略的伸缩性不是很好,并且性能很差,因此在实际的实现中很少使用。 对于所有支持序列的数据库,我们总是应该优先使用SEQUENCE生成策略,而大多数现代数据库通常都会这样做。

复合标识符:

Hibernate还允许我们定义一个复合标识符。 要定义组合标识符,我们创建一个主键类,其中包含构成组合键的持久属性。 根据JPA规范,我们的主键类必须为:

  1. @EmbeddedId@IdClass注释进行注释
  2. 公开并有一个公开的无参数构造函数
  3. 可序列化
  4. 实现equals()hashCode()方法

组成合成的属性可以是基本的,合成的或ManyToOne。 但是,集合和OneToOne属性被认为不合适。

1.使用

定义和使用复合键的一种方法是使用@EmbeddedId批注

因此,让我们开始定义主键类并使用@Embeddable对其进行注释

Java

@Embeddable
public class EmployeePurchasesPK implements Serializable {
 
    private long empId;
    private long productId;
 
    //equals() and hashCode() methods
    ...
}

现在,我们可以使用@EmbeddedId批注轻松地从我们的实体中引用此类:

Java

@Entity
public class EmployeePurchases {
 
    @EmbeddedId
    private EmployeePurchasesPK primaryAttributes;
 
    ...
}

要使用我们的实体类设置或检索主键属性,我们将具有以下内容:

Java

EmployeePurchasesPK primaryAttributes = new EmployeePurchasesPK();
primaryAttributes.setEmpId(1001);
primaryAttributes.setProductId(7822);
 
EmployeePurchases empPurchases = new EmployeePurchases();
empPurchases.setPrimaryAttributes(primaryAttributes);
...

显然,我们的EmployeePurchases实体具有一个由empIdproductId组成的复合键。

2.使用

使用@IdClass创建复合键时我们可以使用@Id批注在主类中定义所有合成属性。 我们的主键类中的代码保持原样,但仅充当“影子”

Java

@Entity
@IdClass(EmployeePurchasesPK.class)
public class EmployeePurchases {
 
    @Id
    private long empId;
 
    @Id
    private long productId;
 
    ...
 
}

通过这种方法,我们可以使用主要实体类的getter / setter方法直接设置键值:

Java

EmployeePurchases empPurchases = new EmployeePurchases(); 
empPurchases.setEmpId(1011);
empPurchases.setProductId(9331);
...

但是,此方法无法为我们提供标识符和实体对象之间的清晰区分。

派生标识符:

在Hibernate中,我们可以选择使用@MapsId注释从其关联之一复制实体的标识符值

Java

public class EmployeeHistory {
 
    @Id
    private long id;
 
    @OneToOne
    @MapsId
    private Employee employee;
 
    ...
 
}

在这里,我们的EmployeeHistory实例将具有与相应Employee实例完全相同的ID

结论:

在本教程中,我们研究了在Hibernate中定义标识符的多种方法。 我们还介绍了不同的关键自动生成策略。

成为第一个发表评论的人。

翻译自: https://www.javacodegeeks.com/2019/04/identifiers-hibernate.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值