Spring JPA: Find all records from the past or now - spring-data-jpa

I have entity Ticket which has a field nextActionDate as Date/Timestamp.
I am heavily unclear how to select all records which are due to an update, i.e. is either now or in the past (with additional parameters).
In my JPARepository I want to annotate the method like
#Query("FROM Ticket t WHERE ... AND !t.nextActionDate.after(new Date())")
List<Ticket> findOpenedMail();
But this fails with expecting '=', found 't'. Also I am not sure if new Date() will be calculated at the time of query - or already pre-prepared when the Bean is created.
So, what is the correct syntax?

You can pass date parameter and use <, > operators in your query:
#Query("FROM Ticket t WHERE ... AND t.nextActionDate < :nextDate ")
List<Ticket> findOpenedMail(#Param("nextDate") Date nextDate);
and call yourRepository.findOpenedMail(new Date());

If you are using mysql you can try annother aproach by changing the date type to Long and save your date in seconds/milliseconds and use the mysql function UNIX_TIMESTAMP(NOW()) (now() is optional) in nativeQuery.
#Query(value = "select * from ticket t where... and t.next_action_date < UNIX_TIMESTAMP()", nativeQuery = true)
List<Ticket> findOpenedMail();
UNIX_TIMESTAMP() will return the current date in seconds.

Related

Spring JPA Hibernate giving error updating timestamp wo timezone in postgres

I have been trying to update timestamp field using an update stmt. I tried java.sql.timestamp, java.util.date, Calendar, LocalDateTime, ZonedDateTime and bunch of other java date util packages. None of them seem to be working.
Column: commit_ts (TimeStamp without Timezone in Postgresql) is defined in our JPA/Hibernate as
#Column(name = "COMMIT_TS")
#Temporal(TemporalType.TIMESTAMP)
private Timestamp commitTs;
here is the Query
#Timed(name = "updateWorkAllocationStatus")
#Transactional
#Modifying(clearAutomatically = true)
#Query(
nativeQuery = true,
value = "UPDATE wlm_work_allocation SET commit_ts=:ts " +
"WHERE allocation_id = :allocationId " +
"and status = :status " +
"and commit_ts == null"
)
int updateWorkAllocationStatus(
#Param("timestamp") Timestamp ts,
#Param("allocationId")Long allocationId,
#Param("status")String status
);
I also tried NativeQueries
#NamedNativeQuery(name = "WorkAllocationEntity.updateCommitTs",
query="UPDATE wlm_work_allocation SET commit_ts= TIMESTAMP WHERE allocation_id=:allocationId and status=:status and commit_ts==null")
Note: According to this link,The SQL standard requires that writing just timestamp be equivalent to timestamp without time zone, and PostgreSQL honors that behavior.
https://www.postgresql.org/docs/9.1/static/datatype-datetime.html
Springboot version :1.5.7.RELEASE
Postgres JDBC Driver : 9.0-801.jdbc4
PostgresSQL DB: 9.6.5
Error:
org.postgresql.util.PSQLException: ERROR: operator does not
exist: timestamp without time zone == unknown
Hint: No operator matches the given name and argument type(s).
You might need to add explicit type casts.
Can anyone help?
The comparison operator in JPQL and SQL is = not ==
commit_ts==null
should be
commit_ts is null

JPA-Query for a Date in a Datetime column

I'm trying to build a query for all orders which were created today.
My Order-Entity has a datetime field like this:
#Column(name = "OrderCreationDate")
#Temporal(TemporalType.TIMESTAMP)
private Date orderCreationDate;
Named-Query:
#NamedQuery(name = "OrderHeader.findByOrderCreationDate", query = "SELECT o FROM OrderHeader o WHERE o.orderCreationDate = :orderCreationDate")
I tried to build the query like this:
public List<OrderHeader> findFromToday() {
Date dateToday = new Date();
TypedQuery<OrderHeader> query = em.createNamedQuery("OrderHeader.findByOrderCreationDate", OrderHeader.class).setParameter("orderCreationDate", dateToday);
return query.getResultList();
}
Of course the ResultList is empty since the date AND time would have to match.
Unfortunately I need the time in my database, so the orderCreationDate needs to stay datetime/timestamp.
So how can I query for a specific date, ignoring the time?
thanks!
Your call to setParameter needs to pass in the temporal type argument also, defining what to use for comparison.
http://www.datanucleus.org/javadocs/javax.persistence/2.1/javax/persistence/Query.html#setParameter-java.lang.String-java.util.Date-javax.persistence.TemporalType-

