Select data with ZonedDateTime - java

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!

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.

Hibernate Timestamp to LocalDateTime conversion unexpected result

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!

Hibernate Incorrect datetime value

Hoping someone can clear this up for me. I'm getting some warnings when I run a unit test that is using hibernate criteria. The specific warnings are:
Mar 10, 2016 11:48:31 AM org.hibernate.engine.jdbc.spi.SqlExceptionHelper$StandardWarningHandler logWarning
WARN: SQL Warning Code: 1292, SQLState: 22007
Mar 10, 2016 11:48:31 AM org.hibernate.engine.jdbc.spi.SqlExceptionHelper$StandardWarningHandler logWarning
WARN: Incorrect datetime value: '1454684370' for column 'date_created' at row 1
Mar 10, 2016 11:48:31 AM org.hibernate.engine.jdbc.spi.SqlExceptionHelper$StandardWarningHandler logWarning
WARN: SQL Warning Code: 1292, SQLState: 22007
Mar 10, 2016 11:48:31 AM org.hibernate.engine.jdbc.spi.SqlExceptionHelper$StandardWarningHandler logWarning
WARN: Incorrect datetime value: '1454684700' for column 'date_created' at row 1
I can't figure out what Hibernate is complaining about. The column it's talking about, 'date_created', is of type datetime. I've tried passing in every other version of the date object, a string, a java.util.Date, a java.sql.Timestamp, but those just cause actual errors. Specifically they cause:
java.lang.ClassCastException: java.sql.Timestamp cannot be cast to java.lang.Long
or, of course, whatever other type I tried passing instead of Long. The times I'm passing in are epoch times but for some reason I'm getting these errors and the unit tests aren't passing.
Also, in case it might help, here is the specific code in the tests:
public List<Content> findByCollectionName(String collectionName, Long exclusiveBegin, Long inclusiveEnd, Long expiration)
{
if(collectionName == null)
return null;
Session session = currentSession();
session.beginTransaction();
Criteria criteria = session.createCriteria(Content.class).setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
criteria.createAlias("collections", "cols");
criteria
.add(Restrictions.and(Restrictions.eq("cols.name", collectionName), buildCriterion(exclusiveBegin, inclusiveEnd, expiration)));
List<Content> list = criteria.list();
session.getTransaction().commit();
return list;
}
private Criterion buildCriterion(Long exclusiveBegin, Long inclusiveEnd, Long expiration)
{
List<Criterion> criterion = new ArrayList<Criterion>();
if(exclusiveBegin != null)
criterion.add(Restrictions.gt("dateCreated", exclusiveBegin));
if(inclusiveEnd != null)
criterion.add(Restrictions.le("dateCreated", inclusiveEnd));
if(expiration != null)
criterion.add(Restrictions.ge("dateCreated", expiration));
Criterion[] array = new Criterion[criterion.size()];
for(int j = 0; j < array.length; j++)
{
array[j] = criterion.get(j);
}
return Restrictions.and(array);
}
EDIT Sorry for the delay, here's the requested additions.
#Entity
#Table(name = "content")
public class Content implements Serializable
{
private static final long serialVersionUID = -8483381938400121236L;
public Content()
{
}
public Content(String messageId, ContentBlock block) throws NullPointerException
{
if(messageId == null || block == null)
throw new NullPointerException("Null objects passed for Content object creation");
this.messageId = messageId;
this.setContentBlock(block);
this.dateCreated = System.currentTimeMillis();
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", columnDefinition = "BIGINT UNSIGNED")
private int id;
#Column(name = "message_id")
private String messageId;
#Column(name = "date_created")
private long dateCreated;
#Column(name = "content_wrapper", columnDefinition = "longblob")
private byte[] contentWrapper;
#ManyToMany(mappedBy = "contentBlocks")
private List<TCollection> collections;
/*#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "message_id")
private TMessage message;*/
I omitted the getters and setters for brevity
As for the database, it's got a regular structure. The TContent table has:
column type
id bigint
user_id int
name varchar
date_created datetime
collection_wrapper longblob
tspoll_expire decimal
Please let me know if I can add anything else or have missed anything. Thanks for taking a look.
In the past I've used the following, which successfully converts between MySQL datetime field and java.util.Date:
#Temporal(TemporalType.TIMESTAMP)
private Date dateTime;
And more recently with Joda-time, the following successfully converts between MySQL 5.7 datetime(3) and org.joda.time.DateTime:
#Column(columnDefinition = "DATETIME(3)")
private DateTime dateTime;
There will be other options but these are the two I'm currently familiar with.
Hibernate has a bug (sort of) when parameter hibernate.hbm2ddl.auto set to update If table contains filed with the same name, for example from previous deployment, it just leave field 'as is' and doesn't change field type.
I think, previously you set date_created as Date type, but later switch it to long.
Possible solutions:
change java bean field type long dateCreated; to Date dateCreated; and work with Date type in code.
manually change database structure accordinly to your java classes. alter table content alter column date_created TYPE bigint I doesn't sure mysql allow to do it, in that case you should write migration procedure.
drop database and recreate it with hibernate (only if content not important/test/garbage)

Categories

Resources