Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JPA 2.0: Load a subset of fields for an entity

Tags:

hibernate

jpa

I have an Entity named address. The address Entity has several fields, one of which is CITY. I've created a query by calling entityManager.createQuery but my query only includes the CITY field in the select clause (because I only want to load that field). The CITY field is of type String. When I get my resultList, I do not get a list of Address objects but instead a list of Object[].

Is there any way to have a list of Address created instead of a list of Object[]? My JPA provider is hibernate, latest version. I want a solution that does not require the use of anything Hibernate specific.

like image 348
Justin Kredible Avatar asked Jun 29 '11 19:06

Justin Kredible


2 Answers

This is possible with constructor expressions in your query. Normally you would use this with a custom DTO, but it should work with the entity too. First create an additional constructor in your entity taking only the needed fields:

public Address() {
    //default constructor
}

public Address(String city) {
    this.city = city;
}

Your query could then look like this:

select new your.package.Address(a.city) from Address a where ...

Note that the resulting object is not attached to the EntityManager, so changes to it won't be automatically persisted.

like image 147
Jörn Horstmann Avatar answered Sep 23 '22 05:09

Jörn Horstmann


How would Hibernate load Address instances if you request for cities? JPA entities are objects, and objects are supposed to respect invariants. For example, one such invariant might be that an address always has an ID, a street, etc. If Hibernate loaded partial objects (with only the city attribute filled), those invariants would be broken and you could not rely on your own code anymore. You would also have all sorts of problems if you tried to attach such an Address to another object, or if you simply tried to remove it, because it wouldn't even has an ID anymore.

So the short answer is no : it's not possible.

The long answer is that since Adress is a POJO, you just have to create Addresses from the loaded cities by yourself, or by using a ResultTransformer. But you would get transient Address instances rather than attached Adress entities. This is a recipe for countless bugs and confusion, IMHO.

like image 37
JB Nizet Avatar answered Sep 23 '22 05:09

JB Nizet