Consider table A and B. Entire column in table A and only one column in table B need to be taken.Previously,a named query is created with which entire column values of table A are taken. Now i need to include one column of table B too.
In DAO class,below is code
X x=null
Query query = getEntityManager().createNamedQuery("AAA").setParameter("serialID",val);
x=(X) query.getSingleResult()
And in DTO class, AAA is part of class X which refers to table A. The query of AAA is below:
select X from A X where COLUMNVAL= serialID;
Now, table B also has COLUMNVAL too and i need to consider value of xyz column from that table.Consider xyz is mapped in class Q.
I tried the below query for which i got classcast exception as java.lang.object cannot be cast to A
select X, Q.xyz from A X, B Q where X.COLUMNVAL = Q.COLUMNVAL AND X.COLUMNVAL=serialID
Please favour how to proceed further. A has huge number of columns so ResultList is not preferred.
I tried the below query for which i got classcast exception as
java.lang.object cannot be cast to A
select X, Q.xyz from A X, B Q where X.COLUMNVAL = Q.COLUMNVAL AND
X.COLUMNVAL=serialID
if you wish to use that query, you'll non get objects of class A, but instead an Array of Object where the first element is an object of class and the second element is the value Q.xyz
so you should use
Object[] x;
x=(Object[]) query.getSingleResult()
Create a ResultDTO class, which extends entity class A thus having all fields from class A and have its own required field(xyz) of the entity class B. Now you can do this to get ResultDTO:
String queryString = "select a, b.xyz from A a join B b on(a.field = b.field)"
+ " where a.serialID = :serialID";
return (List<ResultDTO>) entityManager.createQuery(queryString)
.setParameter("serialID", serialId);
.unwrap(org.hibernate.query.Query.class)
.setResultTransformer(Transformers.aliasToBean(ResultDTO.class))
.getResultList();
Moreover, I would suggest you to read this post The best way to map a projection query to a DTO (Data Transfer Object) with JPA and Hibernate
Related
Can any one tell me why addEntity is not identifying separate column from alias? Both parent and child getting child value only. parents field is getting override by child filed.
If I keep pr.* first in select statement then it take parent value in both object.
My code is as below.
String sql="select ch.*,pr.* from users as ch inner join users as pr on ch.parent_id=pr.id";
Query
query=session.createSQLQuery(sql).addEntity("ch",UserDTO.class).addEntity("pr",UserDTO.class);
List<Object> result=query.list();
Object[] objects = (Object[])result.get(0);
UserDTO child=(UserDTO)objects[0];
UserDTO parent=(UserDTO)objects[1];
I have read this doc hibernate doc, it is suggesting to use as follow. But {} is not working in mysql select.
sess.createSQLQuery("SELECT {cat.*}, {mother.*} FROM CATS c, CATS m WHERE c.MOTHER_ID = c.ID")
.addEntity("cat", Cat.class)
.addEntity("mother", Cat.class)
I cannot find a solution to a problem that seems to be easy. Say there are 2 entity classes:
class A {
Set<B> bs;
}
class B {
String text;
}
How to create a criteria query that returns all A's that contains at least one B entity which fulfills a given condition (like b.text = 'condition')?
I think this link can be useful:
http://mikedesjardins.net/2008/09/22/hibernate-criteria-subqueries-exists/
It contains the following example about how create n exists criteria:
"What you’re really trying to do is to obtain all Pizza Orders where an associated small pizza exists. In other words, the SQL query that you’re trying to emulate is
SELECT *
FROM PIZZA_ORDER
WHERE EXISTS (SELECT 1
FROM PIZZA
WHERE PIZZA.pizza_size_id = 1
AND PIZZA.pizza_order_id = PIZZA_ORDER.pizza_order_id)
The way that you do that is by using an “exists” Subquery, like this:
Criteria criteria = Criteria.forClass(PizzaOrder.class,"pizzaOrder");
DetachedCriteria sizeCriteria = DetachedCriteria.forClass(Pizza.class,"pizza");
sizeCriteria.add("pizza_size_id",1);
sizeCriteria.add(Property.forName("pizza.pizza_order_id").eqProperty("pizzaOrder.pizza_order_id"));
criteria.add(Subqueries.exists(sizeCriteria.setProjection(Projections.property("pizza.id"))));
List<pizzaOrder> ordersWithOneSmallPizza = criteria.list();
And voila, the result will contain two PizzaOrders!"
I have two entity objects (A and B) that have a One-To-Many relationship. I am using JPA (Hibernate) to join these tables and query them for a specific result set, but the criteria I specify for the child table (B) are not applied when fetching my results. This is how I have defined the query:
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<A> query = builder.createQuery(A.class);
Root<A> a = query.from(A.class);
Join<A, B> abJoined = a.join(A_.b);
query.distinct(true)
.where(builder.and(
builder.equal(a.get(A_.id), id),
builder.equal(a.get(A_.active), 1),
builder.equal(a.get(A_.location), 1011),
builder.equal(a.get(A_.status), "Pending"),
builder.equal(abJoined.get(B_.status), "Not Moved"),
builder.greaterThan(abJoined.get(B_.detailId), 0)
));
When I call entityManager.createQuery(query).getResultList(); I get one instance of entity 'A', but when I try to access 'B' through 'A' a.getB() the two criteria that I had specified for abJoined are not applied and I get all instances of 'B' that are joined to 'A'. Is there something more I need to do to get these criteria applied? If the criteria cannot be applied, is there a recommended method for removing the corresponding instances of 'B' from the result set?
I can provide more code or other details if necessary.
The query is used to select which A entities must be returned by the query. But the A entities will never be partial entities containing only a subset of their Bs. They will always be complete instances of A, reflecting the state of what A is in the database, and which B this A is related to.
BTW, even if this was possible (it's not, and explicitely forbidden by the JPA spec), your query would at least have to load the Bs as well, using a fetch join. Otherwise only the state of A is returned by the query, and the linked Bs are loaded lazily.
But in JPA, for a #OneToMany relationship, Query is fired first on the master, with all the Criteria and fetches just master records.
Later Individually the query is fired, BUT BUT BUT......the B table criteria will not contain all the conditions, but only one condition i.e. just the primary key VALUE of master records fetched in i.e just with one condition "b.A_id=[primarykeyfetched from master]"
SOLUTION is simple
Make an Independent class, in which we require the fields of #OneToMany relationship
STEP 1
public class AB {
private A a;
private B b; //#OneToMany with A in the Entity class definitions
public AB(){}
public AB(A a, B b){ ///Very Important to have this constructor
this.a=a;
this.b=b;
}
getter setter....
}
STEP 2
CriteriaQuery<AB> q = criteriaBuilder.createQuery(AB.class);
Root<A> fromA = criteriaQuery.from(A.class);
List<Predicate> predicates = new ArrayList<Predicate>();
Join<A,B> fromB = fromA.join("b", JoinType.INNER);/*"b",fieldName of B in entity Class A*/
criteriaQuery.select(criteriaBuilder.construct(AB.class,A,B));//looks AB's 2 param constr.
predicates.add(criteriaBuilder.equal(fromA.get("name"), filter.getName()));
predicates.add(criteriaBuilder.equal(fromB.get("salary"), filter.getSalary()));
..........
List<AB> ABDataList = typedQuery.getResultList();
for(AB eachABData :ABDataList){
....put in ur objects
obj.setXXX(eachABData.getA().getXXX());
obj.setYYY(eachABData.getB().getYYY());
}
This will give all the results applying all the criteria to master table A, and comparing the primary key of Table B instead of foreign key.
I'm using native query to get data from database and add them into an object that content float values like:
select tons, delivered_tons from contract where id = 1
and using createSQLQuery() to execute the query
and return an object array like:
Object[] result = (Object[])query.uniqueResult();
and cast them into my object
A a = new A((Float)result[0],(Float)result[1]);
The problem is that I can't know the return type of the query (float or double). So do hibernate has any method to control the return type?
If you used HQL instead os SQL, Hibernate would use the types that you chose to map the columns in your entity:
Assuming you have a Contract entity containing these fields:
#Entity
public class Contract {
#Column(name = "tons")
private Float tons;
#Column(name = "delivered_tons")
private Float deliveredTons;
...
}
You would simply execute the HQL query
select c.tons, c.deliveredTons from Contract c where c.id = :id
and you would be sure to get an array containing two Floats.
That said, for such a simple query, why don't you just use
Contract c = (Contract) session.get(Contract.class, id);
and then get the fields you want from the entity?
Lets say that class 'X' is mapped to table 'X' class 'A' is mapped to Table 'A' and Class 'B is mapped to table 'B'.
Table X Structure:(X_ID, some other columns
Table A Structure:(A_Id,X_Id, some other columns)
Table B Structure:(A_Id, some other columns)...Table B also has A_Id
Class 'B' extends class 'A'. We have the mapping files for both of them as:
Class 'A' Parent Mapping file:
#Entity
#Table(name = 'A')
#Inheritance(stratergy=InheritanceType.Joined)
public abstract class A {
#Id #Clumns(name = "A_Id)
#GeneratedValue
protected Long aId;
-- some more A specific fields
}
Class 'B' Mapping file:
#Entity
#Table(name= 'B')
Public class B extends A{
---- B specific fields
}
Now, I have a SQL Query as below that I need to write using hibernate criteria API.
select * from X
INNER JOIN A
ON X.id = A.id
INNER JOIN B
ON A.id = B.id
where B.name = 'XYZ'
and B.Sex = 'M'
I have come up with:
Criteria c = session.createCriteria(x.class, "x");
.createAlias("x.a", "a")
.createAlias("a.b", "b")
.add(Restrictions.eq("b.sex", "M"))
.add(Restrictions.eq("b.name", "XYZ"));
But, if we check the mapping file, there is no direct reference of B in A. Hence hibernate throws out "B not related to A" entity.
Is there any way this inheritance can be mapped in query crteria
You shouldn't need to reference A at all in your criteria, or use any aliases.
Criteria c = session.createCriteria(B.class);
.add(Restrictions.eq("sex", "M"))
.add(Restrictions.eq("name", "XYZ"));
will give you the result you need.
Because of the InheritanceType.Joined, this will probably produce SQL that includes a join to the the A table (something close to the sql you show), but it isn't necessary to specify that join in the criteria.
The things that look like columns in the criteria are actually (reflective) references to fields in your Java objects. Hibernate figures out the columns to put in the sql from your annotations, and should the join to the A table if it's needed based on the inheritance annotation.
To be sure of this in your context, and to understand all this a bit better, I'd advise trying it and turning on logging of the generated sql as described in this answer to another SO hibernate question.
Try this way:
Criteria rootCrit = session.createCriteria(A.class);
rootCrit.createAlias("B", "B");
rootCrit.add(Restrictions.eq("B.sex", "M"));
rootCrit.add(Restrictions.eq("B.name", "XYZ"));