JPA CriteriaBuilder how to create join + like query - java

I have a SQL query:
SELECT s.*, p.name, p.code
FROM `stock` s
LEFT JOIN product p ON s.product_id = p.id
WHERE p.name LIKE "%q%"
And I need to create the query using criteriabuilder
I started so:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Long> cq = cb.createQuery(Long.class);
Root<Stock> stock = cq.from(Stock.class);
Path<String> path = stock.get(filter.getKey());//i have error here
String likeValue = wildCard + value + wildCard;
Predicate filterCondition = cb.conjunction();
filterCondition = cb.and(filterCondition, cb.like(path, likeValue));
Please help, how to do it better?

the selection is unclear. In SQL you select s.*, p.name, p.code, but in criteria you expect a Long?
your LEFT JOIN has not to be LEFT.
in criteria you've no join at all.
you should use metamodel, as a general advice.
I think you want all Stocks which contain at least one Product with name like %value%.
If my assumption is right:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Stock> cq = cb.createQuery(Stock.class);
Root<Stock> stock = cq.from(Stock.class);
Join<Stock, Product> product = stock.join(Stock_.products);
cq.select(stock);
cq.distinct(true);
cq.where(cb.like(product.get(Product_.name), "%" + value + "%");
return em.createQuery(cq).getResultList();

Related

How to join an entity with custom select using CriteriaBuilder

I have a scenario where I need to get the row with maximum date. The SQL query for this would be
SELECT c.*
FROM course c
INNER JOIN
(SELECT moduleId ,MAX(endDate) AS max_date
FROM course
WHERE moduleId = 12345
GROUP BY moduleId
) customSelect
ON customSelect.moduleId = c.moduleId AND c.endDate = customSelect.max_date
WHERE c.moduleId = 12345
I need to convert this query to JPA using CriteriaBuilder.Since this isn't a direct entity join, rather a selection join to root entity, I'm having trouble to figure out how to join the custom select part to the root entity Course with below syntax:
CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<Course> criteriaQuery = builder.createQuery(Course.class);
Root<Course> root = criteriaQuery.from(Course.class);
And then how to root.join(JoinType.INNER) to join customSelect part?
If someone can show some pointers to the syntax of of joining the root to a custom selection, that would be great.
Try this
CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<Course> criteriaQuery = builder.createQuery(Course.class);
Root<Course> root = criteriaQuery.from(Course.class);
criteriaQuery.select(root).where(cb.equal(root.get(Course_.moduleId), 12345));
criteriaQuery.orderBy(cb.desc(r.get(Course_.endDate)));
TypedQuery<Course> query = em.createQuery(criteriaQuery);
query.setMaxResult(1);
Course result = query.getSingleResult();

How to add filter on second table parameter while doing left join using criteriaquery

I am stuck in a situation where I am not able to create a filter on left join between two table.
My query is something like this.
select count(*)
from orders o
left
join payments p
on o.id = p.o_id
where o.uid_id = 1
and p.name = "abc"
I am trying to do left join using criteria query. In criteria query.
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Orders> query = cb.createQuery(Orders.class);
Root<Orders> ordersRoot = query.from(Orders.class);
Join<Orders, Payments> join = ordersRoot.join(JOIN_COLUMN, JoinType.LEFT);
List<Predicate> predicates = new ArrayList<>();
predicates.addAll(getPredicates(cb, ordersRoot)); //this method gives other predicates on order table
query.where(predicates.toArray(new Predicate[predicates.size()]));
query.select(ordersRoot).distinct(true);
TypedQuery<Orders> query = entityManager.createQuery(criteriaQuery);
List<Orders> list = query.getResultList();
This is my criteria Java code.
In this I have not added for this check.
orders and payments table has one to many relationship.

Build criteria query with joins and custom parameters

I need to build following query using JPA and criteria query but I stuck on join conditions. The query is:
SELECT p.*
FROM output cu
JOIN user ur ON cu.id = ur.id AND cu.key = ur.key
JOIN product p ON cu.id = p.id AND cu.key = p.key
WHERE p.refreshtimestamp IS NOT NULL AND cu.active = true
So far I have following, but how to apply join conditions:
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Output> cq = cb.createQuery(Output.class);
Root<Output> output= cq.from(Output.class);
Join<Output, User> user = output.join("user", JoinType.INNER);
Join<User, Product> product = user.join("product", JoinType.INNER);
Any help will be appreciated
Following should help.
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Product> criteria = builder.createQuery(Product.class);
Root<Output> outputRoot = criteria.from(Output.class);
Root<User> userRoot = criteria.from(User.class);
Root<Product> productRoot = criteria.from(Product.class);
Predicate[] predictes = {
builder.equal(outputRoot.get("id"), userRoot.get("key")),
builder.equal(productRoot.get("id"), userRoot.get("key")),
builder.notEqual(productRoot.get("refreshtimestamp"), null), // not sure about null
builder.equal(outputRoot.get("active"), true)
};
criteria.select(productRoot);
criteria.where(builder.and(predicates));
Although this would produce cross joins query, it will work because of where clause making it work like inner join as you require.

Criteria API count from grouped count

I have a problem with Criteria API (JPA 2.0). I want to write code which returns the same result as query (select count from (select count from ... group by ...)):
SELECT COUNT(*) FROM (
SELECT COUNT(*) FROM a
LEFT JOIN p ON a.id = p.a_id
LEFT JOIN s ON a.id = s.a_id
WHERE ... GROUP BY s.r_id
)
I wrote something like this:
CriteriaBuilder builder = slave.getCriteriaBuilder();
CriteriaQuery<Long> query = builder.createQuery(Long.class);
Subquery<Long> subquery = query.subquery(Long.class);
Root<A> entity = subquery.from(A.class);
Join<A, P> pJoin = entity.join("p", JoinType.LEFT);
Join<A, S> sJoin = entity.join("s", JoinType.LEFT);
subquery.select(builder.count(entity));
subquery.where(/*where predicate*/);
subquery.groupBy(sJoin.get("r"));
query.select(builder.count(subquery));
Long result = slave.createQuery(query).getSingleResult();
But I get the exception:
java.lang.IllegalStateException: No criteria query roots were specified
What am I doing wrong here?

JPA 2 + Criteria API

Employee (table)
id - int
ctd_id - int
message - char
SELECT a.*
FROM Employee a left outer join
( select * from Employee where message = 23 ) b
on a.ctd_id = b.ctd_id
where a.message = 22 and b.id is null;
This is what i tried
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Employee> criteria = cb.createQuery(Employee.class);
Root<Employee> emp = criteria.from(Employee.class);
CriteriaQuery<Employee> sq = c.select(emp);
Subquery<Employee> sq2 = criteria.subquery(Employee.class);
Root<Employee> emp2 = sq2.from(Employee.class);
Join<Employee,Employee> sqEmp = emp2.join("ctd_id", JoinType.LEFT);
sq.select(sqemp).where(cb.equal(emp2.get("message"), cb.parameter(String.class, "23")));
sq.where(cb.in(path).value(sq2));
TypedQuery<Employee> q = em.createQuery(criteria);
List<Employee> employeess = q.getResultList()
But, i am not able to understand as to how i should apply a join on a subquery with where clause.
please help .
JPA does not support sub-queries in the FROM clause.
Either use SQL for your query, or rewrite it not to have a sub-query in the from clause, it doesn't look like you need it.

Categories

Resources