I have a table with users and are trying to get a list with the people who have birthday today so the app can send an email.
The User is defined as
#Entity
public class User {
#Size(max = 30)
#NotNull
private String name;
[...]
#Temporal(TemporalType.DATE)
#DateTimeFormat(style = "S-")
protected Date birthday;
}
and I've got a method which returns the people which were born today like so
#SuppressWarnings("unchecked")
public static List<User> findUsersWithBirthday() {
List<User> users =
entityManager().createQuery("select u from User u where u.birthday = :date")
.setParameter("date", new Date(), TemporalType.DATE)
.getResultList();
return users;
}
This is fine and all for finding people which were born today, however tha's not really that useful, so I've been struggling for a way to find all the users that were born today, independent of the year.
Using MySQL there's functions I can use like
select month(curdate()) as month, dayofmonth(curdate()) as day
However I've been struggling to find a JPA equivalent to that.
I'm using Spring 3.0.1 and Hibernate 3.3.2
I don't know how to do that in JPQL but HQL has day() and month() functions so you could run:
from User u
where day(u.birthday) = day(CURRENT_DATE)
and month(u.birthday) = month(CURRENT_DATE)
If using HQL is not an option, I would go for a native query.
Related
In my reservation-entity i have a column "bookingDate" --> example: "2021-05-10 12:00:00".
So in this object the date and starttime of an user-booking gets displayed.
If a user wants to book a timeslot, i want to check first if the selected timeslot is empty. So i want to query the database by date&startTime.
I tried it with https://www.baeldung.com/spring-data-jpa-query-by-date , but it didnt work. I got the errors: "The annotation #Temporal is disallowed for this location" & "#Temporal cant be used for variables"
these are the relevant classes:
Reservation.java
#Entity
public class Reservation {
#Id #GeneratedValue
private int reservationId;
#DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
private LocalDateTime bookingDate;
private int court = 1;
private String playerNames;
private int userIdReservation;
//getter and setters
With the method "findByBookingDate()" i want to query the database, if the selected timeslot is empty...
VerificationClass.java
public boolean validateReservation(Reservation r) {
LocalDateTime tempDate = r.getBookingDate();
if(reservationRepository.findByBookingDate(tempDate)){ // todo: + and Court
logger.getLogger().info(this.getClass().getName() + "||Booking Slot is empty -- Reservation created||");
return true;
}
logger.getLogger().info(this.getClass().getName() + "||Booking Slot is full -- Reservation failed||");
return false;
}
ReservationRepository.java
#Repository
#Repository
public interface ReservationRepository extends JpaRepository<Reservation, Integer>{
#Query("Select r from reservation r where r.booking_date = :tempDate")
boolean findByBookingDate(#Param("tempDate") LocalDateTime tempDate);
}
If I run it like this i always get an "org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'backyardcodersSpringReactApplication'" --> so the application does not successfully start up.
Im very thankful for every tip and critique!
cheers!
Not understood completely. this is just a lead maybe not a perfect solution.
You can use java.time.LocalDateTime . and annotation be like #DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME).
And the query should be like. [the query will check all the reservation for that day]
Select
from reservation_table
Where
timeSlot between ‘2021-05-10 00:00:00’ and ‘2021-05-10 23:59:59’
I copied your code in my local file. Instead of
import org.springframework.data.jpa.repository.Temporal;
I used
import javax.persistence.Temporal;
in your Reservation.java file.
Also this is my very first answer on Stackoverflow.
First of all #Temporal have three different arguments and it can be applied to the variable of type date , time and time stamp.
Usage
#Temporal(Temporal type.DATE)
private Date date;
#Temporal(Temporal type.TIMESTAMP) // INSERT BOTH DATE WITH TIME TILL MILLISECONDS
private Calendar date;
Why not just just extract the localdate from your LocalDateTime and pass it on? and extract the hour and pass it on and query 2 different columns with it.
LocalDateTime.toLocalDate()
LocalDateTime.getHour()
#Repository
public interface PostRepository extends JpaRepository {
Page<Post> findAllByCategory(Pageable pageable, Category category);
LocalDate dateBefore4Hours = LocalDate.now().minus(4, ChronoUnit.HOURS); //tried but couldnt figured it out
#Query("SELECT a FROM Post a WHERE a.createdDate ") //none of sql keywords i've tried here didnt wor
Page<Post> findAllWithCreationDateTimeInLastFourHours();
}
If you need to compare time you may use LocalDateTime, because LocalDate don't have the time component. So to get the LocalDateTime of 4 hours ago you can do this:
LocalDateTime currentTimeMinus4Hours = LocalDateTime.now().minusHours(4L);
Then you can just use that in your query and sort the column, just like so:
#Query("SELECT a FROM Post a WHERE a.createdDate > :currentTimeMinus4Hours ORDER BY a.createdDate")
Page<Post> findRecentPosts(LocalDateTime currentTimeMinus4Hours);
I have a web app hosted on Google App Engine with a datastore containing some tables. The table I'm querying is Towns. I want to get all towns of x name. In the datastore, I can see the following columns: ID/Name, date, town.
#Entity
public class Town {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Key key;
private String Name;
private String Date;
// getters, setters
}
My query is as follows:
EntityManager em = EMF.get().createEntityManager();
Query q = em.createQuery("SELECT t FROM Towns t WHERE t.name LIKE :townName ORDER BY c.date")
.setParameter("townName", name);
List<Town> townLogs = new ArrayList<Town>(q.getResultList());
However, I get the following error:
org.datanucleus.exceptions.NucleusUserException: Cannot find type of (part of) t.name since symbol has no type; implicit variable?
Change the case of Name to name & Date to date. That should help you get around the issue that you are facing.
The next issue that you are likely to face is with the implicit reference of "c". That should also ideally be t.date
Hope that helps.
I am playing around with JPA and other Java EE 6 stuff, but now I am facing some problems with a types query using the criteria Builder.
The business case for my poc is a twitter clone, so I have users which has a list of subscribers and subscriptions and I got Tweets.
#Entity
public class Tweet {
#Id #GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
#ManyToOne
private TwitterUser author;
#ManyToOne
private TwitterUser receiver;
#Temporal(TemporalType.TIMESTAMP)
private Date datetime;
private String message;
}
#Entity
public class TwitterUser {
#Id #GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String username;
private String displayname;
private String password;
private String email;
#Temporal(TemporalType.TIMESTAMP)
private Date since;
#ManyToMany(cascade=CascadeType.ALL)
private List<TwitterUser> subscriptions;
#ManyToMany(mappedBy = "subscriptions")
private List<TwitterUser> subscribers;
}
The datamodel generated by JPA consists of 3 tables: Tweet, TwitterUser and TwitterUser_TwitterUser. Everything's fine so far. Basic queries do work well.
Now I want to select all Tweets for a timeline, what means all tweets of users, who are in the list of subscriptions of the current logged in user. I thought of a solution by using a subselect, so my sql would look like:
select * from TWEET where author_id in (
select subscriptions_ID from TWITTERUSER_TWITTERUSER where subscribers_ID = ?loggedInUserId);
This query works well, but I have no idea how to write it down using the CriteriaBuilder and generics. I don't even get a compilable piece of code that could fail at some other point, because I am not sure what the type of the subquery should be.
I was searching through lots of examples now, but they are mostly just using raw-types or using the subquery for retrieving the element of the lefthand-side of the in-clause.
Maybe I miss the wood for trees but I am really perplexed here. :(
In JPQL, one way of expressing this would be something akin to the following:
SELECT
tweet
FROM
Tweet tweet JOIN tweet.author author
WHERE
EXISTS (
SELECT
user
FROM
TwitterUser user JOIN user.subscriptions subscriber
WHERE
user = :loggedinUser AND
subscriber = author
)
As Criterias following the JPQL model almost directly, maybe this gets you started.
So thanks again to you guys helping me. I finally managed to find a solution with your input and it looks as follows:
public List<Tweet> findAllForSubscriber(TwitterUser user) {
// Select tweets
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Tweet> cq = cb.createQuery(Tweet.class);
Root<Tweet> tweet = cq.from(Tweet.class);
cq.select(Tweet);
// Select subscribers of user
Subquery<Long> sq = cq.subquery(Long.class);
Root<TwitterUser> twitterUser = sq.from(TwitterUser.class);
Join<TwitterUser, TwitterUser> subscriptions = twitterUser.join(TwitterUser_.subscriptions);
sq.select(subscriptions.get(TwitterUser_.id));
sq.where(cb.equal(twitterUser, user));
// Where authorId in list of subscribers
cq.where(cb.in(tweet.get(Tweet_.author).get(TwitterUser_.id)).value(sq));
//
return em.createQuery(cq).getResultList();
}
My drawbacks were:
The Criteria API is just able to
do a compare of objects within an
equal() but not within a in()
statement. But I did not get a
helpful exception, all that was
generated was a wrong query (eclipselink & derby) :(
The in() statement
takes the lefthand-side of the in
statement, the value statement takes
the list of possibilities, the
wording confused me.
I cannot simply access the ids
of all subscriptions, I have to use a
join. It's quite clear if you think
about the table structure but I
missed that when simply thinking of
my objects.
P.S.: My solution totally misses to select the tweets of the user himself! ^^
There is a similar Criteria query example here,
http://en.wikibooks.org/wiki/Java_Persistence/Querying#Subselect.2C_querying_all_of_a_ManyToMany_relationship
Following class structure is given:
class Job
{
String description;
Collection<JobHistory> history;
}
class JobHistory
{
Date assignDate;
User jobOwner;
}
class JobOwner
{
String name;
String id;
}
This class-structure is accessible on the db via JPA. In the DAO-Layer I can write queries in JPA syntax.
The Problem: I want a list with Job and JobHistory entries for a given owner with given id and who is the last one in the Jobhistory of the job (ordered by assignDate). Sounds quite complicated, perhaps simpler: give me all jobs and JobHistory where specified owner is the actual owner of the job.
Update: for clarity I will slightly change the names of the classes.
class Job
{
String description;
Collection<JobOwnerHistory> history;
}
class JobOwnerHistory
{
Date assignDate;
User jobOwner;
}
class JobOwner
{
String name;
String id;
}
Every Job has a history of his owners sorted by assignDate. The actual owner got the job last assigned (i.e. MAX(assignDate)). I want find for every job the JobOwnerHistory entry with MAX(assignDate) for a specific user User.
I found the following answer for the query:
SELECT j, h FROM Job j JOIN j.history h JOIN h.jobOwner u
WHERE u.name = :name AND
(SELECT MAX(h2.assignDate) FROM Job j2 JOIN j2.history h2
WHERE h2 member of j.history) = h.assignDate
The most important part in the query is the subselect with MAX(h2.assignDate) because I want to get the job and the newest entry in the owner-history.
Try:
SELECT j, j.history FROM Job j JOIN User u WHERE u.name = :name
If I were to do this in EclipseLink, I would change it slightly:
public List<Job> getAllJobsForUser(String username) {
List<Job> jobs = entityManager
.createQuery("SELECT j FROM Job j JOIN User u WHERE u.name = :name")
.setParameter("name", username)
.setHint(QueryHints.BATCH, "j.history")
.queryForList();
}
The difference? In the first version, you're returning two objects, so you have to retrieve them from a List or Object arrays whereas in the second, the query hint just loads all the job histories from an (assumedly) lazyy one-to-many relationship.
I don't know if Hibernate has an equivalent to this. Toplink Essentials doesn't. But it's one of my favourite features of EclipseLink.
Oh and obviously you can (and probably should) use a named query instead of an adhoc query like I've done (since those can be verified during the build).