我需要访问一个现有的 MySQL 数据库,该数据库使用 BIGINT
列来存储时间戳:
create table mytable (created bigint);
现在我更喜欢使用 java.util.Date
或 java.time.Instant
实例而不是整数,所以我试图让 Hibernate 转换值直接地。不幸的是,当像这样注释时,Hibernate 将无法识别该列:
@Column(name = "created")
private Date created;
或者像这样:
@Column(name = "created")
@Temporal(TemporalType.TIMESTAMP)
private Calendar created;
这确实会在未来返回一些东西,比如 2017-07-01T04:14:00+02:00
。如何让 Hibernate 正确转换 BIGINT
列,这样我就不必在 getter 和 setter 中转换它们?
最佳答案
Hibernate 的 TemporalType.TIMESTAMP
映射到 java.sql.Timestamp
。 Timestamp
构造函数采用 Long 值,即自纪元以来的毫秒数。数据库中的值存储为 Unix 时间戳,即自纪元以来的秒数。
我写了一个 UnixTimestampType
,它需要几秒而不是几毫秒,并创建 Date
实例:
public class UnixTimestampType extends AbstractSingleColumnStandardBasicType<Date> implements IdentifierType<Date>, LiteralType<Date> {
private static final long serialVersionUID = 1L;
public static final UnixTimestampType INSTANCE = new UnixTimestampType();
public UnixTimestampType() {
super(UnixTimestampTypeDescriptor.INSTANCE, JdbcDateTypeDescriptor.INSTANCE);
}
@Override
public String getName() {
return "date";
}
@Override
public String[] getRegistrationKeys() {
return new String[] { getName(), java.sql.Date.class.getName() };
}
@Override
public String objectToSQLString(Date value, Dialect dialect) throws Exception {
final java.sql.Date jdbcDate = java.sql.Date.class.isInstance(value) ? (java.sql.Date) value : new java.sql.Date(value.getTime());
return StringType.INSTANCE.objectToSQLString(jdbcDate.toString(), dialect);
}
@Override
public Date stringToObject(String xml) {
return fromString(xml);
}
}
和
public class UnixTimestampTypeDescriptor implements SqlTypeDescriptor {
private static final long serialVersionUID = 1L;
public static final UnixTimestampTypeDescriptor INSTANCE = new UnixTimestampTypeDescriptor();
@Override
public int getSqlType() {
return Types.INTEGER;
}
@Override
public boolean canBeRemapped() {
return true;
}
@Override
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
return new BasicBinder<X>(javaTypeDescriptor, this) {
@Override
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options) throws SQLException {
Date date = javaTypeDescriptor.unwrap(value, Date.class, options);
date.setTime(date.getTime() / 1000);
st.setDate(index, date);
}
};
}
@Override
public <X> ValueExtractor<X> getExtractor(final JavaTypeDescriptor<X> javaTypeDescriptor) {
return new BasicExtractor<X>(javaTypeDescriptor, this) {
@Override
protected X doExtract(ResultSet rs, String name, WrapperOptions options) throws SQLException {
Date date = new Date(rs.getLong(name) * 1000);
return javaTypeDescriptor.wrap(date, options);
}
};
}
}
关于java - 在 JPA/Hibernate 中将 BIGINT 列用于 java.util.Date 或 java.time.Instant,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13647030/