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

Java Spring JPA环境下如何将Date转换为Epoch时间戳并存入DynamoDB表?

Java Spring JPA环境下如何将Date转换为Epoch时间戳并存入DynamoDB表?

我看了你的配置,发现核心问题是DynamoDB表结构和实体类的类型不匹配——你的CloudFormation把createdAt定义为数字类型(N,存Epoch时间戳),但实体类里直接用了Date类型作为范围键,而AWS SDK的DynamoDB映射默认不会自动把Date转成数字时间戳,所以得做类型转换处理。下面给你两种可行的解决办法,你可以按需选择:

方案1:自定义类型转换器(推荐)

这种方式能让业务层依然用Date类型,底层转换逻辑完全封装在转换器里,代码更干净。

步骤1:写一个Date转Long的类型转换器

创建一个实现DynamoDBTypeConverter的类,负责在Date和Epoch时间戳(Long)之间互相转换:

import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTypeConverter;
import java.util.Date;

public class DateToEpochTimestampConverter implements DynamoDBTypeConverter<Long, Date> {
    // 把Date转成Long时间戳存到DynamoDB
    @Override
    public Long convert(Date date) {
        return date != null ? date.getTime() : null;
    }

    // 把DynamoDB里的Long时间戳转成Date返回给业务层
    @Override
    public Date unconvert(Long timestamp) {
        return timestamp != null ? new Date(timestamp) : null;
    }
}

步骤2:在实体类的范围键上绑定转换器

修改你实体类中getCreatedAt方法的注解,加上@DynamoDBTypeConverted指定转换器:

@DynamoDBRangeKey
@DynamoDBAttribute(attributeName = "createdAt")
@DynamoDBTypeConverted(converter = DateToEpochTimestampConverter.class)
public Date getCreatedAt() {
    return pk != null ? pk.getCreatedAt() : null;
}

同时,PrimaryKey内部类里的createdAt字段不用改,Lombok的@Data会自动生成正确的getter,转换器会自动处理和DynamoDB字段的映射逻辑。

方案2:直接用Long类型存储,维护Date的便捷方法

如果不想写转换器,也可以直接把实体里的范围键改成Long类型,然后加个忽略DynamoDB映射的Date属性,方便业务层使用:

步骤1:修改PrimaryKey内部类

把createdAt字段改成Long类型,再加两个忽略映射的方法来处理Date和时间戳的转换:

@Data
@Builder
@DynamoDBDocument
@NoArgsConstructor
@AllArgsConstructor
public static class PrimaryKey implements Serializable {
    @DynamoDBHashKey
    private String bookId;
    @DynamoDBRangeKey
    private Long createdAtTimestamp; // 对应DynamoDB的N类型

    // 业务层用的Date属性,不映射到DynamoDB
    @DynamoDBIgnore
    public Date getCreatedAt() {
        return createdAtTimestamp != null ? new Date(createdAtTimestamp) : null;
    }

    @DynamoDBIgnore
    public void setCreatedAt(Date createdAt) {
        this.createdAtTimestamp = createdAt != null ? createdAt.getTime() : null;
    }

    // 重构of方法,支持传入Date自动转时间戳
    @DynamoDBIgnore
    public static Book.PrimaryKey of(String bookId, Date createdAt) {
        return Book.PrimaryKey.builder()
                .bookId(bookId)
                .createdAtTimestamp(createdAt != null ? createdAt.getTime() : null)
                .build();
    }
}

步骤2:修改实体类的getCreatedAt方法

让它返回Long类型的时间戳,对应DynamoDB的N类型:

@DynamoDBRangeKey
@DynamoDBAttribute(attributeName = "createdAt")
public Long getCreatedAt() {
    return pk != null ? pk.getCreatedAtTimestamp() : null;
}

// 保留set方法,业务层依然可以传Date
public Book setCreatedAt(final Date createdAt) {
    if (pk == null) {
        pk = new Book.PrimaryKey();
    }
    pk.setCreatedAt(createdAt);
    return this;
}

注意一个潜在的小坑!

我看到你实体类里的getbookId()方法名是小写b开头:

@DynamoDBHashKey
@DynamoDBAttribute(attributeName = "bookId")
public String getbookId() {
    return pk != null ? pk.getbookId() : null;
}

但Lombok的@Data注解会给bookId字段生成getBookId()(大写B开头)的getter,这会导致AWS SDK的DynamoDB映射找错方法,出现主键映射失败的问题。你应该把这个方法名改成getBookId(),和Lombok生成的保持一致:

@DynamoDBHashKey
@DynamoDBAttribute(attributeName = "bookId")
public String getBookId() {
    return pk != null ? pk.getBookId() : null;
}

public Book setBookId(final String bookId) {
    if (pk == null) {
        pk = new Book.PrimaryKey();
    }
    pk.setBookId(bookId);
    return this;
}

这样修改后,你的实体类就能正确把Date转成Epoch时间戳存到DynamoDB的createdAt字段里,也能正常从数据库读取转成Date返回给业务层啦。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 08:43:02