You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Hibernate复合主键含日期类型插入报错IdentifierGenerationException求助

嘿,我来帮你搞定这个Hibernate日期主键的问题!结合你遇到的报错和代码情况,我分两种场景给你讲清楚解决方案:

一、单日期类型主键的设置

如果你的实体只有Date类型的主键,核心注意点是:Hibernate默认的主键生成策略不支持自动生成Date类型主键,所以不能加@GeneratedValue(除非你自定义生成器),得手动设置主键值,同时明确指定日期的存储类型:

@Entity
public class SingleDateKeyEntity {
    @Id
    @Temporal(TemporalType.TIMESTAMP) // 按需选TIMESTAMP/DATE/TIME
    private Date id;

    // 其他字段、getter/setter
}

插入数据时,你需要自己给id字段赋值(比如用当前时间),然后再调用persist方法保存。

二、包含Date类型的复合主键解决方案

你遇到的报错org.hibernate.id.IdentifierGenerationException: Unknown integral data type for ids : java.util.Date,本质是给Date类型的主键字段加了@GeneratedValue(strategy = GenerationType.AUTO)——Hibernate的AUTO策略只支持数值型(Long/Integer)或特定生成器生成的字符串,完全不兼容Date类型。而且复合主键的配置也有特定规范,具体步骤如下:

步骤1:定义复合主键类

复合主键必须是一个实现Serializable的类,还要重写equals()和hashCode(),示例如下(根据你实际的前两个主键类型调整):

import java.io.Serializable;
import java.util.Date;
import java.util.Objects;

public class PartyContactMechPK implements Serializable {
    // 对应你实体里的第一个Long主键
    private Long firstId;
    // 假设第二个主键是String,根据你的实际情况修改类型
    private String secondId;
    // Date类型的第三个主键
    private Date thirdId;

    // 必须有无参构造器
    public PartyContactMechPK() {}

    // 带参构造器方便创建对象
    public PartyContactMechPK(Long firstId, String secondId, Date thirdId) {
        this.firstId = firstId;
        this.secondId = secondId;
        this.thirdId = thirdId;
    }

    // 生成getter和setter方法
    // ...

    // 重写equals和hashCode,用于Hibernate判断主键唯一性
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        PartyContactMechPK that = (PartyContactMechPK) o;
        return Objects.equals(firstId, that.firstId) &&
                Objects.equals(secondId, that.secondId) &&
                Objects.equals(thirdId, that.thirdId);
    }

    @Override
    public int hashCode() {
        return Objects.hash(firstId, secondId, thirdId);
    }
}

步骤2:修改实体类

用@EmbeddedId关联刚才定义的复合主键类,去掉原来单个主键字段上的@GeneratedValue注解:

import javax.persistence.*;
import java.util.List;

@Entity
public class PartyContactMech extends BaseEntity {
    @EmbeddedId
    private PartyContactMechPK pk;

    // 你的其他字段,比如关联的List
    @OneToMany(mappedBy = "partyContactMech")
    private List<YourRelatedEntity> relatedEntities;

    // 生成getter和setter方法
    // ...
}

步骤3:插入数据的正确姿势

插入时需要手动创建复合主键对象,给三个主键字段都赋值(包括Date类型的),再关联到实体上:

// 创建复合主键对象,第三个参数传你需要的Date值(比如当前时间)
PartyContactMechPK pk = new PartyContactMechPK(1001L, "CONTACT_MECH_001", new Date());
// 创建实体并绑定主键
PartyContactMech entity = new PartyContactMech();
entity.setPk(pk);
// 给其他字段赋值
// ...
// 保存到数据库
entityManager.persist(entity);

可选:自动生成Date类型的主键值

如果不想手动设置Date,想让Hibernate自动生成(比如用当前时间戳),可以自定义一个主键生成器:

import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.id.IdentifierGenerator;
import java.util.Date;

public class DateIdGenerator implements IdentifierGenerator {
    @Override
    public Object generate(SharedSessionContractImplementor session, Object object) {
        // 返回当前时间作为主键值
        return new Date();
    }
}

然后在复合主键类的Date字段上指定这个生成器:

public class PartyContactMechPK implements Serializable {
    // ...其他字段

    @GeneratedValue(generator = "date-id-generator")
    @GenericGenerator(name = "date-id-generator", strategy = "com.yourpackage.DateIdGenerator")
    private Date thirdId;

    // ...
}

⚠️ 注意:用自动生成的Date作为复合主键的一部分,要确保三个主键的组合唯一,避免出现同一时间插入相同前两个主键的情况,否则会触发唯一约束报错。

三、报错原因再梳理一遍

你之前的错误就是给Date类型的主键加了@GeneratedValue(strategy = GenerationType.AUTO),Hibernate没法用数值型的生成逻辑去生成Date类型的主键,所以直接抛了异常——只要去掉这个注解,按照复合主键的规范配置,再手动赋值或者用自定义生成器,问题就解决啦!

内容的提问来源于stack exchange,提问作者M.A.M

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 11:09:05