Unable to use OffsetDateTime as a query parameter using JPA Data/JPQL - java

I have an Entity CustomEntity with a data member updateDate of type OffsetDateTime.
I have defined a Repository for this Entity which has a simple method to retrieve list of records matching updateDate as
List<CustomEntity> findByUpdateDate(OffsetDateTime updateDate);
Now, when this method is called from Controller/Service bean, I can see no matching record is retrieved; however, when I execute the generated SQL in the DB, I can see matching rows available.
I can retrieve the records based on other data members of the entity; its just an issue with OffsetDateTime and LocalDateTime
I got to understand that java.time package support was not in JPA 2.1; however I am using JPA 2.3.1. Do I need to use Converters (as suggested for JPA 2.1?
Any help is much appreciable.
EDIT :-
Below is the code for Entity
#Entity
#Table(name = "SAMPLE_TABLE")
public class CustomEntity {
#Id
#GeneratedValue
private Long id;
#Column
private OffsetDateTime updateDate;
//Getters & Setters
}
I am using Microsoft SQL Server and the generated SQL query (hibernate generated) looks something like below
select sample0_.id as id1_10, sample0_.updateDate as update2_10 from sample_table sample0_ where sample0_.updateDate=?
binding parameter [1] as [TIMESTAMP] - [2021-07-27T17:22:34.597Z]

Related

Can I create a entity mapping to table which has a name from specific property of the entity?

For example, I have an entity below.
#Entity
public class Indexer
#NotNull #Id
private long id;
#Column
private string volumeKey;
}
I want to create a table with a ‘volumeKey’ property in this entity.
For example, A indexer has a ‘X12372’ as a volumeKey of property. I want this entity to be mapped to ‘INDEXER_X12372’.
And I tried to create custom NamingStrategy class for Indexer. And I can’t get an entity to be mapped in this class for making a table of name from.
You want the table to be used to be determined by a value of a property.
This is not possible with JPA or Spring Data JPA.
But some (many?) databases can do this transparently with partitioned tables.
See https://docs.oracle.com/cd/B28359_01/server.111/b32024/partition.htm for Oracle documentation as an example.
It should be easy enough to find a similar document for the database you use.

JPA: compare LocalDateTime attribute to builder.currentTimestamp()

Given:
#Entity
public class Paramter() {
#Id
private Long id;
private LocalDateTime startDate;
// getters & setters
}
// Extract from repository/dao method that grabs parameters:
...
final CriteriaBuilder builder = entityManager.getCriteriaBuilder();
final CriteriaQuery<Parameter> query = builder.createQuery(Parameter.class);
final Root<Parameter> param = query.from(Parameter);
// The line below is generates following compilation error due to mismatch
// of the types of LocalDateTime and Timestamp parameters:
// java: no suitable method found for greaterThanOrEqualTo(javax.persistence.criteria.Path<java.time.LocalDateTime>,javax.persistence.criteria.Expression<java.sql.Timestamp>)
query.where(builder.greaterThanOrEqualTo(param.get(Parameter_.startDate), builder.currentTimestamp())); ...
How to properly use java 8 date-time api (more specifically LocalDateTime property) with jpa criteria builder to achive: "select * from parameter where start_date >= sysdate"?
Please consider:
The solution can be Oracle specific but should use JPA criteria builder
I do not want to create a select query to grab the sysdate and than use it in another select query to grab the valid parameters. It should be done in one query like in the expected query example above.
The time from the server is not reliable - database time should be used
Using Hibernate 5.2.16 which seems to include JPA 2.1. Changing to JPA 2.2 doesn't seem to make a difference.

Mapping SQL-Server Datetime Column

