使用 HibernateORM 从 postgre 获取 TIMESTAMP 作为 LocalDatetime
我有这个 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();,警告是警告的实例,会话是休眠会话。但是,尝试像这样从数据库获取警告实例
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:类 java.util.Date 无法转换为类 java.time.LocalDateTime (java.util.Date 和 java.time.LocalDateTime 位于加载程序“bootstrap”的 java.base 模块中)< /code>
Hibernate 似乎在将 LocalDatetime 插入数据库时没有问题,为什么我无法从数据库中取回一个?
在 postgre 中,Expiration 和 DateCreated 列的数据类型都是“timestamp without time zone”
I have this Hibernate model
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;
}
}
I can insert a new Warning into the database with session.save(warning); session.getTransaction().commit();
, warning being an instance of Warning and session being a hibernate session. However, trying to get an instance of Warning from the database like this
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();
}
results in the following error: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 seems to have no problem inserting a LocalDatetime into the database, why can't I get one back from the database?
Both the Expiration and DateCreated columns have data type "timestamp without time zone" in postgre
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
你说:
数据库中的类型错误
您的数据库列使用了错误的数据类型。
TIMESTAMP NOT TIME ZONE
Postgres 类型故意缺少任何时区或相对于 UTC 的偏移量的概念。所以这个类型不能用来表示一个时刻,不能是时间轴上的一个特定点。跟踪某个时刻(时间轴上的特定点)时,请始终使用
TIMESTAMP WITH TIME ZONE
类型的列。Java 中的类型错误
同样,您使用了错误的 Java 类。
LocalDateTime
类故意缺少任何时区或相对于 UTC 的偏移量的概念。所以这个类型不能用来表示一个时刻,不能是时间轴上的一个特定点。而是使用 OffsetDateTime 类从
带有时区的时间戳
。避免遗留日期时间类
这两个
Date
类现在都是遗留的,几年前就被 JSR 310 中定义的现代 java.time 类取代。没有必要使用遗留的类。它们的功能完全被 java.time 类取代。
java.util.Date
被java.time.Instant
取代。java.sql.Date
被java.time.LocalDate
替换。对于数据库工作,请使用:
java.time.OffsetDateTime
作为类似于 SQL 标准类型TIMESTAMP WITH TIME ZONE
类型的数据库列。java.time.LocalDateTime
用于类似于 SQL 标准类型TIMESTAMP NOT TIME ZONE
类型的数据库列。JDBC 4.2+,Jakarta 持久性 (JPA) 和 Hibernate 已全部更新以支持 java.time。
You said:
Wrong type in database
You are using the wrong data type for your database columns.
The
TIMESTAMP WITHOUT TIME ZONE
Postgres type purposely lacks any concept of a time zone or offset-from-UTC. So this type cannot be used to represent a moment, cannot be a specific point on the timeline.When tracking a moment, a specific point on the timeline, always use a column of type
TIMESTAMP WITH TIME ZONE
.Wrong type in Java
Likewise, you are using the wrong Java class.
The
LocalDateTime
class, purposely lacks any concept of a time zone or offset-from-UTC. So this type cannot be used to represent a moment, cannot be a specific point on the timeline.Instead use
OffsetDateTime
class to retrieve values from a column ofTIMESTAMP WITH TIME ZONE
.Avoid legacy date-time classes
Both
Date
classes are now legacy, years ago supplanted by the modern java.time classes defined in JSR 310.There is no need to use the legacy classes. Their functionality is entirely replaced by the java.time classes.
java.util.Date
is replaced byjava.time.Instant
.java.sql.Date
is replaced byjava.time.LocalDate
.For database work, use:
java.time.OffsetDateTime
for database columns of a type akin to the SQL-standard typeTIMESTAMP WITH TIME ZONE
.java.time.LocalDateTime
for database columns of a type akin to the SQL-standard typeTIMESTAMP WITHOUT TIME ZONE
.JDBC 4.2+, Jakarta Persistence (JPA), and Hibernate have all been updated to support java.time.