使用 Hibernate ORM 从 postgres 获取 TIMESTAMP 作为 LocalDatetime
Getting a TIMESTAMP from postgre as a LocalDatetime with HibernateORM
我有这个 Hibernate 模型
package net.nebulacraft.nebulous.Data.Models;
import org.bukkit.command.CommandSender;
import javax.persistence.*;
import java.time.LocalDateTime;
import java.util.UUID;
@Entity
@Table(name = "warning")
public class Warning {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "warningid")
int WarningId;
@Column(name = "userid")
UUID Player;
@Column(name = "rulenumber")
int RuleNumber;
@Column(name = "expiration")
LocalDateTime Expiration;
@Column(name = "datecreated")
LocalDateTime DateCreated;
@Column(name = "warnedby")
UUID WarnedBy;
@Column(name = "message")
String Message;
public UUID getPlayer() {
return Player;
}
public void setPlayer(UUID player) {
Player = player;
}
public int getRuleNumber() {
return RuleNumber;
}
public void setRuleNumber(int ruleNumber) {
RuleNumber = ruleNumber;
}
public LocalDateTime getExpiration() {
return Expiration;
}
public void setExpiration(LocalDateTime expiration) {
Expiration = expiration;
}
public LocalDateTime getDateCreated() {
return DateCreated;
}
public void setDateCreated(LocalDateTime dateCreated) {
DateCreated = dateCreated;
}
public UUID getWarnedBy() {
return WarnedBy;
}
public void setWarnedBy(UUID warnedBy) {
WarnedBy = warnedBy;
}
public String getMessage() {
return Message;
}
public void setMessage(String message) {
Message = message;
}
public int getWarningId() {
return WarningId;
}
public void setWarningId(int warningId) {
WarningId = warningId;
}
}
我可以使用 session.save(warning); session.getTransaction().commit();
将新警告插入数据库,警告是警告的实例,会话是休眠会话。但是,尝试从数据库中获取 Warning 的实例
public static List<Warning> GetWarnings(UUID player) {
var session = DbFactory.getSessionFactory().openSession();
var builder = session.getCriteriaBuilder();
var query = builder.createQuery(Warning.class);
var root = query.from(Warning.class);
query.select(root);
query.where(
builder.and(
builder.equal(root.get("Player"), player),
builder.greaterThan(root.get("Expiration"), new Date())
)
);
query.orderBy(builder.desc(root.get("DateCreated")));
return session.createQuery(query).getResultList();
}
导致以下错误:
java.lang.ClassCastException: class java.util.Date cannot be cast to class java.time.LocalDateTime (java.util.Date and java.time.LocalDateTime are in module java.base of loader 'bootstrap')
Hibernate 向数据库中插入一个 LocalDatetime 似乎没有问题,为什么我不能从数据库中取回一个?
在 postgre 中,Expiration 和 DateCreated 列的数据类型都是“timestamp without time zone”
你说:
Both the Expiration and DateCreated columns have data type "timestamp without time zone" in postgre
数据库类型错误
您为数据库列使用了错误的数据类型。
TIMESTAMP WITHOUT TIME ZONE
Postgres 类型故意缺少任何时区或 offset-from-UTC 的概念。所以这个类型不能用来表示一个时刻,不能是时间轴上的一个具体点。
跟踪时间轴上特定点的时刻时,始终使用 TIMESTAMP WITH TIME ZONE
.
类型的列
输入错误 Java
同样,你用错了Java class.
LocalDateTime
class 故意缺少任何时区或 offset-from-UTC 的概念。所以这个类型不能用来表示一个时刻,不能是时间轴上的一个具体点。
而是使用 OffsetDateTime
class 从 TIMESTAMP WITH TIME ZONE
.
的列中检索值
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
避免遗留 date-time classes
这两个 Date
classes 现在都是遗留的,多年前被现代 java.time classes 所取代JSR 310.
无需使用旧版 classes。它们的功能完全被 java.time classes.
取代
java.util.Date
替换为 java.time.Instant
。
java.sql.Date
替换为 java.time.LocalDate
。
对于数据库工作,使用:
java.time.OffsetDateTime
用于类似于 SQL-standard 类型的数据库列 TIMESTAMP WITH TIME ZONE
.
java.time.LocalDateTime
用于类似于 SQL-standard 类型的数据库列 TIMESTAMP WITHOUT TIME ZONE
.
JDBC 4.2+, Jakarta Persistence (JPA), and Hibernate全部更新支持java.time.
我有这个 Hibernate 模型
package net.nebulacraft.nebulous.Data.Models;
import org.bukkit.command.CommandSender;
import javax.persistence.*;
import java.time.LocalDateTime;
import java.util.UUID;
@Entity
@Table(name = "warning")
public class Warning {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "warningid")
int WarningId;
@Column(name = "userid")
UUID Player;
@Column(name = "rulenumber")
int RuleNumber;
@Column(name = "expiration")
LocalDateTime Expiration;
@Column(name = "datecreated")
LocalDateTime DateCreated;
@Column(name = "warnedby")
UUID WarnedBy;
@Column(name = "message")
String Message;
public UUID getPlayer() {
return Player;
}
public void setPlayer(UUID player) {
Player = player;
}
public int getRuleNumber() {
return RuleNumber;
}
public void setRuleNumber(int ruleNumber) {
RuleNumber = ruleNumber;
}
public LocalDateTime getExpiration() {
return Expiration;
}
public void setExpiration(LocalDateTime expiration) {
Expiration = expiration;
}
public LocalDateTime getDateCreated() {
return DateCreated;
}
public void setDateCreated(LocalDateTime dateCreated) {
DateCreated = dateCreated;
}
public UUID getWarnedBy() {
return WarnedBy;
}
public void setWarnedBy(UUID warnedBy) {
WarnedBy = warnedBy;
}
public String getMessage() {
return Message;
}
public void setMessage(String message) {
Message = message;
}
public int getWarningId() {
return WarningId;
}
public void setWarningId(int warningId) {
WarningId = warningId;
}
}
我可以使用 session.save(warning); session.getTransaction().commit();
将新警告插入数据库,警告是警告的实例,会话是休眠会话。但是,尝试从数据库中获取 Warning 的实例
public static List<Warning> GetWarnings(UUID player) {
var session = DbFactory.getSessionFactory().openSession();
var builder = session.getCriteriaBuilder();
var query = builder.createQuery(Warning.class);
var root = query.from(Warning.class);
query.select(root);
query.where(
builder.and(
builder.equal(root.get("Player"), player),
builder.greaterThan(root.get("Expiration"), new Date())
)
);
query.orderBy(builder.desc(root.get("DateCreated")));
return session.createQuery(query).getResultList();
}
导致以下错误:
java.lang.ClassCastException: class java.util.Date cannot be cast to class java.time.LocalDateTime (java.util.Date and java.time.LocalDateTime are in module java.base of loader 'bootstrap')
Hibernate 向数据库中插入一个 LocalDatetime 似乎没有问题,为什么我不能从数据库中取回一个?
在 postgre 中,Expiration 和 DateCreated 列的数据类型都是“timestamp without time zone”
你说:
Both the Expiration and DateCreated columns have data type "timestamp without time zone" in postgre
数据库类型错误
您为数据库列使用了错误的数据类型。
TIMESTAMP WITHOUT TIME ZONE
Postgres 类型故意缺少任何时区或 offset-from-UTC 的概念。所以这个类型不能用来表示一个时刻,不能是时间轴上的一个具体点。
跟踪时间轴上特定点的时刻时,始终使用 TIMESTAMP WITH TIME ZONE
.
输入错误 Java
同样,你用错了Java class.
LocalDateTime
class 故意缺少任何时区或 offset-from-UTC 的概念。所以这个类型不能用来表示一个时刻,不能是时间轴上的一个具体点。
而是使用 OffsetDateTime
class 从 TIMESTAMP WITH TIME ZONE
.
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
避免遗留 date-time classes
这两个 Date
classes 现在都是遗留的,多年前被现代 java.time classes 所取代JSR 310.
无需使用旧版 classes。它们的功能完全被 java.time classes.
取代java.util.Date
替换为java.time.Instant
。java.sql.Date
替换为java.time.LocalDate
。
对于数据库工作,使用:
java.time.OffsetDateTime
用于类似于 SQL-standard 类型的数据库列TIMESTAMP WITH TIME ZONE
.java.time.LocalDateTime
用于类似于 SQL-standard 类型的数据库列TIMESTAMP WITHOUT TIME ZONE
.
JDBC 4.2+, Jakarta Persistence (JPA), and Hibernate全部更新支持java.time.