My JPA 2.0 Wish List
Until now we have enjoyed easy persistence using JPA 1.0. It's true that JPA 1.0 has some limitations, but now our friends from JSR-317 are working hard to give us a better standard persistence for Java.
I'm part of OpenXava project team, OpenXava produces a full application using as source only Java classes annotated with JPA, so the JPA 2.0 specification is very important for OpenXava. But, JPA 2.0 specification is also very important for all Java developers, because the expressivity of our model will be directly proportional to the expressivity of the new JPA 2.0.
The JPA 2.0 has a lot of new great features, and some of them like me a lot. You can see it by download the draft of the specification from JCP, or by reading the two (part I and part II) articles of Mike Keith here, in JavaLobby.
But
this article is for talking about the missing features of JPA 2.0. I'm
going to say you my wish list for JPA 2.0. Please, if some of the
features like you, send your comment to jsr-317-comments@jcp.org. Maybe, we can influence in the new JPA 2.0.
This is my wish list for JPA 2.0:
- Restriction in callback methods.
- @ManyToOne, @OneToMany and @ElementCollection implicits.
- Converters.
- Method in EntityManagerFactory for obtaining the list of all entities.
- Composite keys without key class.
- UUID as GeneratedType for @GeneratedValue.
- Default fetch value for @ManyToOne.
- @ElementCollection.
- Qualified properties in @OrderBy.
1. Restriction in callback methods
I'm waiting for JPA 2.0 only for seeing the next paragraph from 3.5
Entity Listeners and Callback Methods removed from the
specification:
In general, the lifecycle method of a portable application should
not invoke EntityManager
or Query operations, access other entity instances, or modify
relationships within the same persistence context.
But, it still remains there. Horror!
Each time my developers need to use callback methods is for querying or
saving data. And they need to use JPA to do it. And just it is
forbidden. The conclusion after a time working with JPA is that
callback methods are simply useless.
That is, these scenarios are typical:
- In order to remove some entity I need to verify if some data exists, and we want do it using a JPA query.
- When a entity is saved, some other entities must be automatically created and saved, and we want to use JPA query to do so.
Why not remove this restriction from @PrePersist or @PreRemove at least?
Or, we can create other annotations (executed always before the flush)
where we can use Query and EntityManager.
2. @ManyToOne, @OneToMany and @ElementCollection implicits
This another suggestion is that @ManyToOne, @OneToMany and
@ElementCollection can be implicit, just as @Basic annotation already
is in JPA 1.0.
That is, instead of writting:
@Entity
public class Invoice {
...
@ManyToOne
private Customer customer;
@OneToMany (mappedBy="invoice")
private Collection<Delivery> deliveries;
}
We can write the next code:
@Entity
public class Invoice {
...
private Customer customer;
private Collection<Delivery> deliveries;
}
And JPA will assume a @ManyToOne for customer and a @OneToMany for
deliveries.
This approach has at least two advantage:
- Easy migration from non-JPA code to JPA.
- Less code to write in the hand of the programmer.
3. Converters
In my world it's usual to develop Java applications against legate
database, designed in many case by RPG or COBOL programmer. When types
of the data are not suitable for good Java model classes. For example,
some databases uses 3 numeric values for a data, or a VARCHAR with
arbitrary values that can be mapped to a boolean. A standard type
converter mechanism is needed for this so common scenarios.
Custom
value type of Hibernate or Converters of OpenXava 2 (for single
value, for
multiples values) are two valid options.
Another useful feature is the possibility of declaring conversion
policies by default. Look the default
converters of OpenXava.
4. Method in EntityManagerFactory for obtaining the list of all entities
In OpenXava project we need the
next code:
private static Collection obtainManagedClassNamesUsingHibernate() {
// The next code is Hibernate dependent.
// This code has to be modified in order to work with Glassfish, OpenJPA, etc.
EntityManager manager = XPersistence.createManager();
org.hibernate.impl.SessionImpl impl = (org.hibernate.impl.SessionImpl) manager.getDelegate();
Collection result = impl.getSessionFactory().getAllClassMetadata().keySet();
manager.close();
return result;
}
As you can see, this code is ugly and dependent on Hibernate
implementation
OpenXava is a framework for creating business application from POJOs
annotated with JPA, in order to work it needs to know, at least, the
list of the entities managed by JPA.
To have a standard way to do it would be nice. Maybe a method in
EntityManagerFactory.
Moreover, obtaining the metadata without connecting to database will be
really great.
5. Composite keys without key class
the idea is that we can define an entity with composite key in this simple way:
@EntityNo more. No @IdClass. No @EmbeddedId.
public class Invoice {
@Id
private int year;
@Id
private int number;
...
}
The only place when we will need the key class is for find() method of EntityManager. In this case, we can use some of the next approaches:
1. Map
Map key = new Map();2. Array
key.put("year", 2008);
key.put("number", 3);
Invoice invoice = manager.find(Invoice.class, key);
Invoice invoice = manager.find(Invoice.class, new Object[] { 2008, 3} );
3. Varargs
Invoice invoice = manager.find(Invoice.class, 2008, 3);
4. Refresh
Invoice invoice = new Invoice();
invoice.setYear(2008);
invoice.setNumber(3);
manager.refresh(invoice);
My favourite is the 4.
6. UUID as GeneratedType for @GeneratedValue
Why is not included UUID as GeneratedType for @GeneratedValue ?
Hibernate JPA includes it.
In my organization we develop applications that need to work on AS/400,
Informix, Postgres, MS SQL and MySQL. Using UUID for generating id is
very useful for us, because is very easy migrating from a database
product to another.
I wonder it is not included in JPA.
7. Default fetch value for @ManyToOne
This proposal for JPA 2.0 is about to change the default value of
ManyToOne(fetch ), or even better the possibility to declare it in the
orm.xml, or persistence.xml files.
The next paragraph:
The recommanded approach is to use LAZY onn all static fetching definitions and override this choice dynamically through JPA-QL. JPA-QL has a fetch keyword that allows you to override laziness when doing a particular query. This is very useful to improve performance and is decided on a use case to use case basis.
is extracted from Hibernate JPA documentation.Really in most cases is much better to use LAZY fetching than EAGER fetching. This requires that the developer always must write fetch=FetchType.LAZYon @ManyToOne. It's better that the more common and convenient way would be the default one.
That is, my proposal is that fetch on @ManyToOne will have the default value to LAZY.
Even better will be to declare the default value for fetching in ManyToOne in persistence.xml or orm.xml. In this way we can decide in a global fashion our fetching strategy for references.
8. @ElementCollection
Adding embedded collections to JPA 2.0 are very, very good idea.
Until now we have to use collection to
entities as alternative.
But the annotation to mark it is really ugly:
@ElementCollection
protected Set<String> nickNames = new HashSet();
It's ugly.
Why not:
@ManyToOne @Embedded
protected Set<String> nickNames = new HashSet();
Or still better:
@EmbeddedCuriously, OpenXava has a @AsEmbedded annotation that can be applied to references and collections.
protected Set<String> nickNames = new HashSet();
9. Qualified properties in @OrderBy
Qualified properties in OrderBy are needed sometimes.
I want to write something as this:
@OneToMany (mappedBy="invoice", cascade=CascadeType.REMOVE)
@OrderBy("product.description desc")
private Collection<InvoiceDetail> details;
Where InvoiceDetail has a product reference:
@Entity
public class InvoiceDetail {
@ManyToOne(fetch=FetchType.LAZY, optional=false)
private Product product;
...
}
In fact, OpenXava adds this support with its own XOrderBy annotation just for supporting qualified properties.
Conclusion
What do you think about these suggestion ?
If you like some of them please send your comment to JSR: jsr-317-comments@jcp.org
References
- Login or register to post comments
- 5638 reads
- Printer-friendly version
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)










