【问题标题】:How to make string primary key hibernate. @GeneratedValue strategies如何使字符串主键休眠。 @GeneratedValue 策略
【发布时间】:2023-04-10 08:37:01
【问题描述】:

我的目标是创建一个具有唯一字段 IMEI 的实体设备,我想将其用作主键,并在设备注册时指定它(在创建实体时手动指定)。 我使用 Spring roo 工具进行开发并作为 ORM 休眠。

当我在实体声明中指定时:

@RooJavaBean
@RooToString
@RooJpaActiveRecord(identifierField = "IMEI", identifierType = String.class)
public class Device {...}

我生成了这个:

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "IMEI")
private String Device.IMEI;

在使用 mysql db 将项目部署到服务器时,我收到此错误:

2013-03-17 20:03:23,136 [main] ERROR org.hibernate.tool.hbm2ddl.SchemaExport - HHH000389: Unsuccessful: create table device (imei varchar(255) not null auto_increment, model varchar(255), name varchar(255) not null, version integer, primary key (imei))
2013-03-17 20:03:23,136 [main] ERROR org.hibernate.tool.hbm2ddl.SchemaExport - Incorrect column specifier for column 'imei'

然后我用

覆盖 roo 生成的字段
@Id
@GeneratedValue(generator = "org.hibernate.id.Assigned")
@Column(name = "the_code")
private String code;

(我在here 找到了这个)

但仍然出现错误。然后我将代码简单地更改为:

 @Id
private String IMEI;

然后它工作正常,并要求我在保存实体之前指定 imei 字段。

我的问题是:

使用我的自定义字段作为 id 是否正确?

字符串可以吗?

不是用hibernate生成而是取自设备imei可以吗?

什么是 org.hibernate.id.Assigned?

为什么 roo 为 @RooJpaActiveRecord(identifierField = "IMEI", identifierType = String.class) 生成的代码不起作用?

是否可以创建String自动生成的主键?

什么是默认 GeneratedValue 策略值(我的最后一个案例)?

我已经阅读了official doc,但没有完全理解,请参考我可以阅读的文章。

谢谢,很抱歉问题太长了。

【问题讨论】:

    标签: hibernate spring-mvc generator spring-roo


    【解决方案1】:

    目前,可能没有必要。但我认为我们应该为某人更新这张票。

    我刚开始回答堆栈溢出问题,所以希望这是有道理的

    如果你想在hibernate中自动生成String作为ID,你可以使用IdentifierGenerator和@GenericGenerator定义一个规则。

    实体声明:

    public class Device {...
    
        @Id
        @GenericGenerator(name = "sequence_imei_id", strategy = "com.supportmycode.model.ImeiIdGenerator")
        @GeneratedValue(generator = "sequence_imei_id")
        @Column(name = "IMEI")
        private String IMEI;
    
    ...}
    

    Imei 生成器声明:

    public class ImeiIdGenerator implements IdentifierGenerator {...
        public Serializable generate(SessionImplementor session, Object object) throws HibernateException {
    
                // define your IMEI, example IMEI1, IMEI2,...;
                return "IMEI"+ UUID.randomUUID().toString();
    ...}
    

    当您保存设备对象时,IMEI(id) 将由 ImeiIdGenerator 自动生成。

    【讨论】:

      【解决方案2】:

      @GeneratedValue(strategy = GenerationType.AUTO) 不能与 String 类型一起使用。因此,如果您想使用String 作为 ID,您必须手动分配它。但是如果适合您的需要,可以使用 String 作为 ID。

      使用org.hibernate.id.Assigned也意味着你必须在保存数据之前分配ID值。

      当不添加@GeneratedValue注解时,默认为assigned生成器,这意味着标识符的值必须由应用程序设置。

      详情请参考the hibernate manual

      【讨论】:

        【解决方案3】:

        一个简单的解决方案是在您的实体类上使用@PrePersist 注释。

        只需添加方法

        @PrePersist
        private void ensureId(){
            this.setId(UUID.randomUUID().toString());
        }
        

        并去掉 @GeneratedValue 注释。

        PrePersist 文档:http://docs.oracle.com/javaee/5/api/javax/persistence/PrePersist.html

        斯特凡诺

        【讨论】:

        • 但是如果生成的id已经存在于表中怎么办?虽然 id 是安全生成的,但至少有可能该 id 在表中?
        • UUID 是一个“不可变的通用唯一标识符”,如文档所述。
        • 我想在这里添加一个更新,因为很长一段时间过去了,JPA 也在发展。您现在可以使用UUID 类型,并使用@GeneratedValue(strategy = GenerationType.AUTO) 对其进行注释。您不再需要自己做,而是使用原生 JPA ID 生成
        猜你喜欢
        • 1970-01-01
        • 2015-12-09
        • 2015-06-24
        • 2011-04-05
        • 2010-12-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-10
        相关资源
        最近更新 更多