Exclude some fields from audit with Spring Data JPA #LastModifiedDate - java

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);

Related

How can I group by a date(timestamp_field ) in QueryDSL 5.0.0

How can I write a queryDSL query for the following MySQL query:
SELECT
u.id as user_id,
count(*) as total_completed
date(o.created_at) date
FROM
users u
LEFT JOIN orders o ON o.user_id = u.id
WHERE o.status='COMPLETED'
GROUP BY date(o.created), u.id
I am mainly interested in implementing the date(timestamp_field) so that I can use it for aggregating over entire dates.
This is my OrderEntity:
...
#Table(name = "orders")
public class OrderEntity extends BaseEntity {
#Id
#Column(nullable = false)
private String id;
private Instant createdAt;
...
}
This is in QOrderEntity
public final DateTimePath<java.time.Instant> createdAt = createDateTime("createdAt", java.time.Instant.class);
Basically, how can I truncate/type cast the SQL Timestamp field to DATE in the SELECT query. It needs to be done on the WHERE clause, GROUP BY clause, and SELECT clause
I tried this link here: QueryDSL - select rows with date from timestamp column
You can either use between or a custom expression if you use Querydsl SQL
Something like this
DateExpression<Date> converted = DateTemplate.create(Date.class, "convert(date, {0})",
The API doesn't have create() method, maybe it was removed.

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;
}

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!

hibernate HQL delete query nullifies single column

I am working on spring hibernate application and trying to delete from a table using non-id many-to-one relationship based column.
Entity classes are:
#Entity
public class Day {
#id(name = "DAY_ID")
dayId;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#JoinColumn(name = "DAY_ID")
List<Holiday> holidayList;
...
}
#Entity
public class Holiday {
#id(name="HOLIDAY_ID")
holidayId;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "DAY_ID")
Day day;
...
}
I am trying to delete a row from holiday table using hql.
String query = "DELETE FROM Holiday WHERE day.dayId = " + dayObject.getdayId();
Query holidayDeleteQuery = getSession().createQuery(query);
holidayDeleteQuery.executeUpdate();
In the console i am getting proper delete query but on checking DB found out that the row is still there but now the DAY_ID column in holiday table is null. I am not able to figure out why is this happening?
EDIT: help!!! My main problem is why DAY_ID column is changing to null value??
I'm not sure that this is your problem, but in your query you say "DELETE FROM Holidays ...", but your Class name is Holiday. In HQL you should be using Class names rather than table names or anything else. Is this typo in your code or just on here?
Actually after looking further there are a few more problems. This is how I'd write it:
String query = "DELETE FROM Holiday h WHERE h.day = :day";
Query holidayDeleteQuery = getSession().createQuery(query);
query.setParameter("day", dayObject);
holidayDeleteQuery.executeUpdate();
To break it down - use the Class name "Holiday", assign it an alias "h" then reference the day field of the Holiday object ("h.day") and compare it to the actual Day object you have.
What is your ONDELETE foreign key constrain? Might it that other part of your application inserting a row?

Categories

Resources