I have 2 little problems. Let's say I have an entity class called MyEntity. This class has two kinds of properties. Therefore I have two different class Property1 and Property2 which are also entity classes. There are bidirectional relations betweens MyEntity and the property classes, especially Property1 has an attribute List<MyEntity> owningEntities and Property2 has the attribute MyEntity owningEntity. Now I have the following query:
SELECT e FROM Property1 p JOIN p.owningEntities e WHERE p.name IN :propertyNames
This query returns all entities that has a property of the first type with at least one of the given names. But in general the returned list is indistinct. The problem is that the SELECT DISTINCT downs't work here, at least with criteria API - I didn't try it with jpql. The code for the criteria query looks as follows:
CriteriaQuery<MyEntity> cq = cb.createQuery(MyEntity.class);
Root<Property1> property = cq.from(Property1.class);
SetJoin<Property1, MyEntity> entity =
property.join(Property1_.owningEntities);
cq.where(property.get(Property1_.name).in((Object[]) propertyNames));
cq.select(entity);
// cq.select(entity).distinct(true); --> runtime error
List<MyEntity> resultList = em.createQuery(cq).getResultList();
Is there any way to get a distict result list? I can simply convert the list into a set, but it seems ineffective to extract the same results multiple times.
The next problem is, of course I want all entities that has a property of the any type with at least one of the given names. Until now I have two queries and afterwards I merge the results. But again I extract many results multiple times. So, is there any way to combine the following two queries in an effective way?
SELECT e FROM Property1 p JOIN p.owningEntities e WHERE p.name IN :propertyNames
SELECT e FROM Property2 p JOIN p.owningEntity e WHERE p.name IN :propertyNames
Thanks in advance!
Related
I want to assign SQL query result to Java object which is in non-entity class.
My query is counting the number of records in Table A mapped to another Table B.
#Query(value="select count(a.id) from table1 a join table2 b on a.id=b.id group by a.id", nativeQuery=true)
Non-Entity class
public class Sample {
//assign query result to count variable
private long count;
// getters and setters
}
A and B are Entity class, I'm selecting specified columns of Entity A and B and including that columns in Sample.class and sending data as JSON on REST call.
Now my question is to assign count result to count variable.
Thanks in advance
How to do a JPQL query using a "group by" into a projection (Non-Entity-Class)?
Scenario you have two tables: User and User_Role and you want to know how many users in your system has the "public" role and how many have the "admin" role (Any other roles too if present).
For example: I want a query that will let me know there are two users that have "public" role and one user has the "admin" role.
Simplest Example:
#Query("SELECT ur.roleName, count(u.id) from User u left join u.userRole ur group by ur.roleName")
List<Object[]> getCounts();
In this case dealing with the result is more complicated then you typically would want. You would have to iterate over both the list and array of Objects.
Query into a projection Example:
#Query("SELECT new com.skjenco.hibernateSandbox.bean.GroupResultBean(ur.roleName, count(u.id)) from User u left join u.userRole ur group by ur.roleName")
List<GroupResultBean> getCountsToBean();
This would give you a List that is much better to work with.
Code Example: https://github.com/skjenco/hibernateSandbox/blob/master/src/test/java/com/skjenco/hibernateSandbox/repository/UserProjectionExampleTest.java
I'm relativley new to relational databases and I have some problems concerning the creation of queries. First I want to explain the situation shortly. I have several entity classes. All of them extend AbstractEntity or EntityProperty. So entities can have properties and properties have owning entities, so there is a bidirectional relation.
Now let's say ConcreteEntity extends AbstractEntity and I want to create queries like this: Get all entities of type ConcreteEntity which has at least on property with a name contained in the given list propertyNames. Until now I have the following working criteria query:
CriteriaQuery<AbstractEntity> cq = cb.createQuery(AbstractEntity.class);
Root<EntityProperty> property = cq.from(EntityProperty.class);
Join<EntityProperty, AbstractEntity> entity = property.join(EntityProperty_.owningEntities);
cq.where(property.get(EntityProperty_.name).in((Object[]) propertyNames));
cq.select(entity);
But now I want only those entities of type ConcreteEntity. How could I achieve this?
In JPQL I wrote "SELECT entity FROM EntityProperty property JOIN property.owningEntities entity" and here I also have no idea how to write it in the way that only a specific type is returned...
Thanks for answers in advance!
EDIT: moved the second question to criteria query: indistinct result lists and removed distinct in the code (that didn't work)
I know this is an old question but just in case someone stumbles upon the same problem, here is how it can be solved.
You can easily filter by entity type like this:
Predicate p = cb.equal(entity.type(), cb.literal(ConcreteEntity.class));
where entity can be a Path (Root and Join included), cb is a CriteriaBuilder object. So in your case it would be something like this:
CriteriaQuery<AbstractEntity> cq = cb.createQuery(AbstractEntity.class);
Root<EntityProperty> property = cq.from(EntityProperty.class);
Join<EntityProperty, AbstractEntity> entity = property.join(EntityProperty_.owningEntities);
cq.where(cb.and(
property.get(EntityProperty_.name).in((Object[]) propertyNames),
cb.equal(entity.type(), cb.literal.ConcreteEntity.class)
));
cq.select(entity);
The only way I found until now was to create an enumeration with a value for each class The resulting criteria query is
CriteriaQuery<AbstractEntity> cq = cb.createQuery(AbstractEntity.class);
Root<EntityProperty> property = cq.from(EntityProperty.class);
SetJoin<EntityProperty, AbstractEntity> entity =
property.join(EntityProperty_.owningEntities);
cq.where(property.get(EntityProperty_.name).in((Object[]) propertyNames),
entity.get(AbstractEntity_.entityType).in(suitableSubTypes));
cq.select(entity);
List<AbstractEntity> resultList = em.createQuery(cq).getResultList();
As you can see, every entity now has the attribute entityType. I also have to create the collection suitableSubTypes every time. Another problem is that the returned type is List<AbstractEntity>. What I wanted was a method signature like
public static <T extends AbstractEntity> List<T>
getEntities(Class<T> entityClass, String... propertyNames)
but for now I have
public static List<AbstractEntity>
getEntities(Collection<AbstractEntityType> suitableSubTypes,
String... propertyNames)
So I still hope there exists a better solution...
I have a question regarding querying in hibernate. If there is a way to search without specifying an where cause explicitly?
So what I mean is: let's say I have a search form with 10 columns that are bound to my dto fields. So the user can fill some of them and left the rest as nulls. And now I would like to search only by fields that are specified (filled) and left the nulls behind (they doesn't matter).
So the query would be like this:
select e
from entity e
where e.entity = e.searchedCriteriaEntityGivenInDTO
Or a better example via jpg: I'd like to have all sample entities without specifying "where number, where name, where firstanme", but over my dto by "where dtoFields". As mentioned the nulls should be ignored.
Thanks a lot in advance.
[EDIT]: Thanks to Dragon I have a great solution how to do it, but I have one more question: What about I have 2 row's, I can search? My query should look like:
select e
from example e,
where (e.entity = example) OR (e.entity = example2);
I tried to put the
session.createCriteria(MyEntity.class).add(Example.create(myEntityExample))
into an OR-Predicate but it seems it does not work.
Any suggestions?
No, you can't do it with DTOs, but you can use a prototype (example) entity instance for it:
MyEntity myEntityExample = new MyEntity();
myEntityExample.setNumber(12);
myEntityExample.setName("AA");
myEntityExample.setFirstName("BB");
List<MyEntity> results = session.createCriteria(MyEntity.class)
.add(Example.create(myEntityExample))
.list();
I need to join two JPA entities on a property when there is no FK/PK relation between the two.
I am using Hibernate and can use HQL query like this
select foo, bar from FooEntity as foo, BarEntity as bar
where foo.someothercol = 'foo' and foo.somecol = bar.somecol
However, I want to avoid dependency on Hibernate and use EntityManager instead.
Please help.
Your query is valid JPQL and does not use Hibernate specific functionality (just space between bar and from is missing). In JPA 2.0 specification (4.4.5 Joins) this is explained with following words:
An inner join may be implicitly specified by the use of a cartesian
product in the FROM clause and a join condition in the WHERE clause.
In the absence of a join condition, this reduces to the cartesian
product.
The main use case for this generalized style of join is when
a join condition does not involve a foreign key relationship that is
mapped to an entity relationship. Example: SELECT c FROM Customer c, Employee e WHERE c.hatsize = e.shoesize
Main difference to your query is that your select contains two types of entities. Result of query is List of Object[]. Order of elements in array is same as in select
statement. Following works in your case:
String query =
"select foo, bar from FooEntity as foo, BarEntity as bar "+
"where foo.someothercol = 'foo' and foo.somecol = bar.somecol";
List<Object[]> results = em.createQuery(query).getResultList();
for (Object[] fooAndBar: results) {
FooEntity foo = (FooEntity) fooAndBar[0];
BarEntity bar = (BarEntity) fooAndBar[1];
//do something with foo and bar
}
I'd like to search my data source for all object instances based on the values of an object related by association. The data model can be simplified to: object of type A holds a list of objects of type B. The goal is to find all instances of A where A contains a B such that B has a property value of X.
I can already successfully achieve this using Criteria queries as follows:
List<A> results = session.createCriteria(A.class)
.createCriteria("listOfBs")
.add(Restrictions.eq("propertyInB", x))
.list();
This is a simplification, and multiple properties of B will apply - the search functionality is necessary for a user populated filter.
I would like to replace this approach with query by example - where I'd simply create an object graph with the desirable parameters. My attempt in following the Hibernate docs failed, and is described in this question.
I thought that it might be helpful to demonstrate what I'm trying to achieve in a manner that works, and then seek equivalents - that's why I'm re-asking the question.
In short, my question is: How would you implement the above Criteria Query as a Query by Example in Hibernate? I'm using Hibernate 3.6.6.
Thanks!
Suppose you want to do something like :
Select a.* , b*
from a join b on a.id = b.id
where a.property1 = "wwww"
and a.property2="xxxx"
and b.property1="yyyy"
and b.property2="zzzz"
To implement the above query using Query by Example(QBE):
/***Initialize an instance of Class A with the properties that you want to match***/
A instanceA = new A();
instanceA.setProperty1("wwww");
instanceA.setProperty2("xxxx");
Example exampleA = Example.create(instanceA);
/***Do the same for the Class B**/
B instanceB = new B();
instanceB.setProperty1("yyyy");
instanceB.setProperty2("zzzz");
Example exampleB = Example.create(instanceB);
/**Create and execute the QBE***/
List<A> results = session.createCriteria(A.class)
.add(exampleA)
.createCriteria("b",CriteriaSpecification.LEFT_JOIN) // b is the property of Class A
.add(exampleB)
.list();
The result is already fetch-joined , which means the collection instance B in the A is already fully initialized.