休眠中的 GenerationType.AUTO 与 GenerationType.IDENTITY

Posted

技术标签:

【中文标题】休眠中的 GenerationType.AUTO 与 GenerationType.IDENTITY【英文标题】:GenerationType.AUTO vs GenerationType.IDENTITY in hibernate 【发布时间】:2016-01-10 20:06:24 【问题描述】:

目前,我们使用 mysql 作为数据库,我们使用

@Generated Value(strategy = GenerationType.IDENTITY)

在我们需要将数据库迁移到 Oracle 的某些情况下它运行良好,但此时它无法正常运行。如果有人知道这背后的实际区别是什么以及它是如何工作的?

【问题讨论】:

您使用的是什么 ORM 提供程序? 如果你使用GenerationType.AUTO,那么默认情况下hibernate使用hibernate_sequence作为所有表使用的序列,并且一次只能使用一个序列值,这意味着如果使用序列1,那么它不能在其他任何地方使用。但是对于GenerationType.IDENTITY,ID 仅对于该特定列是唯一的。 (测试数据库 - MySQL) 【参考方案1】:

我使用 JPA 和 Oracle 11g,对我有用的解决方案如下

package com.example.springsocial.model;

import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;

@Entity
@Table(name = "rol", uniqueConstraints = 
        @UniqueConstraint(columnNames = "name")
)
public class Rol 
    @Id
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="rol_sequence")
    @SequenceGenerator(name="rol_sequence", sequenceName="rol_sequence", allocationSize=100)
    private Long id;

    @Column(nullable = false)
    private String name;

    private Date createdAt;
    @Column(nullable = true)
    private Date updatedAt;
    @Column(nullable = true)
    private Integer createdBy;
    @Column(nullable = true)
    private Integer updatedBy;

    public Long getId() 
        return id;
    

    public void setId(Long id) 
        this.id = id;
    

    public String getName() 
        return name;
    

    public void setName(String name) 
        this.name = name;
    

    public Date getCreatedAt() 
        return createdAt;
    

    public void setCreatedAt(Date createdAt) 
        this.createdAt = createdAt;
    

    public Date getUpdatedAt() 
        return updatedAt;
    

    public void setUpdatedAt(Date updatedAt) 
        this.updatedAt = updatedAt;
    

    public Integer getCreatedBy() 
        return createdBy;
    

    public void setCreatedBy(Integer createdBy) 
        this.createdBy = createdBy;
    

    public Integer getUpdatedBy() 
        return updatedBy;
    

    public void setUpdatedBy(Integer updatedBy) 
        this.updatedBy = updatedBy;
    

【讨论】:

【参考方案2】:

引用Java Persistence/Identity and Sequencing:

Identity 排序使用数据库中的特殊 IDENTITY 列,以允许数据库在插入行时自动为对象分配 id。许多数据库都支持标识列,例如 MySQL、DB2、SQL Server、Sybase 和 Postgres。 Oracle 不支持 IDENTITY 列,但可以通过使用序列对象和触发器来模拟它们。

所以我更喜欢使用 SEQUENCE 代替

序列对象使用特殊的数据库对象来生成 ID。仅在某些数据库中支持序列对象,例如 Oracle、DB2 和 Postgres。通常,SEQUENCE 对象具有名称、INCREMENT 和其他数据库对象设置。每次选择 .NEXTVAL 时,序列都会增加 INCREMENT。

例子:

@Entity
public class Employee 
    @Id
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="EMP_SEQ")
    @SequenceGenerator(name="EMP_SEQ", sequenceName="EMP_SEQ", allocationSize=100)
    private long id;
    ...

【讨论】:

【参考方案3】:

它如何与 Oracle 一起“正常工作”(您没有像您的意思那样定义基本信息)?我看不到 AUTO 与您的问题的相关性 - 这只是让实现选择它想要使用的内容。

IDENTITY”(根据 JPA javadocs 和规范 - 您应该指的是)表示 自动增量。在 Oracle 中没有这样的概念,但在 MySQL、SQLServer 和其他一些中却有。我希望任何体面的 JPA 实现都能在尝试这样的事情时标记错误。

Oracle 将允许使用“SEQUENCE”或“TABLE”策略

【讨论】:

是的,正如你所说,oracle 中没有自动增量选项。但是如果我使用 GenerationType.AUTO,则模型适用于 oracle 数据库,因为如果我给 Auto,JPA 会自动根据数据库。感谢您的澄清。

以上是关于休眠中的 GenerationType.AUTO 与 GenerationType.IDENTITY的主要内容,如果未能解决你的问题,请参考以下文章

在获取数据时休眠重复域

休眠 java.lang.NullPointerException

删除实体时休眠将外键设置为空

Spring/Hibernate GenerationType.AUTO 的数据库备份问题

如何使用 @GeneratedValue(strategy = GenerationType.AUTO) 创建对象

@GeneratedValue(strategy = GenerationType.AUTO) 没有像想象的那样工作