Hibernate Criteria and DetachedCriteria concate Properties or fields - java

i have a criteria like
public ArrayList<Student>getStudentsWithPicture(final Student student)
{
final Criteria criteria = session.createCriteria(Student.class).add(and(prepareForSelect()));
criteria.add(Subqueries.gt(1L,getDetached);//the students with a less added picture...
return new ArrayList<Student>(criteria.list());
}
i need the students with a less a picture in the table Pictures but this Database is a legacy one
they store the pictures concatening some fields for the student entity
yes a quite weird
i want something like this
SQL
select
this_.ID as y0_,
this_.C01 as y1_,
this_.C02 as y2_,
this_.C03 as y3_
from
student_table this_
where
(
and this_.C11=true
and 1>=
(
select
count(*)
from
PICTURE_TABLE this_
where
(
this_.C03='concatening'+ this_.ID+ this_.C01+this_.C02+this_.C03//the fields of the student
)
)
)
this is just a understandable example the actual query is a lot worse...
as you can see i want the students with status='true' and they have a less one match on the PICTURE_TABLE but the field C03 from the table is created by concatening the fields of the Student which i have retrieve it as well...
my detached
public DetachedCriteria getWithDetachedMatchStudentWithPictures()
{
final String concatedFields = ...........how i accomplish this??????.................
final DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Pictures.class)
.add(equals("c03",concatedFields))
.setProjection(addProjection("id"))
.setResultTransformer(transformer(Pictures.class));
return detachedCriteria;
}
my question is.
can i concate the fields at runtime..?? using Criteria A.P.I
there is some approach?
thanks a lot

Yes, we can contact multiple columns run time in hibernate.
i have concat columns in my beloved query.
Query query = session.createQuery("SELECT DISTINCT f.fileid , f.filename, f.filetype , f.folderpath , max(f.version) from FileBean f GROUP BY concat(folderpath,filename,'.',filetype)");
result = query.list();

Related

JPA Typed query set parameter

