Hibernate 4 Distinct and order by together - java

select distinct groupMember.proUcer.proUserDetail
from proGroupMembership groupMember
where groupMember.proGroup.id =:groupId and groupMember.status = 1
order by groupMember.proUcer.proUserDetail.firstName
ORA-01791 Exception
coming when i execute this Query.
After many research i got solution to solve this problem by selecting one more column on which we are applying order by -
So i convert query according that solution
select distinct groupMember.proUcer.proUserDetail, groupMember.proUcer.proUserDetail.firstName
from proGroupMembership groupMember
where groupMember.proGroup.id =:groupId and groupMember.status = 1
order by groupMember.proUcer.proUserDetail.firstName
Now my problem is I only need list of object but query.list() returning list of array of object.
Please help me to solve this problem.

Don't repeat yourself in the query like that. Use joins:
select distinct proUserDetail
from proGroupMembership groupMember
join groupMember.proUcer proUcer
join proUcer.proUserDetail proUserDetail
where groupMember.proGroup.id = :groupId and groupMember.status = 1
order by proUserDetail.firstName

Related

How to use Count(*) in JPQL

I have a JPQL subquery in which I want to return a list of customerIds that meet a specific condition based on a ManyToOne relationship as shown below:
SELECT c.customerId
FROM Customer c
INNER JOIN FETCH c.customersChild cc
LEFT JOIN FETCH c.childsPet cp on cp.name = 'Rover'
GROUP BY c.customerId
HAVING (COUNT(cp.name) / COUNT(*)) = 1
In this case, the customer should only be present in the list if all of their childrens' pet's names are Rover. The HAVING (COUNT(cp.name) / COUNT(*)) = 1 clause works as-is in Oracle (SQL), since COUNT(cp.name) counts the number of non-null rows for each customer, and COUNT(*) counts the total number of rows (including nulls present due to the left join) for each customer... I believe COUNT(cp.name) works in JPQL but it doesn't seem like there is equivalent for COUNT(*)... does anyone know if there is a way to count all the rows within a group including nulls?
I would suggest you rewrite your query to the more understandable anti-join variant:
SELECT c.customerId
FROM Customer c
WHERE NOT EXISTS (
SELECT 1
FROM c.customersChild cc
JOIN cc.childsPet cp
WHERE cp.name = 'Rover'
)

Insert values in many to many relationship tables with JOOQ

