Hibernate Timestamp to LocalDateTime conversion unexpected result - java

I've an issue with the conversion of 1000-01-01 00:00:00.0 to a LocalDateTime object. i've already checked the Oracle docs to see if maybe 1000-01-01 isn't supported, but that doesn't seem the problem.
The versions I'm using
hibernate-core: 5.2.1.Final
hibernate-commons-annotations: 5.0.1.Final
hsqldb: 2.3.4
spring-test-dbunit: 1.2.0
This is how startDate looks in MyEntity.class
#Basic
#Column(name = "start_date", nullable = false)
public LocalDateTime getstartDate() {
return startDate;
}
Hibernate creates it like this:
Query:[create table my_table (end_date timestamp not null, start_date timestamp not null)]
I've a (example) dataset with the following row
<my_table startDate="1000-01-01 00:00:00.0" endDate="4000-01-01 00:00:00.0" />
DBUnit is loading the data in an in memory database using Hibernate
Query:["insert into my_table(START_DATE, END_DATE) values (?, ?)"]
Params:[(1=1000-01-01 00:00:00.0,2=4000-01-01 00:00:00.0)]
In my JUnit test I fetch the data using an (Hibernate) Entitymanager and following named query:
#NamedQuery(
name = "MyTable.fetchAll",
query = "FROM MyTable m"
)
The select query (simplified):
Query:["select end_date as date_e12_4_, start_date as date_s13_4_ from my_table mytable0_"]
In my JUnit test I assert the returned result but I get an AssertionError:
java.lang.AssertionError:
Expected :MyEntity{startDate=1000-01-01T00:00, endDate=4000-01-01T00:00}
Actual :MyEntity{startDate=1000-01-05T23:09:21, endDate=4000-01-01T00:00}
My startDate 1000-01-01T00:00 becomes 1000-01-05T23:09:21.
The problem doesn't occur with the endDate.
Has anyone had this issue before? Or does anyone know how to solve it?
Please let me know if you need some more information.
Any help is greatly appreciated.
Update: it works when I use LocalDate instead of LocalDateTime.

For the new type from Java 8, you need another dependency from Hibernate.
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-java8</artifactId>
<version>5.0.1.Final</version>
</dependency>
After adding this, use LocalDateTime like normal Basic type.
private LocalDateTime validFrom;
Updated
I try to reproduce your situation.
Here is how i implemented the class.
#Entity
public class MyTable extends ABaseEntity {
private LocalDateTime startDate;
#Type(type="org.hibernate.type.LocalDateTimeType")
public LocalDateTime getStartDate() {
return startDate;
}
public void setStartDate(LocalDateTime startDate) {
this.startDate = startDate;
}
}
Data in database
ID STARTDATE
1 25-AUG-16 12.00.00.000000000 AM
The result when i read back
2016-08-25T00:00
Hope this will help!

Related

Spring JPA automatically fetch system time stamp from database

I'd like to fetch the current system timestamp: SELECT CURRENT_TIMESTAMP; automatically every time I run a select operation.
Sample code below:
SomeEntity.java
#Entity
#Table(name = "some_table")
public class SomeEntity {
#Column(name = "name", length = 500)
private String name;
#Column(name = "current_timestamp")
private LocalDate currentTimestamp;
}
The currentTimestamp column is not physically present in the table but I wish to get the CURRENT_TIMESTAMP value from the database to be populated in this field every time I perform a SELECT operation as below:
List<SomeEntity> records = someCrudRepository.findByName("someName")
OR List<SomeEntity> records = someCrudRepository.findAll()
In short, I'd like to run this query via Spring JPA: SELECT name, current_timestamp FROM some_table;
Is there any way to achieve the same except using native or jpql queries?
I don't want to use Java time library for getting the timestamp as that is not the overall purpose of getting the current timestamp.
Hibernate's #Formula is what you are looking for:
import org.hibernate.annotations.Formula;
public class SomeEntity {
...
#Formula("current_timestamp")
private LocalDate currentTimestamp;
}

Exclude some fields from audit with Spring Data JPA #LastModifiedDate

