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
CodePudding user response:
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 ) ;