selecting distinct ids from a table through hibernate - java

I have the below pojo which contain many attributes and corresponding setters and getters
public class TOAAarty
{
protected long id;
private long version;
//corresponding setters and getters
}
now i have fire the below query which bring distinct records from the data base
select distinct(id) from toa_arty // so this query bring the distincr ids's
now in the similar fashion i want to rite HQL for this in hibernate to achieve the same as above query so what i have tried is that basically there will be a method which will populate the list with the ids as output
so what i have tried is shown below please advise is it correct and is there any other better approach to achieve the same
public List<Long> findDistinctRrokerIds()
{
Criteria query = session.createCriteria(TOAAarty.class);
ProjectionList proList = Projections.projectionList();
proList.add(Projections.property("id"));
query.setProjection(Projections.distinct(proList));
return (List<Long>) criteria.list(); query.list();
}

Related

Projection into List Field using Hibernate Criteria

I have a POJO something like this
Class BillEntity {
private int id;
private double amount;
private List<Integer> paymentIds;
}
I want to fetch this Object from DB using Hibernate criteria, currently I am having code something like this
DetachedCriteria criteria = DetachedCriteria.forClass(Bill.class);
//some Join aliases, which are working as expected
criteria.setProjection(Projections.projectionList()
.add(Projections.property("id") , "id")
.add(Projections.property("amount") , "amount");
criteria.setResultTransformer(new AliasToBeanResultTransformer(BillEntity.class));
criteria.list();
The id and amount are correctly populated, but I am unsure how paymentIds can be populated.
any pointers appreciated!

Hibernate - sqlQuery map redundant records while using JOIN on OneToMany

I have #OneToMany association between 2 entities (Entity1 To Entity2).
My sqlQueryString consists of next steps:
select ent1.*, ent2.differ_field from Entity1 as ent1 left outer join Entity2 as ent2 on ent1.item_id = ent2.item_id
Adding some subqueries and writing results to some_field2, some_field3 etc.
Execute:
Query sqlQuery = getCurrentSession().createSQLQuery(sqlQueryString)
.setResultTransformer(Transformers.aliasToBean(SomeDto.class));
List list = sqlQuery.list();
and
class SomeDto {
item_id;
some_filed1;
...
differ_field;
...
}
So the result is the List<SomeDto>
Fields which are highlighted with grey are the same.
So what I want is to group by, for example, item_id and
the List<Object> differFieldList would be as aggregation result.
class SomeDto {
...fields...
List<Object> differFieldList;
}
or something like that Map<SomeDto, List<Object>>
I can map it manually but there is a trouble:
When I use sqlQuery.setFirstResult(offset).setMaxResults(limit)
I retrieve limit count of records. But there are redundant rows. After merge I have less count actually.
Thanks in advance!
If you would like to store the query results in a collection of this class:
class SomeDto {
...fields...
List<Object> differFieldList;
}
When using sqlQuery.setFirstResult(offset).setMaxResults(n), the number of records being limited is based on the joined result set. After merging the number of records could be less than expected, and the data in List could also be incomplete.
To get the expected data set, the query needs to be broken down into two.
In first query you simply select data from Entity1
select * from Entity1
Query.setFirstResult(offset).setMaxResults(n) can be used here to limit the records you want to return. If fields from Entity2 needs to be used as condition in this query, you may use exists subquery to join to Entity2 and filter by Entity2 fields.
Once data is returned from the query, you can extract item_id and put them into a collection, and use the collection to query Entity 2:
select item_id, differ_field from Entity2 where item_id in (:itemid)
Query.setParameterList() can be used to set the item id collection returned from first query to the second query. Then you will need to manually map data returned from query 2 to data returned from query 1.
This seems verbose. If JPA #OneToMany mapping is configured between the 2 entity objects, and your query can be written in HQL (you said not possible in comment), you may let Hibernate lazy load Entity2 collection for you automatically, in which case the code can be much cleaner, but behind the scenes Hibernate may generate more query requests to DB while lazy loading the entity sitting at Many side.
The duplicated records are natural from a relational database perspective. To group projection according to Object Oriented principles, you can use a utility like this one:
public void visit(T object, EntityContext entityContext) {
Class<T> clazz = (Class<T>) object.getClass();
ClassId<T> objectClassId = new ClassId<T>(clazz, object.getId());
boolean objectVisited = entityContext.isVisited(objectClassId);
if (!objectVisited) {
entityContext.visit(objectClassId, object);
}
P parent = getParent(object);
if (parent != null) {
Class<P> parentClass = (Class<P>) parent.getClass();
ClassId<P> parentClassId = new ClassId<P>(parentClass, parent.getId());
if (!entityContext.isVisited(parentClassId)) {
setChildren(parent);
}
List<T> children = getChildren(parent);
if (!objectVisited) {
children.add(object);
}
}
}
The code is available on GitHub.

Hibernate Projection on list Field/Attribute and Restricted.in

I am have the following product class
productClass
productID
name
make
title
colors {1..*}.
I'm trying to get
productID, colors and name field only..
I product works for single attirbute but colorList wasn't retrieve.
and worst of all.. when I have a criteria (restrictions.in) it says sql is not form properly.. missing attribute y1_
A good example will be
Hibernate criteria with projection not performing query for #OneToMany mapping
I am trying to get the PAYMENT with expenses intact using project where else he is trying to get some fields in expenses
If you want project any set of attributes for any item of color list, consider use http://github.com/moesio/seimos Here you are an example:
As an example, you can use criteria as follows:
Criteria criteria = session.createCriteria(Cat.class);
criteria.add(Restrictions.like(“description”, “Pap”)
.addOrder(Order.asc(“description”);
Criteria subCriteria = criteria.createCriteria("kind", "kind");
subCriteria.add(Restrictions.eq("description", "persa"));
Criteria anotherSubCriteria = subCriteria.createCriteria("anAssociation","anAssociation");
anotherSubCriteria.add(Restrictions.eq("attribute", "anything"));
criteria.setResultTransformer(new AliasToBeanResultTransformer(Cat.class));
criteria.crateAlias(“kind.anAssociation”, “kind_anAssociation”);
criteria.setProjection(Projections.projectionList()
.add(Projections.alias(Projections.property(“id”), “id”))
.add(Projections.alias(Projections.property(“kind.id”, “kind.id”))
.add(Projections.alias(Projections.property(“kind.anAssocation.attribute”, “kind.anAssociation.attribute”))
List cats = criteria.list();
But if you want save some code, you can use Seimos and code just
Filters filters = new Filters();
filters.add(new Filters(“description”, “Pap”)
.add(new Filter(“description”))
.add(new Filter("kind.description", "persa"))
.add(new Filter("kind.anAssociation.attribute", "anything"));
List<Cat> cats = dao.find(filters);
So, consider use http://github.com/moesio/seimos
If I understand you correctly, then you can use such query for your purposes:
List<Object[]> results = sess.createCriteria(Category.class, "category")
.add(Restrictions.in("category.name", new String[]{"Test1", "Test2"}))
.createAlias("items", "item")
.setProjection(Projections.projectionList()
.add(Projections.property("category.id"), "categoryId")
.add(Projections.property("category.name"), "categoryName")
.add(Projections.property("item.name"))
.add(Projections.property("item.initialPrice")))
.list();
It will return the list of Object[] arrays that represents each row of the result.
I don't know sructure of your Color entity and what fields you need from it thats why I posted example for two default entities: Category and Item (their relationship is one-to-many as in your case).
Instead of array you can use List. For example you can define resrictions in above example in such way:
List<String> inRestrictions = new ArrayList<String>();
inRestrictions.add("Test1");
inRestrictions.add("Test2");
...
.add(Restrictions.in("category.name", inRestrictions))
...
EDIT:
If you need Product object with list of colors for it then fetch only it. If you define correct mapping then Colors list will be fetched with it (lazily or eagerly).
List<Product> results = sess.createCriteria(Product.class)
.add(Restrictions.in("... necessary restrictions")
.list()

Retrieving values of a specific field in Hibernate

Consider a class:
class Employee{
Integer empId,
//many other fields
}
I need a DAO method as shown below
List<Integer> getAllEmployeeIds(){
//??
}
I dont want List<Employee> and (NEW EDIT) Set<Intger>
How can i do that in hibernate?Am using hbm files for mapping
Like this. Also, I recommend use querydsl to make it type-safe.
List<Integer> getAllEmployeeIds(){
return (List<Integer>)createQuery("select e.empId from Employee e").list();
}
use an hql query and do something like
String hql = "select E.empId from Employee E";
Query query = session.createQuery(hql);
List<Integer> ids = query.list();
follow the documentation from here.

What is the best optimized way to select many entities with subentities in JPA?

Let's say we have:
#Entity public class Order {
#Id private int id;
#OneToMany(mappedBy="order") private List<Item> items;
...
}
and
#Entity public class Item {
#Id private int id;
#ManyToOne private Order order;
...
}
And let's say there is 10.000 orders with each having 20 items.
We need to iterate thought all order and all their items.
What is the best way to do it in JPA?
My issue is, if I just iterate the elements like:
for (Order order: em.createTypeQuery("select o from Order o", Order.class).getResultList()) {
report.printOrder(order);
for (Item item: order.getItems()) {
report.printOrderItem(item);
}
}
it will result in 10.001 sql queries:
1 time: select * from order
10.000 times: select * from item where order_id = ?
Is there any way to optimize it? Two queries? One query?
(We are using EclipseLink)
Thanks.
You may also want to consider the EclipseLink query Hint "eclipselink.batch" with value "o.items". This results in two queries but can be more effecient than once large joined query.
You may use join fetch (this also requires distinct since join fetch have a join semantics):
select distinct o from Order o join fetch o.items

Categories

Resources