Javier has posted 49 posts at DZone. View Full User Profile

My JPA 2.0 Wish List

06.11.2008
| 11834 views |
  • submit to reddit

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:

  1. Restriction in callback methods.
  2. @ManyToOne, @OneToMany and @ElementCollection implicits.
  3. Converters.
  4. Method in EntityManagerFactory for obtaining the list of all entities.
  5. Composite keys without key class.
  6. UUID as GeneratedType for @GeneratedValue.
  7. Default fetch value for @ManyToOne.
  8. @ElementCollection.
  9. 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:

  1. Easy migration from non-JPA code to JPA.
  2. 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:

@Entity

public class Invoice {

@Id

private int year;



@Id

private int number;

...

}
No more. No @IdClass. No @EmbeddedId.

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();
key.put("year", 2008);
key.put("number", 3);
Invoice invoice = manager.find(Invoice.class, key);
2. Array
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:

@Embedded
protected Set<String> nickNames = new HashSet();
Curiously, OpenXava has a @AsEmbedded annotation that can be applied to references and collections.

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

  • JSR-317: Java Persistence API:
  • OpenXava: Model-driven framework based on JPA.
Published at DZone with permission of its author, Javier Paniza.

(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

I didn't read the JPA 2.0 specification but what really needed is a decent Criteria API like Hibernate has.

Jose Noheda 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:
  • @Id and @Version Fields should be set rigth after entities are managed, so
    one can return them without flushing.
  • Decent QueryByExample (including "like" for Strings)

Imran M Yousuf replied on Wed, 2008/06/11 - 11:56pm in response to: Marcel Overdijk

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

Not me... but Javier! :-)

Imran M Yousuf replied on Thu, 2008/06/12 - 12:19am in response to: Geertjan Wielenga

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

"We plan to address extensions to the Java Persistence query language and an API for criteria queries in the next draft of this specification."

  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

Linda DeMichiel, senior staff engineer at Sun and specification lead on JSR 317, said that the new version of JPA would be based on lessons learned in other persistence systems. Specifically, she's hoping to bring criteria-based dynamic query generation into the API.

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,

@OneToMany implicit, I think if at all it should be a @ManyToMany implicit

If the entity in the other part of the relationship has a reference to this, then we can assumea @OneToMany, otherwise @ManyToMany. 

Geoffrey De Smet replied on Fri, 2008/06/13 - 1:29am

  1. Restriction in callback methods. +1
  2. @ManyToOne, @OneToMany and @ElementCollection implicits. -0
  3. Converters. -0
  4. Method in EntityManagerFactory for obtaining the list of all entities. -0
  5. Composite keys without key class. +1
    1. I like the varargs and object array approach
    2. Composite keys are definitly a pain at the moment, that pain forced us to remove them all together from our domain model (which is probably a good thing, but JPA shouldn't force us)
  6. UUID as GeneratedType for @GeneratedValue. +1 (minor)
  7. Default fetch value for @ManyToOne. +1 (major)
    1. Couldn't agree more
  8. @ElementCollection. -1
  9. Qualified properties in @OrderBy. +1
    1. If and only if the orderBy uses HQL (and not an SQL fragment like in Hibernate)
      1. Like shown in your example you should be able to do implicit joins

Geoffrey De Smet replied on Fri, 2008/06/13 - 1:40am in response to: Marcel Overdijk

[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:

  •  Javadocs on the API
  • Less methods or better method names for: criteria.createAlias(), criteria.createCriteria(), ...
  • A better definition of which methods/arguments trigger fetching (and not just implicit joining)

Javier Paniza replied on Fri, 2008/06/13 - 2:31am in response to: Geoffrey De Smet

Hi geOffrey,

just send your opinion about these suggestions to jsr-317-comments@jcp.org.

Khanh Hoang 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

Oleg Asakhov 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 :-]

Jim Showalter replied on Sun, 2008/08/17 - 7:51pm

Regarding the restriction in lifecycle callbacks, we were able to get this working by creating two persistence units.

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.

Jim Showalter 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.com ... replied on Mon, 2008/11/24 - 11:27pm

A algum tempo descobri um video tutorial totalmente em português sobre JPA produzido pelo Fabio Kung da Caelum, onde mostra passo a passo como utilizar essa biblioteca que é uma mão na roda de quem quer fazer mapeamento de objetos com banco de dados. Nesse tutorial é explicado desde os downloads dos jar necessários, configuração do banco de dados (mysql), utilização do jpa dentro do eclipse, geração das tabelas, etc, etc... dentre todos os videos tutoriais que já vi sobre java em geral, esse foi um dos melhores de todos. Muito bem explicado e detalhado. Para quem não conhece, JPA é a biblioteca usada de base para se construir os EJB Entity Beans, que fazem o papel de manter a integridade entre os objetos de entidade e o banco de dados. Mais uma vez, excelente tutorial! Parabéns Fábio!


http://www.jornaljava.com/2008/11/video-tutorial-utilizando-jpa-com.html

jornaljava.com ... replied on Mon, 2008/11/24 - 11:28pm

A algum tempo descobri um video tutorial totalmente em português sobre JPA produzido pelo Fabio Kung da Caelum, onde mostra passo a passo como utilizar essa biblioteca que é uma mão na roda de quem quer fazer mapeamento de objetos com banco de dados. Nesse tutorial é explicado desde os downloads dos jar necessários, configuração do banco de dados (mysql), utilização do jpa dentro do eclipse, geração das tabelas, etc, etc... dentre todos os videos tutoriais que já vi sobre java em geral, esse foi um dos melhores de todos. Muito bem explicado e detalhado. Para quem não conhece, JPA é a biblioteca usada de base para se construir os EJB Entity Beans, que fazem o papel de manter a integridade entre os objetos de entidade e o banco de dados. Mais uma vez, excelente tutorial! Parabéns Fábio!


http://www.jornaljava.com/2008/11/video-tutorial-utilizando-jpa-com.html

Ryan Fogarty 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

 

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.