Spring JPA automatically fetch system time stamp from database - java

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

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.

How to get total average value from subquery average collection using querydsl

I have the next entity:
#Entity
#Table(name = "search_request_items")
public class SearchRequestItem extends LongIdEntity {
#Column(name = "date")
private Instant date;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "user_id")
private User user;
#Column(name = "result_count")
private Long resultCount;
/**
* Request's text.
*/
#Column(name = "request")
private String request;
/**
* Request's quality. It may take 0 or 1.
*/
#Column(name = "quality")
private Integer quality;
...
}
Then i have the next queryDSL query, which return collection of quality avg and user count grouped by request' text:
public JPAQuery<Tuple> prepareTotalQuery() {
QSearchRequestItem requestItem = QSearchRequestItem.searchRequestItem;
QUser user = QUser.user;
NumberExpression<Double> qualityAvgExpression = requestItem.quality.avg();
NumberExpression<Long> qualityCountExpression = requestItem.user.countDistinct();
JPAQuery<Tuple> query = queryFactory
.select(qualityAvgExpression, qualityCountExpression)
.from(requestItem)
.leftJoin(requestItem.user, user)
.groupBy(requestItem.request)
.having(qualityAvgExpression.isNotNull(),
qualityCountExpression.gt(2));
return query;
}
But i need to return total avg upon this collection just like this native query:
select avg(n1.avg_quality)
from (select count(distinct user_id), avg(quality) as avg_quality
from search_request_items
group by request
having avg(quality) is not null and count(distinct user_id) > 2
) n1;
So, how to update my querydsl query to get this result?
This issue here is that you're using JPA and JPA doesn't allow to use subqueries as join target in the from clause.
Blaze-Persistence is an extension of JPA and integrates well with Hibernate. It adds Common Table Expressions and subselect (even lateral) joins to JPQL. Blaze-Persistence also has a Querydsl integration, allowing you to write a query like the following:
List<Number> fetch = new BlazeJPAQuery<>(entityManager, cbf)
.with(cteType, new BlazeJPAQuery<>()
.bind(cteType.avgQuantity, requestItem.quality.avg())
.from(requestItem)
.leftJoin(requestItem.user, user)
.groupBy(requestItem.request)
.having(qualityAvgExpression.isNotNull(), qualityCountExpression.gt(2))))
)
.select(cteType.avgQuantity.avg())
.from(cteType) ​
​.fetch();
However, with plain JPA and Hibernate, there is no simple way to do this.
Provided that you're only averaging a set of numbers though, which are not intensive to serialize over JDBC and do not suffer from potential N+1 issues, I'd suggest to simply do the final average step in memory:
queryFactory
.select(qualityCountExpression)
.from(requestItem)
.leftJoin(requestItem.user, user)
.groupBy(requestItem.request)
.having(qualityAvgExpression.isNotNull(),
qualityCountExpression.gt(2))
.stream()
.collect(Collectors.averagingDouble(i -> i.doubleValue()))

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

Jpa create native query from form input

Usually during my work hours i spend a lot of time querying the db(oracle) and parsing blob from various table where the streams that we receive are stored.
There are various type of stream so i was trying to made a simple webapp where i write the select statement and it returns all the stream parsed accordingly.
My problem is that using jpa and executing the simple native query:
select B_BODY from TABLE_B where TRANSACTION_ID = 'GG-148c-01502790743907855009';
the statement doesn't return anything but querying directly the database return the record.
this is my java code:
#Transactional(readOnly = true)
public List<Object[]> retrieveBlobs(String squery) {
squery = squery + " and rownum <= "+maxResults;
Query query = em.createNativeQuery(squery);
List<Object[]> resultList = query.getResultList();
return resultList;
}
this is the sql generated:
Hibernate:
select
B_BODY
from
TABLE_B
where
TRANSACTION_ID ='GG-148c-01502790743907855009'
and rownum <= 100
i know that this way might seems weird but our team spend a lot of time trying to tokenize the stored streams(the code that identify how to parse the stream is also stored in the tables).Useless to say this application is going to be used only internally.there is a way to just execute the query as it is and retrieve the correct output?
Well, I tried to reproduce your problem on MariaDB (with mysql-connector-java + hibernate) but selecting a lob with native query was working properly.
You can try to create entities which will be holding your blob and check if this would help. Just make a standard entity with #Lob annotation over your lob column.
#Entity
#NamedQueries(
#NamedQuery(name = FIND_ALL, query = "SELECT m FROM LobEntity m")
)
public class LobEntity {
public static final String FIND_ALL = "PhpEntity.findAll";
#Id
#Column(name = "id")
private String id;
#Lob
#Column(name = "lob")
private byte[] lob;
//Use Blob class if you want to use streams.
//#Column(name = "lob")
//#Lob
//private Blob lob;
}

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