I have a named parameter in JPA typed query. I am setting a list of value in condition.
I am setting a list of integer, but when JPA converts typed query to corresponding sql query it is adding a to_number function and index of the table is not used.
List<Integer> studentIds=ArrayList<Integer>
//Student id is number in database and indexed.
query = "SELECT T.* FROM STUDENT WHERE STUDENT_ID IN (:studentIds)"
TypedQuery<Object[]> typedQuery = entityManager().createQuery( query, Object[].class);
typedQuery.setParameter("studentIds", studentIds);
The issue is when JPA generates the query it is adding to_number function to convert the list
SELECT * from student t4 where student_id in (?,?,?);
filter("T4"."student_id"=TO_NUMBER(:9) OR "T4"."student_id"=TO_NUMBER(:10) OR
"T4"."student_id"=TO_NUMBER(:11) OR "T4"."PRODUCT_SET_ID"=student_id(:12)
Any thoughts how to make sure JPA does not add a to_number function, so index will be used.
I had to use an array when I was passing values into a '.in' predicate. Try this:
List<Integer> studentIds=ArrayList<Integer>
Integer[] ids = new Integer[studentIds.size()];
ids = studentIds.toArray(ids);
//Student id is number in database and indexed.
query = "SELECT T.* FROM STUDENT WHERE STUDENT_ID IN (:studentIds)"
TypedQuery<Object[]> typedQuery = entityManager().createQuery( query, Object[].class);
typedQuery.setParameter("studentIds", ids);

Hibernate result list cast to get rows

Hello I had problem with iterate Hibernate ResultList
I had followed query that I got from external class:
queryContent = "select distinct c.identity, c.number, c.status, ctr.name, aab.paymentConditions.currency from AgreementStateBean ast join ast.currentAgreement aab join conagr.contract c where c.agreementStateId = ? and con.mainContractor = true ? "
And I must sum whole aab.paymentConditions.currency, check numbers of statutes and names.
I want to do this by iterate list of results:
Query q = session.createQuery(queryContent);
List result = q.list();
Long wholeCurrency, numberOfStatutes;
for(Object res : result){
//wholeCurrency += res.getColumnName?
}
My question is how to cast res Object to have possibility to get concrete column values? I had read about create map inside hibernate query but I don't know it is good practice to modyfied query string by adding
"new map(" prefix and then ")"
before from sql statement
Solution:
After All I decided to use map in my query. I modified my external query by adding hibernate map statement by replacing select by 'select new map(' and from by ') from'.
Additional thing is to add 'as' statement with name of key because without them column keys are integer.
So after all my query looks like follow:
"select new map( distinct c.identity, c.number, c.status as status, ctr.name as name, aab.paymentConditions.currency as currency ) from AgreementStateBean ast join ast.currentAgreement aab join conagr.contract c where c.agreementStateId = ? and con.mainContractor = true ? "
That was the most siutable solution for me, I tried with 'NEW com.example.MyClass' as Kostja suggested but in my case I didn't have control for incoming query so I can not rely on pernament constructor.
new List( select...
Is also interest but it also didn't tell me on with position I have my field that give me information.
If I understand correctly, you want to have a typed representation of your result without it being an entity itself. For this, you can use constructor queries:
"SELECT NEW com.example.MyClass( e.name, e.data) FROM Entity e"
MyClass has to have a matching constructor. Full qualification (com.example) is not mandatory AFAIK.
If you are using this query often, creating a view in the DB may be a good idea. You can map a view to an entity just as if it were a regular table, but please note that you cannot store changes to you data over a mapped view.
EDIT: Turns out, mapping to an unspecified Map is alright with Hibernate:
select new map( mother as mother, offspr as offspr, mate as mate )
As per http://docs.jboss.org/hibernate/orm/4.2/devguide/en-US/html/ch11.html#ql-select-clause
you can use
queryContent = "select new list(distinct c.identity, c.number, c.status, ctr.name, aab.paymentConditions.currency) from AgreementStateBean ast join ast.currentAgreement aab join conagr.contract c where c.agreementStateId = ? and con.mainContractor = true ? "
And you get List<List> as result.

Select data from two tables using SQL

I have two tables linked by another table like this:
ROLES(RoleID, RoleName)
EMPLOYEES(EmployeeID, E_Name, Address)
ROLE_EMPLOYEES(RoleID#,EmployeeID#).
I want a query that retrieves all from EMPLOYEES and RoleID from ROLES and displays on Java form.
I have tried this but does not work:
rs=st.executeQuery("SELECT EMPLOYEES.*, ROLES.* FROM EMPLOYEES JOIN ROLES");
while(rs.next()){
//MOVE THE CURSOR TO THE FIRST RECORD AND GET DATA
int employeeid=rs.getInt("EmployeeID");
String id=Integer.toString(employeeid);
String name=rs.getString("E_Name");
String addr=rs.getString("Address");
String s = rs.getString("RoleID");
jComboBox1.addItem(s.trim());
//DISPLAY THE FIRST RECORD IN THE TEXT FIELD
txtEmpNumber.setText(id);
txtEmpName.setText(name);
txtEmpAddress.setText(addr);
jComboBox1.setSelectedItem(s);
}
You may try this:
SELECT
EM.*, RL.*
FROM
EMPLOYEES EM
INNER JOIN
ROLE_EMPLOYEES REM ON REM.EmployeeID = EM.EmployeeID
INNER JOIN
ROLES RL ON RL.RoleID = REM.RoleID
Just by writing the keyword JOIN the db-engine does not know in which way it should join the data of the tables; unless you want to retrieve a cartesian product (that's not your case), you need to explicitly set the criteria by using the ON clause.

What will be the Criteria for following SQL?

Can any one help me out with Criteria for following query :
SELECT * From TableA Inner Join TableB On TableA.ID=TableB.ID
I am trying with the following Criteria
Criteria criteria = session.createCriteria(TableA.class);
criteria.setFetchMode("TableB", FetchMode.JOIN);
The above criteria retrives both the table data.
Also if I need only specific columns from TableA how will the criteria Change ?
Thanks for your time.
Edit: TableA has one-to-many relationship with TableB.
Question doesn't make sense. In hibernate, the 2 Tables should actually be entities in which case they would have a relationship between them. Are you trying to randomly join 2 tables and get a result back? If so you have to use sql and use a ResultTransformer to convert the result into objects.
private ResultTransformer getResultsTransformer()
{
ResultTransformer transformer = new AliasToBeanResultTransformer(
MyResultBean.class) {
#Override
public Object transformTuple(Object[] values, String[] aliases)
{
MyResultBean row = new MyResultBean();
for (int i = 0; i < aliases.length; i++)
{
row.set(aliases[i], values[i]);
}
return (row);
}
};
return transformer;
}
Call this as follows:
Query q = session.createSQLQuery(sql);
q.setResultTransformer(getResultsTransformer());
List<MyResultBean> list = q.list();
UPDATE: If Table A has a 1-to-Many with Table B, then I find it easiest to use Alias
Criteria criteria = getSession().createCriteria(TableA.class);
criteria.createAlias("tableB","b");
criteria.add(Restrictions.eqProperty("id", "b.id");
criteria.list();
I hope this helps. Regards,
With JOIN, you need to indicate to Hibernate that you only want the "root entity", whcih is tableA. Add the following to your code:
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

Hibernate Criteria query: getting a list of objects with a m..n relationship where child table does not have a certain property

I have the following tables
CREATE TABLE "COMPANIES" (
"ID" NUMBER NOT NULL ,
"NAME" VARCHAR2 (100) NOT NULL UNIQUE
)
/
CREATE TABLE "COMPANIESROLES" (
"ID" NUMBER NOT NULL ,
"COMPANYID" NUMBER NOT NULL ,
"ROLENAME" VARCHAR2 (30) NOT NULL
)
/
CREATE TABLE "ROLES" (
"NAME" VARCHAR2 (30) NOT NULL
)
/
This structure represents a number of companies and the roles allowed for each company. For these tables, there are the corresponding Hibernate objects:
public class Company implements Serializable {
private Long id;
private String name;
private Set<Role> companyRoles;
//(getters and setters omitted for readability)
}
public class Role implements Serializable {
private String name;
//(getters and setters omitted for readability)
}
Finding out all companies, which have a specific role using the Hibernate Criteria API is no problem:
Session session = this.sessionFactory.getCurrentSession();
Criteria criteria = session.createCriteria(Company.class);
criterion = Restrictions.eq("companyRoles.name", "ADMIN");
criteria.add(criterion);
List<Company> companyList = criteria.list();
Hibernate translates this to an SQL query (approximately)
SELECT *
FROM companies this_
inner join companyroles cr2_
ON this_.id = cr2_.companyid
inner join roles role1_
ON cr2_.rolename = role1_.NAME
WHERE role1_.NAME = 'ADMIN'
And now the problem: how can I reverse the query, i.e. find out all companies, which do not have a mapping for the role "ADMIN"? If I simply try to reverse the criterion by setting
criterion = Restrictions.ne("companyRoles.name", "ADMIN");
(not equals instead of equals), Hibernate creates a query like this
SELECT *
FROM companies this_
inner join companyroles cr2_
ON this_.id = cr2_.companyid
inner join roles role1_
ON cr2_.rolename = role1_.NAME
WHERE role1_.NAME != 'ADMIN'
Obviously, this does not produce the desired output, as the list still contains companies having the role "ADMIN", as long as the companies have at least one other role.
What I want to have is a list of companies, which do not have the role "ADMIN". As an additional restriction, this should be doable by just modifying the Criterion object, if possible (this is because the criterion is built automatically as part of an internal framework, and it is not possible to make larger changes there). The solution should also work, when the Criteria object contains other, additional criterions.
How is this doable, or is it?
You need a subquery (DetachedCriteria).
DetachedCriteria sub = DetachedCriteria.forClass(Company.class);
criterion = Restrictions.eq("companyRoles.name", "ADMIN");
sub.add(criterion);
sub.setProjection(Projections.property("id"));
Criteria criteria = session.createCriteria(Company.class);
criteria.add(Property.forName("id").notIn(sub));
List<Company> companyList = criteria.list();
Something like that should do it.

Categories

Resources