Hibernate Criteria Query with Vararg Method - java

The objective is to get certain entities with specific ids. I want to create a vararg method that will take entity ids and return the entity list according to the ids:
#Override
public List<Entity> getEntities(long... ids) {
Session s = sessionFactory.getCurrentSession();
s.beginTransaction();
Criteria criteria = s.createCriteria(Entity.class);
for (long id : ids) {
// for very id I want to create a Restriction
// but Restriction goes like
// criteria.add(Restrictions.or(Restrictions.eq("id", id),Restrictions.eq("id", id)));
}
s.getTransaction().commit();
return null;
}
Usage will be:
List<Entity> list = getEntities(453,282,781,784);
How to create such criteria query?

A variable number of OR id = ? clause is like an IN clause. This is done using the Restrictions.in method:
criteria.add(Restrictions.in("id", ids));

criteria.add(Restrictions.in("id", ids));
criteria.addOrder(Order.asc("id"));
will solve your problem it will return your result in the same order which you passed into varargs

Related

Unable to cast Object to Pojo class [duplicate]

I use JPA 1.0:
Query query;
query = em.createNamedQuery("getThresholdParameters");
query.setParameter(1, Integer.parseInt(circleId));
List<Object[]> resultList = new ArrayList();
resultList = query.getResultList();
Here I get result as List<Object[]>, thus I have to type convert all the parameters of the row to their respective types which is cumbersome.
In JPA 2.0 there is TypedQuery which return an entity object of type one specifies.
But as I am using JPA 1 I can't use it.
How to get result as Entity object of type I want??
EDIT:
QUERY
#Entity
#Table(name="GMA_THRESHOLD_PARAMETERS")
#NamedQuery(
name = "getThresholdParameters",
query = "select gmaTh.minNumberOc, gmaTh.minDurationOc, gmaTh.maxNumberIc, gmaTh.maxDurationIc, gmaTh.maxNumberCellId,"
+ "gmaTh.distinctBnumberRatio, gmaTh.minPercentDistinctBnumber from GmaThresholdParameter gmaTh "
+ "where gmaTh.id.circleId=?1 AND gmaTh.id.tspId=?2 AND gmaTh.id.flag=?3 "
)
Your query selects many fields. Such a query always returns a list of Object arrays. If you want a list containing instances of your GmaThresholdParameter entity, then the query should be
select gmaTh from GmaThresholdParameter gmaTh
where gmaTh.id.circleId=?1 AND gmaTh.id.tspId=?2 AND gmaTh.id.flag=?3
The code to get the list of entities would then be
List<GmaThresholdParameter> resultList = query.getResultList();
You'll get a type safety warning from the compiler, that you can ignore.
I can't respond to this as a comment so I'll just go ahead and make it an answer.
List<Object[]> resultList = new ArrayList(); // CREATE an empty ArrayList object
resultList = query.getResultList(); // getResultList ALSO returns its own ArrayList object
And since you assign the list that getResultList() returns to the same variable as you used for your own empty ArrayList, your application loses any connection to your own empty ArrayList and Java will collect it as garbage. Essentially you created it for absolutely no purpose.
what JB Nizet posted is enough.
List<GmaThresholdParameter> resultList = query.getResultList();
I have done something similar since I was using JPA 1 at that time:
final Collection<YourType> typedResult = new ArrayList<YourType>
for(final Object result : query.getResultList())
{
typedResult.add((YourType) result);
}
return typedResult;
List<GmaThresholdParamerter> result= query.getResultList();
for( GmaThresholdParamerter res : result)
{
System.out.println("" +res.getMinNumberOc());
System.out.println("" +res.getMinDurationOc());
}

How to pass list in hql query where list is a value of a map

