Criteria (NOT IN) - java

please, help me:
I have next tables:
Unit
id
name
User
id
name
Rate
unit_id
user_id
I do not understand how to create correct structure of criteria from SQL:
Code:
SELECT * FROM Unit WHERE id not in (SELECT unit_id FROM Rate WHERE user_id = 55);
I saw this answer. But I do not understand how to make Condition linked to another Table (Entity).

Looking yor tag I think you need the Criteria view of your SQL query; so assuming Unit and Rate classes:
// This is the subquery
DetachedCriteria subquery = DetachedCriteria.forClass(Rate.class)
.add(Restrictions.eq("user_id", 55))
.setProjection(Projections.id())
// This corresponds to (SELECT * FROM Unit WHERE id not in (subquery))
Criteria criteria = session
.createCriteria(Unit.class)
.add(Subqueries.notIn("id", subquery));

I don't know that IN would be the most appropriate in this case. Try an inner join to link up the tables:
SELECT * FROM Unit INNER JOIN Rate ON Rate.unit_id = Unit.id
WHERE Rate.user_id = 55

Related

Criteria Builder select from select

Can anybody help me to create JPA Criteria Builder query in order to achieve this ?:
select id from (
select distinct r.id
r.date
r.name
from report r
inner join unit u
on u.report_id = r.id
order by
r.date desc,
r.name asc)
where rownum <= 10
I just can create inner query:
CriteriaQuery<Object[]> innerQuery = cb.createQuery(Object[].class);
Root<ReportEntity> root = innerQuery.from(ReportEntity.class);
List<Ojbect[]> resultLsit = em.createQuery(
innerQuery.multiselect(root.get(ReportEntity_.id),
root.get(ReportEntity_.date),
root.get(ReportEntity_.name)
.distinct(true)
.orderBy(cb.desc(root.get(ReportEntity_.date)),
cb.asc(root.get(ReportEntity.name))
).setMaxResults(10).getResultList();
Thx in advance :)
I've decided to get List of Object[] and then retrieve id from array
List idList = resultList.stream().map(array -> (Long)array[0]).collect(Collectors.toList());
This is code smell, but unfortunatelly I haven't found better solution.
Note I use this approach to cope Hibernate issue :
"Warning “firstResult/maxResults specified with collection fetch; applying in memory!”? - this warning pops up due to using fetch and setMaxResults in hql or criteria query.
That's why first of all I get all id, and then I find all entities according this id. (select * from ReportEntity r where r.id in :idList) - smth like this.

Named Query, Native Query or Criteria API

I need to report data from 3 different tables in form of a report.
The various search combinations a user can search with are..
INS_USER_ID and DateRange
CUST_ACCT_ID
CUST_ACCT_ID and DateRange
Query..
select DISTINCT W.CUST_ACCT_ID, W.INS_USER_ID, WS.STTI_DATE, WS.STTI_AMT, WC.CMMT from T_WRK W
INNER JOIN T_WRK_STTI WS ON W.WRK_STTI_ID = WS.WRK_STTI_ID
INNER JOIN T_WRK_CMMT WC ON W.WRK_ID = WC.WRK_ID
WHERE W.CUST_ACCT_ID = 90610194 AND WS.STTI_DATE BETWEEN '01-JAN-12' AND '31-DEC-12'
select DISTINCT W.CUST_ACCT_ID, W.INS_USER_ID, WS.STTI_DATE, WS.STTI_AMT, WC.CMMT from T_WRKCS W
INNER JOIN T_WRKCS_STTI WS ON W.WRKCS_STTI_ID = WS.WRKCS_STTI_ID
INNER JOIN T_WRKCS_CMMT WC ON W.WRKCS_ID = WC.WRKCS_ID
WHERE W.INS_USER_ID = 231 AND WS.STTI_DATE BETWEEN '01-JAN-12' AND '31-DEC-12'
All are existing tables are already mapped using Hibernate/JPA.
I have read enough on the various approaches in google, can someone tell me which one of the following hibernate approaches is best suited for my scenario.
NamedQuery
NativeQuery
Criteria API
I am thinking NamedQuery, but have not seen a NamedQuery spanning across multiple tables, an example would be great. Thank you.
Example
#Entity
#NamedQuery(name="findSalaryForNameAndDepartment",
query="SELECT e.salary " +
"FROM Student e" +
"WHERE e.department.name = :deptName AND " +
" e.name = :empName")
You can as well put there an join to the department table and change the query a little bit
For date use parameters
em.createNamedQuery("xxx").setParameter("srtartDate", ...).setParameter("endDate",..)

Hibernate: Joining Criteria