Comments
Fabrizio Giudici replied on Wed, 2008/06/11 - 6:58am
+1 especially for the UUID stuff - but I'd say, at this point, that I'd like to see even a more flexible way, where you candefine a "named key generation strategy". You place the name of the strategy in the annotation, and you bind it to an implementation class in a configuration file.
I'd also like to see the capability of merging multiple persistence.xml files referring to the same PU together, as in modular applications this seems to be a reasonable requirement (I've recently tweaked some code for implementing this feature, but I'd really like to see it out-of-the-box).
Marcel Overdijk replied on Wed, 2008/06/11 - 7:27am
Jose replied on Wed, 2008/06/11 - 7:29am
* Delete orphan
* EntityManager injection in domain entities
Peter Kamm replied on Wed, 2008/06/11 - 3:08pm
Fully agree with:
- Delete orphan
- EntityManager injection in domain entities (very important for Domain Driven Design)
Additionally I wish:one can return them without flushing.
Imran M Yousuf replied on Wed, 2008/06/11 - 11:56pm
in response to: marceloverdijk
I fully agree with criteria api point. It has enabled us to build a generic DAO to handle almost 90% of the DAO usages without having to write HQL/SQL. This is one reason why I have not yet moved to JPA.
Thanks to Geertjan for a nice wishlist, lets hope JPA 2.0 spec team considers them seriously.
Geertjan Wielenga replied on Thu, 2008/06/12 - 12:01am
Imran M Yousuf replied on Thu, 2008/06/12 - 12:19am
in response to: geertjan
Sorry Javier, please accept my apology and thanks for a wonderful article.
Geertjan sorry to you too ; and thanks for posting it to DZone.
Peter Thomas replied on Thu, 2008/06/12 - 3:52am
Now wait a minute. I was under the impression that Criteria query support would be present in JPA 2.0 - that was what I kept hearing.
Looking at the comments above, it looks like there won't be a Criteria API? I don't think I can move from Hibernate then :(
I remember Spring-DAO was promising an abstraction over this, does anyone have any experience with this?
Imran M Yousuf replied on Thu, 2008/06/12 - 4:22am
I quoted the above from Page 15 of JPA 2.0 EDS. It seems we all have been under the correct impression :).
Peter Thomas replied on Thu, 2008/06/12 - 4:56am
Thanks Imran! I'm curious to know how far the "plan" has progressed to becoming reality :) I just did some searching and I found a couple of articles and blog posts mentioning Criteria support planned for JPA 2.0 - but they sounded a little tentative. The latest reference I could find is this article (Jan 2008):
http://www.sdtimes.com/content/article.aspx?ArticleID=31655
Also it looks like the final version of JPA 2.0 would arrive only by the end of 2008. Guess I have to stick to Hibernate for a little while longer...
Imran M Yousuf replied on Thu, 2008/06/12 - 5:07am
Thanks for the article link, since we will be sticking to Hibernate for now, you can have look at -
http://repo.or.cz/w/smart-dao.git
I use it for my Hibernate projects. You will find some usages in http://code.google.com/p/smart-load-test/.
Jens Schauder replied on Thu, 2008/06/12 - 6:05am
I don't agree on the
@OneToMany implicit, I think if at all it should be a @ManyToMany implicit. OneToMany would puts a restriction on the referenced class, and I don't like the idea of creating such a restriction to a class just by referencing it.
Other then that a very good and interesting list.
Javier Paniza replied on Thu, 2008/06/12 - 9:23am
Hi Jens,
If the entity in the other part of the relationship has a reference to this, then we can assumea @OneToMany, otherwise @ManyToMany.
ge0ffrey replied on Fri, 2008/06/13 - 1:29am
ge0ffrey replied on Fri, 2008/06/13 - 1:40am
in response to: marceloverdijk
[quote=marceloverdijk]I didn't read the JPA 2.0 specification but what really needed is a decent Criteria API like Hibernate has.[/quote]
Yes, Hibernat's Criteria API is good and very usefull, but standarizing it through JPA 2.0 couldn't hurt it, I am thinking:
Javier Paniza replied on Fri, 2008/06/13 - 2:31am
in response to: ge0ffrey
Hi geOffrey,
just send your opinion about these suggestions to jsr-317-comments@jcp.org.
Khanh replied on Fri, 2008/08/01 - 1:23am
Hi Javier Paniza! I'm Khanh Hoang, i come from Vietnam.
i'm rearching about Openxava3 for my company. I met some problems when learn it!
My machine is intalled JDK6 and JRE6, IDE: Eclipse3.2
That are:
When i want to create a new project. I have to delete this " defaultValue="${project}DS " if not, it talks that don't know Data sourse and can't create new openxava project.
<input addproperty="project" message="What is your project name?"/>
<!--defaultValue="${project}DS"-->
<input addproperty="datasource" message="What is the datasource?" />
Can't deploy OpenxavaTest project. When i run ant build.xml in OpenxavaTest. It reports all classes in org.openxava.test.model.xejb Package are error
[javac] ^[javac] C:\openxava-3.0.2\workspace\OpenXavaTest\gen-src-xava\org\openxava\test\model\xejb\CommentBean.java:165: cannot find symbol[
javac] symbol : class CommentKey[javac] location: package org.openxava.test.model[
javac] public org.openxava.test.model.CommentKey ejbCreate(org.openxava.test.model.IssueKey containerKey, int counter, org.openxava.test.model.CommentValue value)[javac] ^[
javac] C:\openxava-3.0.2\workspace\OpenXavaTest\gen-src-xava\org\openxava\test\model\xejb\CommentBean.java:178: cannot find symbol[javac] symbol : class IssueKey[
javac] location: package org.openxava.test.model[javac] public void ejbPostCreate(org.openxava.test.model.IssueKey containerKey, int counter, org.openxava.test.model.CommentValue value)
[javac] ^[javac] 100 errors
Please help me config that issues.
mailto: kdhoang@fcg.com
Thank you very much.!
Javier Paniza replied on Fri, 2008/08/01 - 3:39am
Hi Khanh,
put your question about OpenXava in this forum:
http://sourceforge.net/forum/forum.php?forum_id=419690
and I'll help you.
Cheers
Javier
JOleg replied on Fri, 2008/08/15 - 12:41pm
Have not read JPA 2.0 specification either, and in fact my team is at the process of moving our project from plain hibernate to JPA persistence. This is my first project where I deal with JPA, I'm enjoying it so far, but still, we have stumbled upon one feature JPA 1.0 does not provide.
* What we really lack is the automatic flush feature before any JDBC operation. Don't confuse my wish with the available auto flush mode which basically implicitly does flush'es before select's. This is not what I am after. I really want to have an option to tell to the persistence context to trigger em.flush() before and after every JDBC operation. For example, we call em.persist(entity), and persistence context does flush after that (implicitly).
* Secondly. I'm not 100% sure this is impossible unlke with the flush() wish, but I would like to automatically refresh() entities whenever a @OneToMany collecton is being called. Suppose we have a Parent table and a Child table. Parent table has something like:
Collection<Child> getChilds() {}
if I add something to the Child table during the transaction, then getChilds() will return everything but the entity I have added during the transaction. To overcome this issue, I need to explicitly call em.refresh(parent)and only after that call parent.getChilds();
Need something like:
Class Parent {
...
@OneToMany(mappedBy = "parent", refreshOnAccess = true)
Collection<Child> getChilds () {}
}
or, as an alternative, a more flexible control over 2nd level cache.
* Session beans to be annotable by @Local and @Remote annotations together. I know some JBoss versions had a bug which allowed this, but this is not part of spec, and this has been fixed in later JBoss versions.
I'm sure I can think of something else to this list, but otherwise, very good articl.
---
I did not know I could not inject EntityManager into Entities... not even sure if it's a good idea to inject EntityManager into DOs :-]
jshowalter replied on Sun, 2008/08/17 - 7:51pm
The first persistence unit has the entity with the lifecycle callbacks.
The second persistence unit does queries to get info used to do validation.
The lifecycle callbacks call utility methods that first try to get validation info from TreeCache. If that fails, they fall back to querying using the second persistence unit.
So far this has been working.
jshowalter replied on Sun, 2008/08/17 - 7:55pm
I would like to add another to your wishlist.
We have an interface. Let's call it Foo. When entities that implement Foo are saved, we want to validate in lifecycle callbacks. It's easy enough to add the @EntityListeners annotation to every class of Entity that implements Foo, but it's possible to forget to do so.
It would be a lot simpler to be able to put the @EntityListeners annotation on the Foo interface and be done with it. We tried that where I work, but the annotation is simply ignored.
It seems like this is a natural and intuitive thing to want to be able to do, and would make a fine addition to JPA's capabilities.
jornaljava replied on Mon, 2008/11/24 - 11:27pm
http://www.jornaljava.com/2008/11/video-tutorial-utilizando-jpa-com.html
jornaljava replied on Mon, 2008/11/24 - 11:28pm
http://www.jornaljava.com/2008/11/video-tutorial-utilizando-jpa-com.html
rfogarty replied on Mon, 2009/03/30 - 10:01am
Hi Javier,
I didn't see any comments on your #3 Converters. I am thinking the same thing I think which is something equivalent to JAXBs @XmlJavaTypeAdapter or a type adapter. For instance, since JPA doesn't seem to know about UUIDs implicitly it serializes it out to a byte[] whereas I would like them stored as VARCHAR. I find the JAXB equivalent extremely useful.
Have you had any feedback (positive or nagative) from the JSR committee about that one? Seems like it would be cake to implement.
Regards,
Ryan