I have a leaveList containing 4 leave names.This leaveList is passed as map value.I want to get leave details from CompanyLeave Table by passing leaveList in hql query.Let be considered,my Company Leave Table contains 6 leave details.leaveList has 3 leave names.I want to get details of these 3 leaves from CompanyLeave Table.
Code for Hql query here leaveNameList is a list as well as map
public List<CompanyLeaveType> getByValidLeave(Map<String, Object> params) {
Query query = sessionfactory.getCurrentSession().createQuery("from CompanyLeaveType WHERE companyCode = :companyCode and leaveName IN (:leaveNames)");
query.setParameter("companyCode", params.get("companyCode"));
query.setParameter("leaveNames", params.get("leaveNameList"));
List<CompanyLeaveType> validLeaveDetails = query.list();
return validLeaveDetails;
}
N.B: I have got java.util.ArrayList cannot be cast to java.lang.String error.How can I pass list in hql query?
Use query.setParameterList(), Check the documentation here.
Query query = sessionfactory.getCurrentSession().createQuery("from CompanyLeaveType WHERE companyCode = :companyCode and leaveName IN (:leaveNames)");
query.setParameter("leaveNames", params.get("leaveNameList"));
Here you are trying to add a list object to the Hql query.
Here in this case the generated query by hibernate looks like this(actually its not happened and is just to make you to understand whats going on here)
1) Select *from companyLeveType_Table where companyCode=someX and leaveName in(ListObject)
But here the leaveName is of type java.lang.String and hence hibernte frameworks expects the values should be the string only. see the sample code (Hibernte expects this)
2) Select *from companyLeveType_Table where companyCode=someX and leaveName in("A","B","C");
from first query its obvious that hibernate framework tries to convert the java.util.ArrayList to java.lang.String and hence exception throws.
Solution 1)
public List<CompanyLeaveType> getByValidLeave(Map<String, Object> params) {
Query query = sessionfactory.getCurrentSession().createQuery("from CompanyLeaveType WHERE companyCode = :companyCode and leaveName IN (:leaveNames)");
query.setParameter("companyCode", params.get("companyCode"));
query.setParameterList("leaveNames", params.get("leaveNameList")); // changes here only remaining is same
List<CompanyLeaveType> validLeaveDetails = query.list();
return validLeaveDetails;
}
Solution 2:
Use Criteria api.
public List<CompanyLeaveType> getByValidLeave(Map<String, Object> params) {
Criteria criteria=session.createCriteria(CompanyLeaveType.class);
criteria.addCriteria(Restrictions.eq("companyCode",params.get("companyCode")))
.addCriteria(Restrictions.in("leaveName",params.get("leaveNameList")));
List<CompanyLeaveType> validLeaveDetails =criteria.list();
return validLeaveDetails;
}
I hope this helps you

Select multiple items based on multiple IDs with hibernate

