JPA select rows with where clause - java

I know that entityManager.find() method can be used to fetch a row with the primary key.
But I have a requirement to define a common find method which accepts a map having the where clause conditions. In the map, key will be the column name and value will be the column name value of the where clause. This method should return the list of selected rows.
Can some one help me out?

Take a look at: EntityManager.createQuery. If I understand your question correctly, this will allow you to create the query that you would like to execute. You could also, take a look at using a CriteriaBuilder.

find fetches the row respect to the primary key.Now as you want
"common find method which accepts a map having the where clause conditions. In the map, key will be the column name and value will be the column name value of the where clause. This method should return the list of selected rows"
for this you have to go for CriteriaQuery like this :
The following simple Criteria query returns all instances of the Pet entity in the data source:
EntityManager em = ...;
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
Root<Pet> pet = cq.from(Pet.class);
cq.select(pet);
TypedQuery<Pet> q = em.createQuery(cq);
List<Pet> allPets = q.getResultList();
The equivalent JPQL query is:
SELECT p FROM Pet p
Moreover i will advise you to go for annotation based mapping in your entities & look for setter & getter for the methods.In that design also you can have customized method by java logic for this go here to read.

Following might be overkill, but is a fairly generic way to approach it utilizing the criteriaBuilder. While I can't paste the code here (work) I created an abstract BaseFilter<Entity> class.
The easy part is then having the implementing objects provide getXX, setXX properties. A getPredicates() was then added to return an ArrayList of predicates that the abstract BaseDAO could then invoke to perform the query.
We worked specifically with the getXX and setXXX so we could reference the elements via eg, get(Entity1_.childObject).get(ChildObject_.grandChildObject) to assist in refactoring. JPA also supports it via string name so you could implement the getPredicates with that.
JPA requires the actual Entity.class reference in their calls it was a bit of fun trying to obtain it. Eventually a google search turned it up.

Related

getNamedQuery with explicit custom class

Say I have a Person model (Java class and Database table) which has columns/fields like name, age, gender, height, weight.
Now there are 2 possibilities
1) I would need the entire column data..so i would have the named query
as;
#NamedQuery(name = "Person.findAll", query = "Select p from Person
WHERE ..."
2) I need only specific column data..so i would have the named query as;
#NamedQuery(name = "Person.findSpecific", query = "Select p.name,
p.age from Person WHERE ..."
In the first case, if I call/execute the named query as;
Query query = getNamedQuery("Person.findAll");
it automatically maps the response to the Person Java class. But in the 2nd case (specific columns), it does not. It shows the response as Vector with Object array.
My question is is there any explicit way of making the query response map automatically to my custom class when I am using the specific column query
I have already tried
Query query = getNamedQuery("Person.findSpecific",Person.class);
But that again does not map it to Person class.
You can use constructor expressions in the select clause of any JPA query:
select new my.app.PersonView(p.name, p.age) from Person p ...
In this case, for every line in the result, a new PersonView instance is created.
Note that this instances are NOT connected to the data source (they are not managed), so you will not be able to change the underlying data by modifying the instances.
That's why I suggest to NOT use entity classes in constructor expressions to not mix them up with 'real' entities. Instead write custom 'transfer objects' that only carry the data. Either one tailored class per projection or - if many different projections on the same entity are required - one bigger class with multiple constructors that is used for all projections. In that case, some fields will always be empty.

When use createQuery() and find() methods of EntityManager?

I would like to know the difference between on these methods.
When use the createQuery()and find() methods of EntityManager ?
What the advantages about each of them ?
Thank you for answer me.
You use find when you want to look up an entity by primary key. That means you know exactly what you're looking for, you just want to pull it out of the database.
You use createQuery when you want to find entities using criteria or if you want to use a JPQL statement to define what you get back. So you would use the query when you want to get an entity or collection of entities matching some conditions.
The createQuery method allows you to create a JPQL statement that will be executed. The JPQL statement allowed is much more dynamic than the one executed by find. For example given the following table:
create table CAT(
cat_id integer,
cat_name varchar(40)
)
You could execute a query to find the cat by name.
entityManager.createQuery("select c from Cat c where c.name = :name");
The find method only allows you to retreive an object using its primary key. So to use the find method for the above table:
entityManager.find(Cat.class, new Integer(1));
In a nutshell, createQuery allows you to retrieve entities in a more dynamic fashion, while find limits you to searching for an entity with a known id.

