使用 HibernateORM 从 postgre 获取 TIMESTAMP 作为 LocalDatetime

发布于 2025-01-10 13:49:43 字数 3013 浏览 0 评论 0原文

我有这个 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

恰似旧人归 2025-01-17 13:49:43

你说:

Postgre 中 Expiration 和 DateCreated 列的数据类型都是“timestamp without time zone”

数据库中的类型错误

您的数据库列使用了错误的数据类型。

TIMESTAMP NOT TIME ZONE Postgres 类型故意缺少任何时区或相对于 UTC 的偏移量的概念。所以这个类型不能用来表示一个时刻,不能是时间轴上的一个特定点。

跟踪某个时刻(时间轴上的特定点)时,请始终使用 TIMESTAMP WITH TIME ZONE 类型的列。

Java 中的类型错误

同样,您使用了错误的 Java 类。

LocalDateTime 类故意缺少任何时区或相对于 UTC 的偏移量的概念。所以这个类型不能用来表示一个时刻,不能是时间轴上的一个特定点。

而是使用 OffsetDateTime 类从 带有时区的时间戳

OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;

避免遗留日期时间类

这两个 Date 类现在都是遗留的,几年前就被 JSR 310 中定义的现代 java.time 类取代。

没有必要使用遗留的类。它们的功能完全被 java.time 类取代。

  • java.util.Datejava.time.Instant 取代。
  • java.sql.Datejava.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:

Both the Expiration and DateCreated columns have data type "timestamp without time zone" in postgre

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 of TIMESTAMP WITH TIME ZONE.

OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;

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 by java.time.Instant.
  • java.sql.Date is replaced by java.time.LocalDate.

For database work, use:

  • java.time.OffsetDateTime for database columns of a type akin to the SQL-standard type TIMESTAMP WITH TIME ZONE.
  • java.time.LocalDateTime for database columns of a type akin to the SQL-standard type TIMESTAMP WITHOUT TIME ZONE.

JDBC 4.2+, Jakarta Persistence (JPA), and Hibernate have all been updated to support java.time.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文