【问题标题】:JPA: Override Auto generated ID [duplicate]JPA:覆盖自动生成的 ID [重复]
【发布时间】:2012-07-24 23:00:46
【问题描述】:

我在 Employee 类中有以下定义

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "employee_id")
private Integer employeeId;

现在我想导入具有现有员工 ID 的现有员工。即使我在保存之前设置了员工 ID,分配的 ID 也会被忽略并存储自动递增的 ID。我们如何覆盖它?

复合键也有类似的问题,已在here

中得到解释

【问题讨论】:

  • 显然,一些 JPA 实现(例如 DataNucleus JPA)可能会提供一种机制,仅当该字段为空时才允许自动生成,但作为规范的 JPA 不允许。

标签: java hibernate jpa


【解决方案1】:

我编写了自己的生成器来解决这个问题。

public class UseExistingIdOtherwiseGenerateUsingIdentity extends IdentityGenerator {

    @Override
    public Serializable generate(SharedSessionContractImplementor session, Object object) throws HibernateException {
        Serializable id = session.getEntityPersister(null, object).getClassMetadata().getIdentifier(object, session);
        return id != null ? id : super.generate(session, object);
    }
}

并像这样使用它:(替换包名)

@Id
@GenericGenerator(name = "UseExistingIdOtherwiseGenerateUsingIdentity", strategy = "{package}.UseExistingIdOtherwiseGenerateUsingIdentity")
@GeneratedValue(generator = "UseExistingIdOtherwiseGenerateUsingIdentity")
@Column(unique = true, nullable = false)
protected Integer id;

【讨论】:

  • 如果您的id 列的类型是UUID,您应该将IdentityGenerator 更改为UUIDGenerator
【解决方案2】:

您必须重写 getEmployeeId() 方法并在此方法上使用 Annotation 在这种情况下,JPA 对类中的所有字段使用 getter 方法,您必须在 getter 方法上移动其他注释

【讨论】:

    【解决方案3】:

    在这种情况下,最好有一个@MappedSuperclass

    @MappedSuperclass
    public AbstractEmployee {
       // declare all properties, getters, setters except for the id
    }
    
    @Entity
    @Table(name="EMPLOYEE")
    public class Employee extends AbstractEmployee {
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        @Column(name = "employee_id")
        private Integer employeeId;
    
        ...
    }
    
    @Entity
    @Table(name="EMPLOYEE")
    public class EmployeeWithAssignedId extends AbstractEmployee {
        @Id
        @Column(name = "employee_id")
        private Integer employeeId;
    
        ...
    }
    

    因此,当您要手动分配 ID 时,请使用第二类。我没有对此进行测试,但我相信它应该适用于您的情况。我不相信 JPA 中有任何规则说两个类不能具有相同的表名:)

    【讨论】:

    • 我的模型类是从 Roo 生成的。修改这些类会很麻烦。相反,我实现了一个新的生成器,如下所述
    • 好的。请尝试在您的问题中提及这些内容,因为这些重要信息可能会改变人们的答案。
    【解决方案4】:

    你不能覆盖它。首先,JPA 没有提供这样做的方法。第二个问题是 GenerationType.AUTO 可以生成这样的列类型,它不会通过 SQL 语句接受用户分配的值。

    手动执行数据导入,不要尝试将应用程序本身用作导入工具。

    【讨论】:

    • :( 除了手动导入还有其他方法吗?我不能手动进行,因为还有一些预处理。在这种情况下,我必须编写插入代码:(
    • @sidgate 也许您可以禁用自动生成,导入并重新启用它?
    • 这是可能的,但这取决于 id 的列定义(或 GenerationType.AUTO 在数据库中的实际实现方式)是否可以简单地禁用/启用。
    • 请参考下面的答案。我能够通过拥有自己的发电机来解决这个问题。你觉得这个实现有什么问题吗?
    猜你喜欢
    • 2020-11-15
    • 1970-01-01
    • 1970-01-01
    • 2022-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-14
    相关资源
    最近更新 更多