I have an entity called User. This entity contains several fields and one of them is lastModifiedDate:
#LastModifiedDate
#Column(name = "last_modified_date", columnDefinition = "DATETIME")
private ZonedDateTime lastModifiedDate;
Every time the table is updated, this field gets updated too. Which per se is fine.
The issue is that in the same entity I have also another field called loginTime:
#Column(name = "login_time", columnDefinition = "DATETIME")
private ZonedDateTime loginTime;
This field is updated whenever a new user logs into the application.
However, when users log in, since the loginTime field is updated, the field lastModifiedDate is also updated consequently.
Is there a way to prevent lastModifiedDate from being updated when specific fields (like loginTime) are updated?
Thank you
You can use JPQL update query using #Query to update only loginTime field then lastModifiedDate field will not be updated.
#Modifying
#Query("update User u set u.loginTime = :loginTime where u.id = :id")
int updateLoginTime(#Param("loginTime") ZonedDateTime loginTime, #Param("id") Integer id);

Hibernate expecting Date for Timestamp database column

I am using projections to retrieve a subset of columns into a DTO. Below is the DTO
QuestionPreviewDto.java
private Long id;
private String question;
private Timestamp datePosted;
public QuestionPreviewDto(Long id, String question, Timestamp datePosted){
this.id = id;
this.question = question;
this.datePosted = datePosted;
}
Database table
CREATE TABLE question
(
id BIGINT NOT NULL,
question varchar(250) NOT NULL,
date_posted TIMESTAMP,
.....
)
Below is the repository method to populate the DTO where QuestionEntity is the entity class mapped to the database table question.
#Query("select new QuestionPreviewDto(id, question, datePosted) from QuestionEntity where id = :id")
QuestionPreviewDto getQuestionPreview(#Param("id") Long id);
The query above give me the following error
Unable to locate appropriate constructor on class [QuestionPreviewDto]. Expected arguments are: long, java.lang.String, java.util.Date
[cause=org.hibernate.PropertyNotFoundException: no appropriate constructor in class: QuestionPreviewDto]
Not sure why Hibernate is expecting java.util.Date when type for datePosted is Timestamp in database and Java class ?
Inside the DTO you can use Date only with Temporal as Timestamp like below
#Temporal(TemporalType.TIMESTAMP)
private java.util.Date utilTimestamp;
While you save it in Date in DTO it will automatically converted in to timestamp its a timestamp in DB.
Make sure that your QuestionEntity
mapped properly according to O\R mapping documentation:
date, time, timestamp
Type mappings from java.util.Date and its subclasses to SQL types DATE, TIME and TIMESTAMP (or equivalent).
calendar, calendar_date
Type mappings from java.util.Calendar to SQL types TIMESTAMP and DATE (or equivalent).
https://docs.jboss.org/hibernate/core/3.3/reference/en/html/mapping.html#mapping-types-entitiesvalues
I had the same problem with my quarkus application using hibernate.
I solved it by changing the field in my DTO to Date and annotate it like this:
#Type(type="timestamp")
private Date datePosted;
This did not change the format of the timestamp, and my Entity class could still use the Timestamp type like this:
#Type(type="timestamp")
private Timestamp datePosted;
So apparently this workaround is only needed for DTO projection.

Select data with ZonedDateTime

I have object
...
#CreatedDate
#Column(name = "created_date", nullable = false)
#JsonIgnore
private ZonedDateTime createdDate = ZonedDateTime.now();
...
table - postgeSQL
create table inventory_request
(...
created_date timestamp,
.....
);
I need to select objects with databases between dates ZonedDateTime.now() and last year - ZonedDateTime.now().minusMonths(12)
my JPA repository
List<Inventory> findByCreatedDateBetween(ZonedDateTime now, ZonedDateTime end);
after execute i have only empty array, but values is present in database
I try use TimeStamp - 'java.lang.IllegalArgumentException: Parameter value [2018-11-20 14:44:23.528] did not match expected type [java.time.ZonedDateTime (n/a)]'
How is fix it? How to get the necessary data please help? Thanks!

Using joda DateTime in parameters for native query in spring-data-jpa fails because of bad binding

Here are two queries that should be exactly the same except one is marked as native and the other is not. The first one works fine, but the second one fails with incompatible data type in conversion
#Transactional(readOnly = true)
#Query(value = "select startDate from TaskMetrics where startDate between :startDate and :endDate")
List<DateTime> findStartDateByStartDateBetween(#Param("startDate") DateTime startDate,
#Param("endDate") DateTime endDate);
This generates the query:
select taskmetric0_.startDate as col_0_0_ from TaskMetrics taskmetric0_ where taskmetric0_.startDate between ? and ?
With bindings
binding parameter [1] as [TIMESTAMP] - [2015-02-02 10:57:14.279]
binding parameter [2] as [TIMESTAMP] - [2015-02-04 10:57:14.281]
-
#Transactional(readOnly = true)
#Query(nativeQuery = true, value = "select startDate from TaskMetrics where startDate between :startDate and :endDate")
List<DateTime> findStartDateBetween(#Param("startDate") DateTime startDate,
#Param("endDate") DateTime endDate);
This generates the query:
select startDate from TaskMetrics where startDate between ? and ?
With one binding, which also seems a bit odd (especially why #2?):
binding parameter [2] as [VARBINARY] - [2015-02-04T10:57:14.315-05:00]
I'm using Hibernate 4.3.8.Final as my JPA 2.1 provider and Jadira Usertype 3.1.0.CR10 for JodaTime support.
Am I doing something wrong or is this a bug somewhere?
Bug opened here - https://jira.spring.io/browse/DATAJPA-671
Workaround for the bug:
public class MyDaoClass {
// Converter provided by joda time user type library
private TimestampColumnDateTimeMapper columnDateTimeMapper = new TimestampColumnDateTimeMapper();
#Override
public void doAction(MyObject myObject) {
Query q = getEntityManager().createNamedQuery("MyNativeNamedQuery");
q.setParameter("date", columnDateTimeMapper.toNonNullValue(myObject.getDate()), TemporalType.TIMESTAMP);
q.executeUpdate(); // or select
}
The second one is a nativeQuery as i know the will not work with joda DateTime. use Java.sql.Date instead.

Categories

Resources