How to compare timestamp with date without time in JPQL?

I'd like to get objects with create_date = :my_date where create_date is in 2014-12-02 14:49:15.029 format and my_date is in 2014-12-02 format in JPA.
Is there any way to compare timestamp column with Date object (yyyy-MM-dd format) in JPQL using NamedQuery or should I use native query?
If you are using jpql try to use
date(timestamp_column)
eg :
#Query(select te from Testentity te where date(te.createdTimestamp) >= CURRENT_DATE)
public List<Testentity> getTestDate()
You can use NamedQuery, you need to properly manipulate the #Temporal annotation and the TemporalType enum.
So if your object property is a Date without a time portion, you would annotate it as #Temporal(TemporalType.DATE), further on when supplying a parameter to your named query you would use one of the two available signatures
setParameter(String name, java.util.Date value, TemporalType temporalType)
setParameter(String name, java.util.Calendar value, TemporalType temporalType)
so your query will have a part like:
query.setParameter("my_date", myDate, TemporalType.DATE)

Using php DateTime object in mysql query

I'm trying to create a query that pulls information about sellers from my database, but only if their store has launched in the last 3 days. The easiest way I can think of to calculate the date for the query is using a new DateTime() object. When I output my code to test it, it's in the proper string for MySQL to query it with, but whenever I try to bind the variable, I get an error. I'm using Zend_Db to query, (PDO adapter)
action:
public function indexAction()
{
$dateMod = new DateTime();
$dateMod->modify('-2 days');
$dateMod->format('Y-m-d H:i:s');
// get sellers initialized in last 3 days
$sellerTable = new Application_Model_DbTable_Sellers();
$select = $sellerTable->select()->setIntegrityCheck(false);
$select->from(array('s' => 'seller'),array('sellerID', 'businessName'));
// select firstName, lastName, picture from user table, and businessName and sellerID from seller table.
$select->join(array('u' => 'user'), 's.userID = u.userID', array('firstName', 'lastName', 'picture'));
$select->where('s.active = 1 AND s.contentApproval = 1 AND s.paymentApproval = 1 AND s.featured = 1');
$select->where('s.launchDate > ?', $dateMod);
$select->order('s.launchDate DESC');
$newSellers = $sellerTable->fetchAll($select);
When I assign $dateMod to the view, it outputs the correct Y-m-d H:i:s format. But when I plug it into the query, I get the following error:
Message: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ') ORDER BY `b`.`launchDate` DESC' at line 2
If I hardcode a value into dateMod in the mysql timestamp format, the query works fine. How can I access just the string value of the timestamp in the DateTime object? getTimestamp returns a unix formatted timestamp, even after assigning a format.
The format() function returns the formatted date, so you need to assign that to a variable for use in the query:
$dateFormatted = $dateMod->format('Y-m-d H:i:s');
$select->where('s.launchDate > ?', $dateFormatted);

How to write JPA Query to the equivalent mysql query

I want to write equivalent JPA query to the following mysql query
select active_package,sum(duration),sum(charge),count(*)
from User
where call_type="MO"
and start_date between '2012-02-01' and '2012-02-09'
group by active_package;
For JPA Query the corresponding Attributes are below.
activePackage,callType,duration,charge,startDate
Entity class is User.
I want to use the createQuery() of JPA.
Can any one tell me or give me the link where can i find the solution for this.
Try this one, it should work, if not, please comment, we will get it work :).
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Tuple> cq = cb.createQuery(Tuple.class);
Root<User> entity = cq.from(User.class);
cq.multiselect(entity.get("activePackage"),
cb.sum(entity.get("duration").as(Long.class)),
cb.sum(entity.get("charge").as(Double.class),
cb.count(entity).as(Long.class)));
cq.where(cb.equal(entity.get("callType"), "MO"),
cb.between(entity.get("startDate").as(Date.class),
new Date(), new Date()));
cq.groupBy(entity.get("activePackage"));
List<Tuple> resultList = entityManager.createQuery(cq).getResultList();
for (Tuple result : resultList) {
System.out.println(result.get(0) + " " + result.get(1)
+ " " + result.get(2) + " " + result.get(3));
}
Also if you want to filter only by date, but have timestamp in your model, you can check this Compare date's date part only with Timestamp in Hibernate answer.
Also JPA provides constructing result classes as return values, so you can group your columns. Read more.