Spring Data JPA QueryLimit - spring

#Query(value = "SELECT e FROM user Order By e.id DESC LIMIT 0, :n ")
List findTopN(#Param("n") long n);

#Query(value = "SELECT * FROM event_tracker.user Order By user.id DESC LIMIT 0, :n",nativeQuery = true)
List findTopN(#Param("n") long n);

Related

Inner join with more than one OR conditions in spring boot

I am using spring boot specification and trying to execute a query that looks like this -
SELECT DISTINCT
p.name
FROM
partner p
INNER JOIN
detail d ON p.detail_id = d.id
INNER JOIN
account a ON d.account_id = a.id
OR d.crm_id = a.top_parent
OR d.crm_id = a.global_partner
I have used the code
Join<Partner, Detail> details = root.join("detail");
Join<Detail, Account> account = details.join("account");
Predicate global = cb.equal(details.get("crm_id "), account.get("top_parent"));
Predicate top = cb.equal(details.get("crm_id "), account.get("global_partner"));
account.on(cb.or(global, top));
However, it creates the query
SELECT DISTINCT
p.name
FROM
partner p
INNER JOIN
detail d ON p.detail_id = d.id
INNER JOIN
account a ON d.account_id = a.id
AND (d.crm_id = a.top_parent
OR d.crm_id = a.global_partner)
Notice the AND operator in the query...I need to replace it OR operator
Another use case I am struggling with
#Entity
public class Detail {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#OneToMany(mappedBy = "detail", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private Set<Skill> skills;
}
I am trying to generate the query below using specifications
order by (select count(s.detail_id) from skill s where detail.id = s.detail_id AND s.category is not null) desc
I have used the code below
cq.orderBy(cb.desc(cb.size(details.get("skills"))));
But the query it generates is
order by (select count(s.detail_id) from skill s where detail.id = s.detail_id) desc
Notice that I am unable to add an extra AND to the order by clause
I believe you can not change that AND.
could you change the query in the following way
SELECT DISTINCT p.name
FROM partner p INNER JOIN detail d ON p.detail_id = d.id, account a
where d.account_id = a.id
OR d.crm_id = a.top_parent
OR d.crm_id = a.global_partner
and the jpa criteria similar to
Join<Partner, Detail> details = root.join("detail");
Root<Account> account = criteria.from(Account.class);
Predicate global = cb.equal(details.get("crm_id"), account.get("top_parent"));
Predicate top = cb.equal(details.get("crm_id"), account.get("global_partner"));
Predicate byId = cb.equal(details.get("account").get("id"), account.get("id"));
Predicate or = cb.or(global, top, byId);
criteria.where(or);

Hibernate, select where foreign key is null

I have entity as follows:
#Entity
#Table(name = "LORRY")
#NamedQueries({
#NamedQuery(name = "Lorry.findSuitableLorries",
query = "SELECT l from Lorry l " +
"WHERE l.order IS NULL")
})
public class Lorry {
#Id
#Column(name = "ID", length = 7)
#Pattern(regexp="[a-zA-Z]{2}\\d{5}")
#Size(min = 7, max = 7)
private String regNum;
#OneToOne(mappedBy = "lorry")
private Order order;
}
Now I need to select all rows where order id is null in the LORRY table, but it doesn't seem to work as I get empty list every time. How can I check if foreign key is null using JPQL?
Try either SELECT l from Lorry l WHERE l.order.id IS NULL or SELECT l from Lorry l left join l.order o WHERE o IS NULL

Pass date parameter to native query

