How in hql query select part of object? - java

I need tune query for performance. The tree of objects like:
classA {
classB b;
classC c;
.....}
I need select similar to SQL:
select a.field1, b.field2, c.field3, c.field4 from a left outer join b
on a.id=b.fk left outer join c on b.id=c.fk
I don't understand what kind of result will be returned, does it arrayList? Or query returns
all 3 objects?
Thanks.

It will be
List<Object[]> list = new ArrayList<Object[]>();

The result which would be returned by the query would be type of -
List<Object[]>

If you use HQL I think you use hibernate. Provide mapping with relations (ManyToOne or OneToOne) to your objects:
class A {
#ManyToOne
pribvate B b;
#OneToOne
private C c;
}
Then use session methods to select your object A with hql query of criteria. Hibernate do all joins for you automatically. And it will return List of A.

Related

using enum list as parameter in HQL query

I have an entity called Band with a attribute List<Genres> genres, Genres is a ENUM with the following values: ALTERNATIVE_ROCK("Alternative Rock"), CLASSIC_ROCK("Classic Rock"), HARD_ROCK("Hard Rock"), HEAVY_METAL("Heavy Metal"),PROGRESSIVE_ROCK("Progressive Rock");
I'm trying to create a method that returns a List<Band> using an List<Genres> as parameter using HQL, something like:
public List<Band> listBandsPerGenres(List<Genres> genres);
But i'm receiving some errors with HQL queries that i'd tried?
Above some hql queries that i've tried...
Query q = getSession().createQuery("SELECT b FROM Band b JOIN FETCH b.genres g WHERE g IN (?)");
q.setParameter(0, genres);
return q.list();
returns an error saying that an ArrayList cannot be cast to Enum...
or...
"SELECT b FROM Band b JOIN FETCH b.genres g WHERE g.value IN (?)"
returns an error like : dereference scalar collection element ENUM
property genres mapping, entity Band...
#Basic(optional=false)
#Enumerated(EnumType.STRING)
#ElementCollection(targetClass=Genres.class)
#CollectionTable(name="banda_generos", joinColumns=#JoinColumn(name="id_banda", nullable=false))
private List<Genres> genres;
This works for Hibernate 4
Query q = s
.createQuery("SELECT b FROM Q27715453$Band b JOIN b.genres g WHERE g IN (:genres)");
q.setParameterList("genres", Arrays.asList(Genres.ROCK, Genres.CLASSIC));
System.out.println(Arrays.toString(q.list().toArray()));
Check that the method Query#setParameterList is used instead of Query#setParameter, also it's used g insted of g.value.
I don't think you can do that. According to JPA spec (section 4.6.9. page 185) lists aren't supported as left-side operand with IN expression.

Possible to perform a NOT IN for one-to-many relationship with Hibernate criteria?

I have a question about Hibernate and if it's possible to achieve the query using the Criteria API with the current data model structure I'm using. I have a data model with the following structure:
ParentClass contains a List:
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, targetEntity = org.test.ChildClass.class)
#JoinColumn(name = "child_uuid")
private List<ChildClass> childList = new ArrayList<ChildClass>();
The child class has one field:
private String testField
The query I'm attempting to write can be expressed as follows:
Return a list of all ParentClass objects that have the ABSENCE OF an object ChildClass that has a "testField" value of "1". In other words, there must not be an object in that list that has the testField value of 1.
Currently I have this query:
Criteria criteria = getSession().createCriteria(org.test.ParentClass);
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
criteria.createAlias("childList", "c");
SimpleExpression expression = Restrictions.ne("c.testField", "1");
criteria.add(expression);
return (List<T>) criteria.list();
What happens is that I will get any ParentClass objects that contain at least one ChildClass that has a value of c.testField other than "1". This includes ParentClass objects that DO have a "testField" value of "1", which I'm trying to exclude entirely.
The table structure has ChildClass having a reference to ParentClass, but not vice versa. So it seems that each ChildClass object is joined with the ParentClass, and if they fulfill the above restriction, that ParentClass gets returned. This is the incorrect result as it means a ParentClass that has two ChildClass objects, one with value "1" and the other with value "2" will get returned.
Thanks for any help
You need the equivalent of the following HQL query:
select distinct p from Parent p
where not exists (select c.id from Parent p2 join p2.children c
where c.testField = '1' and p2.id = p.id)
You should be able to translate that to Criteria (if you really want to use criteria instead of using clearer HQL queries). You'll need to use Subqueries.notExists().
try with this one
Criteria criteria = getSession().createCriteria(org.test.ParentClass,"parent");
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
criteria.createAlias("parent.ChildClass", "pc");
SimpleExpression expression = Restrictions.ne("pc.testField", "1");
criteria.add(expression);
return (List<T>) criteria.list();

Hibernate Criteria. Join / Select when no Assosiation