Programmatic, "non-dynamic" construction of HQL queries within the bounds of the JPA

Example:
List<Object[]> list = em.createQuery(
"SELECT 'Foo', 123 FROM IrcEvent ev", Object[].class).getResultList();
What I don't like in that example:
How do I know the table name? Can't I specify the entity class instead?
How do I know the column name? jOOQ provides auto-completion by creating a DSL from the database schema.
There could be syntax errors everywhere.
What I basically want is something like
entityManager.deleteAll(EntityClass.class);
to delete the rows of an antire table (for example).
JPA 2 Criteria API http://docs.oracle.com/javaee/6/tutorial/doc/gjitv.html is for creating type safe queries programmatically, but it does not support deletes

What does ":P" mean in a JDO query

I am using JDO on google app engine. Each 'Employee' has a 'key'. I have a set of keys and wanted to retrieve all Employees whose key belongs to this set.
So I implemented it using the 'contains()' filter as specified here. The code works fine and looks like this -
List<Key> keys = getLookupKeys(....) ..//Get keys from somewhere.
Query query = pm.newQuery(Employee.class,":p.contains(key)"); //What is ":P" here?
List<Employee> employees = (List<Employee>) q.execute(keys); //This correctly gives me all I want
All that I wonder is what is this ":P" in this query? The Employee object does not have any field named 'p' neither my query declares any such parameter. So what does this 'p' point to? Does 'p' has any special meaning?
I believe it's mapping an implicit input parameter. As there's only one parameter, you don't need to explicitly call setParameter, you can just use it. I believe it would have been okay as:
Query query = pm.newQuery(Employee.class,":keys.contains(key)");
List<Employee> employees = (List<Employee>) q.execute(keys);
which might be clearer.
See the "implicit parameters" part of the Apache JDOQL docs for another example.

Does Hibernate's Criteria API still not support nested relations

I'd like to use Hibernate's Criteria API for precisely what everybody says is probably its most likely use case, applying complex search criteria. Problem is, the table that I want to query against is not composed entirely of primitive values, but partially from other objects, and I need to query against those object's id's.
I found this article from 2 years ago that suggests it's not possible. Here's how I tried it to no avail, there are other aspect of Hibernate where I know of where this sort of dot notation is supported within string literals to indicate object nesting.
if (!lookupBean.getCompanyInput().equals("")) {
criteria.add(Restrictions.like("company.company", lookupBean.getCompanyInput() + "%"));
}
EDIT:
Here's my correctly factored code for accomplishing what I was trying above, using the suggestion from the first answer below; note that I am even using an additional createCriteria call to order on an attribute in yet another associated object/table:
if (!lookupBean.getCompanyValue().equals("")) {
criteria.createCriteria("company").add(
Restrictions.like("company", lookupBean.getCompanyValue() + "%"));
}
List<TrailerDetail> tdList =
criteria.createCriteria("location").addOrder(Order.asc("location")).list();
Not entirely sure I follow your example, but it's certainly possible to specify filter conditions on an associated entity, simply by nesting Criteria objects to form a tree. For example, if I have an entity called Order with a many-to-one relationship to a User entity, I can find all orders for a user named Fred with a query like this:
List<Order> orders = session.createCriteria(Order.class)
.createCriteria("user")
.add(eq("name", "fred"))
.list();
If you're talking about an entity that has a relationship to itself, that should work as well. You can also replace "name" with "id" if you need to filter on the ID of an associated object.

Categories