I am using hibernate in eclipse.
And i have 3 ONE TO MANY relation tables.
ONE [Company] --> MANY [Officer], And ONE [Officer] --> MANY [Task].
They all have unique id (companyId, officerId, taskId).
Currently i know how to find all the tasks belong to an officer and i also know how to find all the officers belong to a company.
here is the code snippet:
public static ArrayList<Officer> getOfficersByCompany(Company company){
ArrayList<Officer> officers = new ArrayList<Officer>();
DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Officer.class);
detachedCriteria.add(Restrictions.eq(Key.COMPANY, company));
detachedCriteria.add(Restrictions.eq(Key.OBJSTATUS, Value.ACTIVED));
List<Object> list = HibernateUtil.detachedCriteriaReturnList(detachedCriteria);
for(Object o : list){
officers.add((Officer) o);
}
return officers;
}
And below is the detachedCriteriaReturnList method in HibernateUtil class.
public static List<Object> detachedCriteriaReturnList(DetachedCriteria dc){
Session session = getSessionFactory().openSession();
session.beginTransaction();
Criteria criteria = dc.getExecutableCriteria(session);
List<Object> list = criteria.list();
session.getTransaction().commit();
session.close();
return list;
}
However, if i try to get all the task belongs to a company, how should i implement the code. I have tried using: detachedCriteria.add(Restrictions.allEq(officers));
public static ArrayList<Task> getTasksByOfficers(Map<String, Object> officers){
ArrayList<Task> tasks = new ArrayList<Task>();
DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Task.class);
detachedCriteria.add(Restrictions.allEq(officers));
List<Object> list = HibernateUtil.detachedCriteriaReturnList(detachedCriteria);
for(Object o : list){
tasks.add((Task) o);
}
return tasks;
}
But i realise that the map only stores unique key and value pair, if i try to use the second officer's id the first one will be replaced.
Or is there any other ways to perform the selection faster and more efficient?
ONE [Company] --> MANY [Officer], And ONE [Officer] --> MANY [Task].
In HQL this should be pretty straight forward (I gave up using Criteria API, as it did not allow joining the same object class twice):
Obviously, I did not test the queries, but they should work...
select Task
from Task join Task.Officer o join o.Company c
where c.name = 'xxx'
or
select t
from Company c join c.Officers o join o.Tasks t
where c.name = 'xxx'
Note: My experience with criteria is limited, as I have said. But looking at your code, I have two comments. Maybe you should not use the Map of officers but the list officers.values() to allEq(). Second remark: If you didn't do a mistake, Hibernate obviously magically finds the reference to the property you want to be allEq with, otherwise, the allEq misses a property you want to compare to.
UPDATE: Ok, as promised, I checked the Javadocs for you: https://docs.jboss.org/hibernate/orm/3.5/api/org/hibernate/Criteria.html
A join in HQL is the equivalent of a criteria added to another criteria or an alias:
detachedCriteria = DetachedCriteria.forClass(Task.class)
.createCriteria("Officer") // Officer property of task
.createCriteria("Company") // Company property of officer
.add(Restriction.eq(Key.COMPANY, compKey); // the company
List<Object> list = detachedCriteria
.getExecutableCriteria(hibernateSession)
.list();
This should get you going...
Note on HQL:
To run the query, you get a query from the hibernate session with the HQL and then you call list() or executeUpdate()on it. taskHqlString is a HQL-statement as above. Replace the companyKey in the query with a named parameter :companyKey:
String taskHqlString = "select Task "
+ " from Task join Task.Officer o "
+ " join o.Company c "
+ " where c.name = :companyKey";
List<Task> list = (List<Task>)hibernateSession
.createQuery(taskHqlString)
.setParameter("companyKey", companyKeyValue)
.list();

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: how do I retrieve my entities from a ScrollableResults?

I do a query that returns a list of entities. How can I retrieve the entities from a ScrollableResults:
Session s = ....;
Query q = s.createQuery("....") # returns 100000s rows
ScrollableResults sr = q.scroll();
sr.scroll(45999); # just a number
Employee employee = ???
How do I get an employee in the last line of code
try the get(0) method, or get()[0]
Here's a link to API: ScrollableResults
get() returns the entire current row, get(index) returns object at index position without initializing the rest of them. There are also a bunch of convenience getXXX() methods that cast result to given type.
I do a query that returns a list of entities. How can I retrieve the entities from a ScrollableResults... How do I get an employee.
Just to improve the other answers, the ScrollableResults does the entity conversion for you although this isn't immediately clear from the Javadocs.
As #Bozho says, calling sr.get() will return the entity at the current location, but wrapped in an array. In looking at the code for ScrollableResultsImpl the current row's result is set with:
if ( result != null && result.getClass().isArray() ) {
currentRow = (Object[]) result;
} else {
currentRow = new Object[] { result };
}
So ScrollableResults.get() always returns an array of results and if your entity is not an array, it will be at get()[0].
So, with your code you would do something like:
while (sr.next()) {
// get the entity which is the first element in an Object[]
Employee employee = sr.get()[0];
...
}
To retrieve entities the simplest way would be to cast the object to whichever object you want:
E.g:
ScrollableResults sr = q.scroll();
while (sr.next()) {
CustomObject object = (CustomObject) sr.get()[0]; // Now CustomObject will have all the properties mapped
}
This works perfect for all the scenarios.

Categories

Resources