Find next Date/Time in JPA query - java

I need to return the next meeting for a user. For example, to userId 1, the next meeting will be today (MeetingId 1), because today is 02-12-2019 13:12PM. If I search for the next meeting today at 15:00PM, the next meeting will be at 09-12-2019 (MeetingiD 2). If I search for the next meeting tomorrow, the next meeting will be at 09-12-2019 (MeetingiD 2).
I'm using MYSQL database and the query (but I don't know how to search exactly):
#Query(select m from meeting m inner join m.group g inner join g.user u where u.id = :userId order by m.meetingDate desc)
Meeting getNextMeeting(#Param(userId) long userId)
public class Meeting {
#Id
#GeneratedValue(strategy= GenerationType.IDENTITY)
private long id;
#OneToMany()
private Group group;
private Date meetingDate;
private Time meeting;
}
public class Group {
#Id
#GeneratedValue(strategy= GenerationType.IDENTITY)
private long id;
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "userId",nullable = false)
private User user;
}
public class User {
#Id
#GeneratedValue(strategy= GenerationType.IDENTITY)
private long id;
}

To get only one next meeting, You need to filter out all the future event using the below condition and limit 1.
Below query works, if you are using Postgres
(date m.date + time m.time) > CURRENT_TIMESTAMP and limit 1