Hi I need to do the following using Criteria
Select * from product pd, (Select productID pd1 from ... where ...) tpd1,
(Select productID pd2 from ... where ...) tpd2
where pd.productID = tpd1.pd1 and pd.productID = tpd1.pd2
May I know if it is possible?
The original SQL was using IN conditions
Select * from product pd where productID in (Select productID pd1 from ... where ...) and
productID in (Select productID pd2 from ... where ...)
but it takes too long to get the result, using the join SQL statement I was able to obtain my result faster.
any help?
Given you're using Hibernate, you may have to do something like this, which should work ok if the number of expected matches are relatively low:
select *
from product pd
where pd.productID in
(select productID
from product pd2
join tpd1 on (pd2.productID = tpd1.pd1)
join tpd2 on (pd2.productID = tpd2.pd2)
where tpd1....
and tpd2....
);
I assume there is a unique index on product.productID.
Alternatively, you could try the EXISTS formulation which may or may not work better than your original query:
select *
from product pd
where EXISTS
(select null from tpd1 where pd.productID = tpd1.pd1 and ...)
and EXISTS
(select null from tpd2 where pd.productID = tpd2.pd2 and ...)
;

problem in setString method.in retrieving data from the table

i have two tables "Table1" with columns user_name,Password and course ID and another table "course" with columns course_id,course_name.I have used the following code to display the course ID from Table1 according to the user_name received from the login page.using ResultSet rs1.now i want to retrieve the course_name from the table "course" according to the course ID receieve from "Table1".for that in the second query pstmt2.setString(1, ); what parameter i should use to get the course_id value from the previous query
HttpSession sess=request.getSession();
String a=(String)sess.getAttribute("user");
String b=(String)sess.getAttribute("pass");
try {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Connection con=DriverManager.getConnection("jdbc:odbc:ggg");
Statement st = con.createStatement();
String query="select * from Table1 where user_name=?";
PreparedStatement pstmt=con.prepareStatement(query);
pstmt.setString(1,a);
ResultSet rs1=pstmt.executeQuery();
while(rs1.next())
out.println("<h3>COURSE ID: "+rs1.getString("course ID")+"<h3>");
String query2="SELECT * from course where course_id=?";
PreparedStatement pstmt2=con.prepareStatement(query2);
pstmt2.setString(1,);
ResultSet rs2=pstmt2.executeQuery();
while(rs2.next())
{
out.println("<h3>course name: "+rs2.getString("course_name")+"<h3>");
}
why do you go for two turns of database hit, even though you created one time connection object.
modify the query as below
SELECT * from course where course_id = (select course_id from Table1 where user_name=?);
from this query you noneed to give input of courseid also.
No need to hit database twice to get the results that you need. use the query
Select table1.course_id, course.course_name from table1, course where table1.course_id=course_id and table1.user_name=?
This should set the course_id parameter:
pstmt2.setString(1,rs1.getString("course_id"));
Or, as I see the "course_id" column may have a different name in "Table1":
pstmt2.setString(1,rs1.getString("course ID"));
As the other post mentioned there's no need to go to another set of query. Try this example query:
SELECT course.course_id, course.course_name
FROM table1 t1
INNER JOIN course c
ON t1.course_id = c.course_id
WHERE t1.user_name = ?;
Now if you insist your coding the parameter o your pstmt2.setString(1,); is:
pstmt2.setString(1,rs1.getString("course_id")); //or course ID defending on your column name

Hibernate detached queries as a part of the criteria query

java experts can you please help me write detached queries as a part of the criteria query for the following SQL statement.
select A.*
FROM AETABLE A
where not exists
(
select entryid
FROM AETABLE B
where B.classpk = A.classpk
and B.userid = A.userid
and B.modifiedDate > A.modifiedDate
)
and userid = 10146
You need to write a correlated subquery. Assuming property / class names match column / table names above:
DetachedCriteria subquery = DetachedCriteria.forClass(AETable.class, "b")
.add(Property.forName("b.classpk").eqProperty("a.classpk"))
.add(Property.forName("b.userid").eqProperty("a.userid"))
.add(Property.forName("b.modifiedDate").gtProperty("a.modifiedDate"));
Criteria criteria = session.createCriteria(AETable.class, "a")
.add(Property.forName("userid").eq(new Integer(10146)))
.add(Subqueries.notExists(subquery);
Just one addition to the above query. If the entryid is not the primary key, then you'll need to add projection.
DetachedCriteria subquery = DetachedCriteria.forClass(AETable.class, "b")
.add(Property.forName("b.classpk").eqProperty("a.classpk"))
.add(Property.forName("b.userid").eqProperty("a.userid"))
.add(Property.forName("b.modifiedDate").gtProperty("a.modifiedDate"))
.add(setProjection(Projections.property("entryId")); // Additional projection property
Criteria criteria = session.createCriteria(AETable.class, "a")
.add(Property.forName("userid").eq(new Integer(10146)))
.add(Subqueries.notExists(subquery);

Categories