I'm using Spring Boot with Spring Data JPA to map an Entity to a table in a SQL Server database for which I've created an #Embeddable composite key. There's a column I'd like to use as part of the key and according to SQuirreL its type name is datetime and the class name is java.sql.Timestamp. The key class looks like this:
#Embeddable
public class MyEntityIdentifier implements Serializable {
#Column(name = "LastUpdateDateTime")
private Timestamp lastUpdateDateTime;
...but the lastUpdateDateTime property always resolves to null without error. I've checked and there are no null fields for this column. I've also tried resolving to java.util.Date without success. Is there another type I should be using or something I'm doing wrong?
Hibernate will internally convert to a native Java type (i.e. java.util.Date as opposed to java.sql.Timestamp) by adding the #Temporal annotation.
#Column(name = "LastUpdateDateTime")
#Temporal(TemporalType.DATE)
private Date lastUpdateDateTime;

Skip a column on INSERT with JPA

I have a JPA/EclipseLink model with multiple parameters whose values are set as defaults by the PostgreSQL database. Specifically, I have:
An id column of type SERIAL which auto-increments when new rows are added
A created_at column of type TIMESTAMP which defaults to now()
My model looks like this:
import javax.persistence.*;
#Entity
#Table(name="entity")
#NamedQuery(name="Entity.findAll", query="SELECT e from Entity e")
public class Entity {
#Id #GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
#Column(name="created_at")
private java.sql.Timestamp createdAt;
// constructor, getters, and setters
}
When I try to insert a row with persist() in javax.persistence.EntityManager, the insertion fails because a NULL value is being set for the created_at column. Rather than inserting NULL, I want to simply not insert anything into that column and allow PostgreSQL to set it to now(). Essentially, I would like to use #GeneratedValue on createdAt, but that annotation is only for primary keys and cannot be used on multiple attributes. Is there another annotation I can use that will accomplish this?
You may want insertable=false in the Column annotation:
#Column(name="created_at", insertable=false)
private java.sql.Timestamp createdAt;
From: http://docs.oracle.com/javaee/5/api/javax/persistence/Column.html
boolean insertable
(Optional) Whether the column is included in SQL INSERT statements generated by the persistence provide
You can add #DynamicInsert on your entity class. The insert statement will include null fields when without this annotation. Also, you can add # DynamicUpdate when executing the update statement.
#Entity
#DynamicInsert
#DynamicUpdate
#Table(name="entity")
#NamedQuery(name="Entity.findAll", query="SELECT e from Entity e")
public class Entity {
#Id #GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
#Column(name="created_at")
private java.sql.Timestamp createdAt;
// constructor, getters, and setters
}
As mentioned in another answer, JPA providers will set the value on insert if you have it marked as insertable=true (the default). This occurs with many providers even if null as it allows statement reuse.
Just excluding it from the statement though might not be what you want, as to have the value in your entity (and in the cache) will require refreshing. EclipseLink though has #ReturningInsert which allows EclipseLink to update the entity with the value in the database. Unfortunately support is only for Oracle - other databases require use of stored procedures to return run the insert and return the value.

IntelliJ persistence tool type mapping

I have a PostgreSQL database schema. And I am trying to generate JPA entities from that schema in IntelliJ with the integrated persistence tool. Everything works fine, except the mapping of timestamps.
The persistence tool is trying to map the PostgreSQL TIMESTAMP data type to java.lang.Object or java.io.Serializable. I can't change the mapping to LocalDateTime, String or anything else.
Is there any way to set the correct mapping types?
UPDATE:
I get the following exception:
SchemaManagementException: Schema-validation: wrong column type encountered in column [timestamp] in table [ProcessEvent]; found [timestamptz (Types#TIMESTAMP)], but expecting [bytea (Types#VARBINARY)]
Have you used the proper annotation for the attribute?
#Entity
public class Employee {
...
#Basic
#Temporal(DATE)
private Calendar startDate;
...
}
Please see: https://en.wikibooks.org/wiki/Java_Persistence/Basic_Attributes#Temporal.2C_Dates.2C_Times.2C_Timestamps_and_Calendars

Categories