Mysql has now() function that returns current date.
Ref: https://www.w3schools.com/sql/func_mysql_now.asp
Try this query:
#Query("select m from meeting m inner join m.group g inner join g.user u where u.id = :userId and m.meetingDate > now() order by m.meetingDate asc")
List<Meeting> getNextMeetings(#Param(userId) long userId)
You sorting should be ascending(from the closest date to now to the farthest). Query will return list of entities. I would suggest you to check the order in result query and take the first entity from the list -> list.get(0). Otherwise, you can sort it by yourself and take the first.

Related

Operand should contain 2 column(s) when fetching data through JPQL using IN & MEMBER OF clause

I am trying to fetch data of employee availability creating a query. I have used #ElementCollection annotation to map skills and daysAvailable, which stores data into other table.
TypedQuery<Employee> query = entityManager.createQuery("select e from Employee e where :day MEMBER OF e.daysAvailable and :list MEMBER OF e.skills ", Employee.class);//
query.setParameter("day", dayOfWeek);
query.setParameter("list", employeeRequestDTO.getSkills());
List<Employee> list = query.getResultList();
I am trying to pass a set in my query. If there is only one element in set then the query works but if more then 1, then it is not able to fetch. I have tried using e.skills in (:list) instead of
:list MEMBER OF e.skills. But still no luck!!
#Entity
public class Employee {
#Id
#GeneratedValue
private long id;
#Nationalized
private String name;
#ElementCollection(fetch = FetchType.EAGER)
#CollectionTable(name = "skills", joinColumns = #JoinColumn(name = "emp_id"))
#Enumerated(EnumType.STRING)
private Set<EmployeeSkill> skills;
#ElementCollection(fetch = FetchType.EAGER)
#CollectionTable(name = "days", joinColumns = #JoinColumn(name = "emp_id"))
#Enumerated(EnumType.STRING)
private Set<DayOfWeek> daysAvailable;
// Getters & Setters
This is the domain i have created and now want to fetch all employees who are available on a particular day and have particular skills. I have created query for this but it is showing error - java.sql.SQLException: Operand should contain 2 column(s)
This is the query generated-
select * from employee e where ( 'TUESDAY' in ( select d.days_available from days d where e.id=d.emp_id)) and (( 'PETTING','FEEDING' ) in (select s.skills from skills s where e.id=s.emp_id));
Any suggestions?
In JPQL, MEMBER OF takes a single argument and checks if that's contained in the provided collection.
Check out the Hibernate User Guide for more details.
Try this query instead:
select e
from Employee e
join e.skills s
where
:day MEMBER OF e.daysAvailable and
s in :list

Sorting by relation property

Here's my working database setup:
#Entity
class Foo {
#Id
#Column(name = "ID")
#GeneratedValue(strategy= GenerationType.IDENTITY)
private Long id;
#OneToMany(fetch = FetchType.LAZY)
#JoinColumn(name = "FOO_ID")
private Set<Bar> bars;
//...
}
#Entity
class Bar {
#Id
#Column(name = "ID")
#GeneratedValue(strategy= GenerationType.IDENTITY)
private Long id;
#Column(name = "STATUS")
private String status;
//...
}
FooRepository extends CrudRepository {
#Query("select distinct f from Foo f left join f.bars b where b.status = :status ")
public Page<Bar> findByBarStatus(#Param("status") BarStatus status, Pageable pageable);
}
I'd like to be able to sort this query by Bar.status, here's how I tried to change the query:
#Query("select distinct f from Foo f left join f.bars b where b.status = :status order by b.status desc")
public Set<Bar> findByBarStatus(#Param("status") BarStatus status);
However that causes sql syntax error:
org.h2.jdbc.JdbcSQLException: Order by expression "BARS1_.STATUS" must be in the result list in this case;
Here you have applied distinct on f and thus you can not have some other column in order by. Actually, order by item must be there in select list.
So, the problem is in query, you can remove distinct if you are sure that f will be unique (but that's not the case I guess) or you can try with clause,
with temp as
(select distinct f, b.status
from Foo f left join f.bars b
where b.status = :status order by b.status desc)
select f from temp
you have to call b.status in your query select statement like below query.
select DISTINCT(f), b.status from Foo f
LEFT JOIN f.bars b where b.status = :status order by b.status desc

jpa + hibernate Query for get records from two tables with join

I need to get record like :-
toolTypeId, quantity, toolName , onTruck, Damage, loss
2 50 test1 20 25 5
onTruck, Damage, loss:- total records from list
first 3 are from toolsType table and last 3 from userTools.
My model classes :-
ToolsType.java
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String toolName;
private Long quantity;
UserTools.java
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#OneToOne
private ToolsType toolsType;
private Long loss;
private Long onTruck;
private Long damage;
I am trying something like that in my Repository file
:- select count(toolstype.id), toolstype.toolName, quantity FROM toolstype GROUP BY(toolstype.id);
I know its not correct Please help me for correct query for this issue.
Thanks
Use this query. Hope it will help you. You need to use alias in this case.
select count(ttype.id), ttype.toolName, ttype.quantity FROM toolstype as ttype GROUP BY(ttype.id);
UPDATED Query is given below:
select count(ttype.id), ttype.toolName, ttype.quantity, utools.onTruck, utools.damage, utools.loss
FROM toolstype ttype, usertools utools
where ttype.id = utools.id
GROUP BY ttype.toolName, ttype.quantity, utools.onTruck, utools.damage, utools.loss
You must use this JPQL query:
select tt.id, count(tt.id), tt.toolname, ut.onTruck, ut.damage, ut.loss
from UserTools ut
join ut.toolsType tt
group by tt.id, tt.toolname, ut.onTruck, ut.damage, ut.loss
You need to put all select values in the group by clause for the query to group the results.
UPDATE:
If you need the sum of UserTools values and all the ToolsType values in the result, the query would be:
select tt.id, count(tt.id), tt.toolname, sum(ut.onTruck), sum(ut.damage), sum(ut.loss)
from ToolsType tt, UserTools ut
where tt.id = ut.toolsType.id
group by tt.id, tt.toolname, ut.onTruck, ut.damage, ut.loss
I also think that the relation between UserTools and ToolType would be #ManyToOne instead of #OneToOne.

How to get root by recursive oracle query in Hibernate

I'm a little curious, is there a way to get result of connect by sql query like root Entity with already mapped descendants.
So if I'm insert in base something like this:
insert into table test (id, parent_id, some_text) values
(1, null, 'a'),
(2, 1, 'b'),
(3, 1, 'c'),
(4, 2, 'd');
then by sql query
select *
from test t
start with t.id = 1
connect by prior t.id = t.parent_id
order siblings by t.some_text
I will get
id | parent_id | some_text
1 null a
2 1 b
4 2 d
3 1 c
and by entity
#Entity
#Table(name = "test")
public class Test {
#Id
#Column(name = "id")
#GeneratedValue(generator = "increment")
#GenericGenerator(name = "increment", strategy = "increment")
private BigInteger id;
#Column(name = "parent_id")
private BigInteger parent_id;
#Column(name = "some_text")
private String someText;
#OneToMany(mappedBy = "parent")
private Set<Test> descendants;
#ManyToOne
#JoinColumn(name = "parent_id")
private Test parent;
// getters and setters
}
it will back to me as list of Test. It possible to get root and full tree by recursive function, but it will get new query on iteration (it will very long if I have a big tree).
So is there a possible good way to get root of this tree with already mapped descendants by this query (maybe extend/implement some class/interface which will process mapping from jdbc to entity)?
you can use CONNECT_BY_ROOT unary operator.
See docs
select t.*, connect_by_root id
from test t
start with t.id = 1
connect by prior t.id = t.parent_id
order siblings by t.some_text
BTW: this has nothing to do with Hibernace. This is purely Oracle specific solution.

Criteria query, find all groups that I'm not member of

I have two entities, Group and GroupMember. Group is like it sounds a group that has name and some other properties. Members of the group are mapped with GroupMember entity, which has an entry with a User and a Group for every group the user is member of. They look like the following:
#Entity
#Table(name = EntityTokens.GROUP_TABLE)
public class Group
{
#Id
#Column(name = EntityTokens.GROUP_ID_COLUMN)
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long groupId;
...
// Group members
#OneToMany(orphanRemoval = true, fetch = FetchType.LAZY, mappedBy = "group", cascade = {CascadeType.ALL})
private Collection<GroupMember> groupMembers;
}
#Entity
#Table(name = EntityTokens.GROUP_MEMBER_TABLE)
public class GroupMember
{
#Id
#Column(name = EntityTokens.GROUP_MEMBER_ID_COLUMN)
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long memberId;
...
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = EntityTokens.GROUP_MEMBER_ID_COLUMN)
private Group group;
}
I'm trying to write a criteria query that returns all groups that have some predefined properties and that the current user is not part of. My query looks like this:
CriteriaQuery<Group> q = cb.createQuery(Group.class);
Root<Group> root = q.from(Group.class);
Join<Group, GroupMember> groups = root.join(Group_.groupMembers);
q.select(root);
q.where(cb.notEqual(groups.get(GroupMember_.user), user),
cb.equal(root.get(Group_.global), false),
cb.equal(root.get(Group_.personal), false),
cb.equal(root.get(Group_.privacy), GroupPrivacy.PUBLIC));
q.distinct(true);
The user here represents the current user. This query doesn't work because if there are other members that are part of the same group as me they will be included in the query result due to the join. How should the correct query look like? I'm not that familiar with the criteria query API yet.
join for a ToMany relationship is conceptually an "anyOf" operation, meaning if any of the many is true then the expression is true.
What you want is an "allOf", criteria does not have this, you need to use a sub select for this in SQL.
The JPQL would be,
Select g from Group g where not exists (select m from g.members m where m.user = :user)
The criteria would be the same, using a sub criteria query for the exists.

Categories