I am using Hibernate version 4.2
I have 2 Entities.
#Entity
public class A {
Long Id;
#ManyToOne
B b;
}
#Entity
public class B {
Long Id;
//There is no relation back here with any annotations to A, and can't add a #OneToMany
}
is it possible todo a Query with Hibernate Criteria to get a result that looks like this.
List<Map<B,List<A>>> ? dosn't matter if it is with a join or a select.
example what i want in result:
A.id B.id
1 1,2,3,4
2
3 5
4 7
5
//Trind
You can use something like below. I don't know whether it is your actual requirement though. Assuming B b is OneToOne, 12 is the id of B,
Criteria c = session.createCriteria(A.class, "a");
c.createAlias("a.b", "b");
c.add(Restrictions.eq("a.b.Id", "12"));
return c.list();
this returns a list of arrays and by using those arrays you can form what you want.
I got help from Christian Bauer who have Written Hibernate in Action.
Criteria from Hibernate:
List<Object[]> result =
session.createCriteria(A.class, "a")
.createAlias("b", "i", JoinType.RIGHT_OUTER_JOIN)
.setResultTransformer(PassThroughResultTransformer.INSTANCE)
.list();

What is the object type returning in a join of a hibernate query

When I have the below query it will give me a list of Product.
List<Product>=
getCurrentSession().createQuery("SELECT p FROM Product p ").list();
What will it return when there is a join as below.
getCurrentSession().createQuery("SELECT p FROM Product p inner join ProductCategory pc where p.id=pc.id").list();
It should return List<Object[]> as a result. Please see this thread
And you should access your entities like
for (Object[]> result : query.list()) {
Product p = (Product) result[0];
ProductCategory pc = (ProductCategory) result[1];
}
SELECT p FROM Product p inner join ... something like that gives you a list of Products.
FROM Product p inner join ... something like that gives you a list of arrays.
This will return a list of objects. You will have to cast them in to Product
List list = session.createQuery("SELECT p FROM Product p inner
join ProductCategory pc where p.id=pc.id").list();
According to the documentation for javax.persistence.Query, you are going to get a List back. Why would you think it should be different?
This class casting from java.lang.object to model class doesn't work in any ways. Below is my code.
List<Contactinfo> listStudentInfo = new ArrayList<Contactinfo>();
//listStudentInfo = dataService.getAllStudent(studentInfo);
listStudentInfo = dataService.getStudentInfo();
System.out.println(listStudentInfo.size());
Contactinfo contactinfo = (Contactinfo)listStudentInfo.get(0);
But In hibernate, you don't need join if you have both Entity associated with by #Many-to-one or #One-to-one join annotation. Then you need to select one object only , you will automatically get access to other object via the join. Make sure you keep getter(), setter() method for the joining field. Hope this will clarify the situation.

How to create a JPA query with LEFT OUTER JOIN

I am starting to learn JPA, and have implemented an example with JPA query, based on the following native SQL that I tested in SQL Server:
SELECT f.StudentID, f.Name, f.Age, f.Class1, f.Class2
FROM Student f
LEFT OUTER JOIN ClassTbl s ON s.ClassID = f.Class1 OR s.ClassID = f.Class2
WHERE s.ClassName = 'abc'
From the above SQL I have constructed the following JPQL query:
SELECT f FROM Student f LEFT JOIN f.Class1 s;
As you can see, I still lack the condition OR s.ClassID = f.Class2 from my original query. My question is, how can I put it into my JPQL?
Write this;
SELECT f from Student f LEFT JOIN f.classTbls s WHERE s.ClassName = 'abc'
Because your Student entity has One To Many relationship with ClassTbl entity.
If you have entities A and B without any relation between them and there is strictly 0 or 1 B for each A, you could do:
select a, (select b from B b where b.joinProperty = a.joinProperty) from A a
This would give you an Object[]{a,b} for a single result or List<Object[]{a,b}> for multiple results.
Normally the ON clause comes from the mapping's join columns, but the JPA 2.1 draft allows for additional conditions in a new ON clause.
See,
http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Querying/JPQL#ON
Please see :
public interface YourDBRepository extends JpaRepository<Employee, Long> {
#Query("select new com.mypackage.myDTO(dep.empCode, dep.empName, em.EmployeeCode, em.EmployeeName) \n" +
"from Department dep\n" +
"left join Employee em\n" +
"on dep.DepartmentCode = em.DepartmentCode") // this is JPQL so use classnames
List<myDTO> getDeptEmployeeList();
}
You can also use CrudRepository and include #JoinColumn with FK table class in PK table class and have List return list and then do find operation to achieve the same.
In Department entity class:
#OneToMany
#Fetch(FetchMode.JOIN)
#JoinColumn(name="DEPT_CODE")
private List<Employee> employees;
CriteriaBuilder is yet another option.

Categories