A user can perform actions based on an occurrence value. When this value is equal to 'DAILY', I would like to retrieve all daily actions that have not been completed the last 24 hours.
The working SQL query:
SELECT distinct a.* FROM action as a LEFT OUTER JOIN history as h
ON a.id = h.action_id
AND h.user_id= <user> WHERE a.occurrence = 'DAILY' AND (h.id is NULL OR h.entry_date < TIMESTAMP 'yesterday')
The equivalent native query:
#Query(value =
"SELECT distinct a.* FROM action a "
+ "LEFT OUTER JOIN history h "
+ "ON a.id = h.action_id "
+ "AND h.user_id = :userId "
+ "WHERE a.occurrence='DAILY' AND (h.id IS NULL OR h.entry_date < :yesterday) ", nativeQuery = true)
public List<Action> findAllAvailableActions(#Param("userId") Long userId, #Param("yesterday") ZonedDateTime yesterday);
How it is called in my service :
ZonedDateTime today = ZonedDateTime.now(ZoneOffset.UTC);
ZonedDateTime yesterday = today.minus(1,ChronoUnit.DAYS);
Long userId = userDTO.getId();
List<Action> result = actionRepositoryCustom.findAllAvailableActions(userId, yesterday);
However, I do get the wrong results in my tests (actions that have already been completed are returned). I am afraid this is linked to the date parameter. The attribute entry_date is declared as ZoneDateTime in my entity. What am I doing wrong ?
hibernate : 5.2.4
You can't pass a ZonedDateTime into a native SQL query. You need to convert it to Calendar:
#Query(value =
"SELECT distinct a.* FROM action a "
+ "LEFT OUTER JOIN history h "
+ "ON a.id = h.action_id "
+ "AND h.user_id = :userId "
+ "WHERE a.occurrence='DAILY' AND (h.id IS NULL OR h.entry_date < :yesterday)", nativeQuery = true)
public List<Action> findAllAvailableActions(#Param("userId") Long userId, #Param("yesterday") Calendar yesterday);
And you can convert your ZonedDateTime this way:
public Calendar convertToDatabaseColumn(ZonedDateTime entityAttribute) {
if (entityAttribute == null) {
return null;
}
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(entityAttribute.toInstant().toEpochMilli());
calendar.setTimeZone(TimeZone.getTimeZone(entityAttribute.getZone()));
return calendar;
}
This approach is described here: link

jpql native query not setting parameter

#Repository
public interface GroupRepository extends JpaRepository<Group, String> {
//Other queries....
#Query(value = "with cte(group_id, parent_group_id, group_name) as( "
+ "select group_id, parent_group_id, group_name "
+ "from hea.hea_group "
+ "where group_id = ?1 "
+ "union all "
+ "select g.group_id, g.parent_group_id, g.group_name "
+ "from hea.hea_group g "
+ "inner join cte on cte.group_id = g.parent_group_id "
+ "where g.parent_group_id is not null "
+ ") select * from cte", nativeQuery = true)
List<Object> getChildGroups(String groupId);
}
Above is the query that I have written that should return the parent group and all of its children. The query does what it is suppose to do when I replace the ?1 with a hard coded group id value and change the method to have no parameters, but when I try to run it as above it returns nothing even though I'm passing in the exact same value that I was hard coding.
Below is the sql that is being generated by the query. When I replace the ? with a group id an run it on a test database it returns the results that it should.
with cte(group_id, parent_group_id, group_name) as( select
group_id,
parent_group_id,
group_name
from
hea.hea_group
where
group_id = ?
union
all select
g.group_id,
g.parent_group_id,
g.group_name
from
hea.hea_group g
inner join
cte
on cte.group_id = g.parent_group_id
where
g.parent_group_id is not null ) select
*
from
cte
The variables are zero based so ?0 is what you should use.

using one list value in another list using anonymous types

I have a list x with anonymous types in which i want to use a value which pre-calculated
int count1 =
(from users in dc.BeadSets
where users.UserId == i
select users
).Count();
var x =
(from users in dc.Users
where users.Id == i
select new { username = users.UserName
, fullname = users.FirstName + " " + users.LastName
, userid = users.Id
}
).ToList();
Now this is working fine as usual
Cannot implicitly convert type 'System.Collections.Generic.List<AnonymousType#1>'
to 'System.Collections.Generic.List<AnonymousType#2>'
but while i am trying to use like this its throwing above error
int count1 =
(from users in dc.BeadSets
where users.UserId == i
select users
).Count();
x =
(from users in dc.Users
where users.Id == i
select new { beadsets= count1
, username = users.UserName
, fullname = users.FirstName + " " + users.LastName
, userid = users.Id }
).ToList();

Resources