I have three tables in my database, SUBSCRIPTION, USER_ID, and an association table called SUBSCRIPTION_USER_ID.
My strategy is to use JOOQ batch with three queries, the first one to insert on row into SUBSCRIPTION, the second query to insert multiple rows into USER_ID, and finally, I need to insert the association IDs into SUBSCRIPTION_USER_ID, so I did the following:
InsertValuesStep2 insertUserIds = insertInto(
USER_ID, USER_ID.USER_ID_TYPE, USER_ID.USER_ID_VALUE);
for (String userId : subscriptionDTO.getUserId())
insertUserIds = insertUserIds.values(getValue(0, userId), getValue(1, userId));
InsertReturningStep insertReturningUserIds = insertUserIds.onConflictDoNothing();
InsertResultStep insertReturningSubscription = insertInto(SUBSCRIPTION)
.set(SUBSCRIPTION.CHANNEL_ID, subscriptionDTO.getChannel())
.set(SUBSCRIPTION.SENDER_ID, subscriptionDTO.getSenderId())
.set(SUBSCRIPTION.CATEGORY_ID, subscriptionDTO.getCategory())
.set(SUBSCRIPTION.TOKEN, subscriptionDTO.getToken())
.onConflictDoNothing()
.returningResult(SUBSCRIPTION.ID);
Unfortunately, to insert values into the association table, I tried many ways but nothing works for me, finally, I tried to insert values in SUBSCRIPTION_USER_IDusing with select but It doesn't work:
InsertValuesStep insertValuesSubscriptionUserIds = insertInto(
SUBSCRIPTION_USER_ID,
SUBSCRIPTION_USER_ID.SUBSCRIPTION_ID,
SUBSCRIPTION_USER_ID.USER_ID_ID)
.select(select(SUBSCRIPTION.ID, USER_ID.ID)
.from(SUBSCRIPTION)
.innerJoin(USER_ID)
.on(concat(USER_ID.USER_ID_TYPE,
val(CATEGORY_USER_ID_DELIMITER),
USER_ID.USER_ID_VALUE).in(subscriptionDTO.getUserId())
.and(SUBSCRIPTION.SENDER_ID.equal(subscriptionDTO.getSenderId()))
.and(SUBSCRIPTION.CHANNEL_ID.equal(subscriptionDTO.getChannel()))
.and(SUBSCRIPTION.CATEGORY.equal(subscriptionDTO.getCategory()))
.and(SUBSCRIPTION.TOKEN.equal(subscriptionDTO.getToken()))));
Am I missing something above? Is there a better way using JOOQ to insert many-to-many relationship values or to use queries results as parameters for other queries?
I'm assuming you posted your entire code. In case of which:
You don't call execute on your USER_ID insertion
Simply add
insertUserIds.onConflictDoNothing().execute();
Or alternatively, fetch the generated IDs using a call to returning().fetch()
Inner join
This might just be a stylistic question, but what you seem to be doing is a cross join. Your INNER JOIN filters aren't really join predicates. I'd put them in the WHERE clause. Clarity may help avoid further problems in such a query.
Specifically, that first "join predicate" is very confusing, containing a CONCAT call, which isn't something one would see in an INNER JOIN every day, and only touches one table, not both:
.on(concat(USER_ID.USER_ID_TYPE,
val(CATEGORY_USER_ID_DELIMITER),
USER_ID.USER_ID_VALUE).in(subscriptionDTO.getUserId())
Wrong predicate
That last predicate seems wrong. You're inserting:
.set(SUBSCRIPTION.TOKEN, subscriptionDTO.getToken())
But you're querying
.and(SUBSCRIPTION.TOKEN.equal(subscriptionDTO.getContactId()))));
That should probably be subscriptionDTO.getToken() again
As mentioned above, I have inserted values for SUBSCRIPTION and USER_ID tables. And get for the association table I need to get the IDs of the already inserted values from the above two tables, so to solve the issue I've used this query to insert in SUBSCRIPTION_USER_ID:
InsertReturningStep insertReturningSubscriptionUserId = insertInto(
SUBSCRIPTION_USER_ID,
SUBSCRIPTION_USER_ID.SUBSCRIPTION_ID,
SUBSCRIPTION_USER_ID.USER_ID_ID)
.select(select(SUBSCRIPTION.ID, USER_ID.ID).from(SUBSCRIPTION
.where(concat(USER_ID.USER_ID_TYPE, val(CATEGORY_USER_ID_DELIMITER), USER_ID.USER_ID_VALUE).in(subscriptionDTO.getUserId()))
.and(SUBSCRIPTION.SENDER_ID.equal(subscriptionDTO.getSenderId()))
.and(SUBSCRIPTION.CHANNEL_ID.equal(subscriptionDTO.getChannel()))
.and(SUBSCRIPTION.CATEGORY.equal(subscriptionDTO.getCategory()))
.and(SUBSCRIPTION.TOKEN.equal(subscriptionDTO.getToken()))).onConflictDoNothing();
Finally, I have executed all the queries using batch:
using(configuration).batch(insertReturningSubscription,
insertReturningUserIds,
insertReturningSubscriptionUserId).execute()

jpa native query not returning all values

I am using jpa native query , but its not returning values from salias it returns values from S
Query query = em.createNativeQuery("Select S.\"MESSAGE\",S.\"DESTINATION\",S.\"SENT_DATE\",S.\"CLIENT_TRACKING_ID\",S.\"MESSAGE_COST\",S.\"sTId\",salias.\"STATUS\",salias.timeDate from \"sent_sms_view\" S left join ( Select Distinct on (\"SMS_ID\") R.\"SMS_ID\",R.\"STATUS\",R.timeDate from \"sms_receipt_view\" R Order By R.\"SMS_ID\",R.timeDate Desc)As salias on S.\"SYSTEM_TRACKING_ID\"=salias.\"SMS_ID\" where S.Id_systemUser=:systemUser and S.\"CLIENT_TRACKING_ID\"=:cTId");
query.setParameter("cTId", cTId);
query.setParameter("systemUser", systemUser);
if (query.getResultList().size() > 0){
List<Object> resultat = query.getResultList();
This is the Postgres query and it works fine
Select S."MESSAGE",S."DESTINATION",S."SENT_DATE",S."CLIENT_TRACKING_ID",S."MESSAGE_COST",S."sTId" ,salias."STATUS",salias.timeDate
from "sent_sms_view" S
left join ( Select Distinct on ("SMS_ID") R."SMS_ID",R."STATUS",R.timeDate from "sms_receipt_view" R Order By R."SMS_ID",R.timeDate Desc)As salias
on S."SYSTEM_TRACKING_ID"=salias."SMS_ID"
where S.Id_systemUser='101' and S."CLIENT_TRACKING_ID" ='abda';
Can anyone tell me what i am doing wrong.
I'm only guessing what you might be trying to do, since you haven't told us, but here's how I'm guessing it should probably look like:
SELECT S."MESSAGE", S."DESTINATION", S."SENT_DATE", S."CLIENT_TRACKING_ID", S."MESSAGE_COST", S."sTId", salias."STATUS", salias.timeDate
FROM "sent_sms_view" S
INNER JOIN "sms_receipt_view" AS salias on (S."SYSTEM_TRACKING_ID" = salias."SMS_ID")
WHERE S.Id_systemUser=:systemUser AND S."CLIENT_TRACKING_ID"=:cTId
However I don't see why you would have numerical IDs, such as Id_systemUser stored as strings. In fact that variable name indicates horrible database design. CamelCasing combined with underscores is something you must categorically avoid.
And you must never call query.getResultList() twice if you're looking for the same results. Simply store the List to a local variable and then use it.

how to use alias in querydsl?

I am new to querydsl and already in love with it, but I can't get how to use an alias in this query.
QProduct product = QProduct.product;
JPQLQuery jPQLQuery =
from(product)
.where(product.name.locate(searchTerm).as("score").gt(0).or(product.code.locate(searchTerm).as("score").gt(0))).groupBy(product.baseProd);
List<Product> matchedNames = jPQLQuery.orderBy(new NumberPath<Integer>(Integer.class, "score").asc()).offset((pageNumber-1)*10).limit(10).list(product);
my first thought was something like this which throws an error with the generated query as:
java.lang.IllegalArgumentException:
org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token:
as near line 3, column 31 [select product from
mesoft.meshopframework.model.Product product where
locate(?1,product.name) as score > ?2 or locate(?1,product.code) as
score > ?2 group by product.baseProd order by score asc]
could someone show me the coorect way to do this?? I hope it's not necessary for DB to calculate product.name.locate(searchTerm) or the other one again for sorting,
thanks
JPQL has a more restricted syntax compared to SQL, but I don't think your example would work in SQL either.
You can't use aliases in the where part and for order you will need pick one of the locate expressions or order by both of them.

jsf hibernate criteria api

I have query in Criteria API, that goes like this:
CriteriaQuery<XXX> query = builder.get().createQuery(XXX.class).distinct(true);
Root<XXX> root = query.from(XXX.class);
Fetch<XXX, YYY> fetch = root.fetch(XXX_.yyy, JoinType.LEFT);
now the part I'm stuck on:
when I got query results, I got list of XXX records, with attached list of YYY records, when they exist. I want to sort my result by NUMBER OF YYY records atatched to XXX object. And so far, I'm closer to paranoia then to that goal. Anyone?
To solve you problem you need to get in result SQL Query(which is generated from hibernate criteria) that will look like this:
SELECT xxx.*,count(yyy.FOREIGN_KEY_FIELD) as count FROM XXX xxx left join YYY yyy on (yyy.FOREIGN_KEY_FIELD=xxx.PRIMARY_KEY_FIELD) group by xxx.PRIMARY_KEY_FIELD order by count
Probably for this case you need to use hibernate query api. Criteria is created for Entities and return only list of entities and some projections. In hql it will look very similar to:
select xxx,count(yyy.FOREIGN_KEY_FIELD) as count from XXX xxx left join xxx.yyy yyy group by xxx.PRIMARY_KEY_FIELD order by count
HQL is more flexible for such queries.

Categories

Resources