JPA2 Metamodel – how to manage that.
Comments: 2JPA2 added new typesafe Criteria API. This allows us to build query in strongly-typed manner instead of string based. To provide such functionality JPA2 use Metamodel API described in JSR-317: Chapter 5.
When entity manager factory is bootstrapping for persistence unit, then persistence provider have to initialize metamodel classes so this classes have to be accessible. For application developers it is important to easy generate them.
We can automatically generate metamodel classes we use Annotation Processing API. The structure of metamodel classes are described in JSR-317: Chapter 6.2.1.1. Briefly for every managed class there will be similar class with name of metamodel class plus “_”, and for every property there will be SingularAttribute for non-collection and
Attribute for Collection|Set|List|Map attribute.
Thanks to that metamodel classes we can write a query, which is type safe and probably more important we can easy do refactorings. That’s in theory, because IDE have to have access to metamodel classes, so the question arise how to manage this classes. I was wonder about three option here:
- Keep generated metamodel as normal code and commit into repository.
- Use external tool to generate metamodel and include results as IDE sources.
- Use IDE support, if exists.
First solution is portable, no IDE configuration, no problems between different IDE’s and so on. The disadvantage of this solution is that we have to remember about generating metamodel classes after we change our code and than commit metamodel into repository. Obviously we break the version control system rule, “don’t commit generated files“.
Second one assumes that you are using some kind of build tool (eg. maven). Then we can setup generation step into that tool (for maven it is maven-processor-plugin) and we setup our IDE to point to that sources. The bad thing about that is that we have to run the tool, otherwise we have not actual metamodel.
Third one is use your IDE for that. Sadly configuration isn’t automatic and every IDE has it’s own way to do this. JPA 2.0 Typesafe Criteria API and Annotation Processing Howto article describes how to do this in IntelliJ IDEA.
Both second and third solution has one additional flaw. You have to specify which annotation generator you want to use. That ties you to JPA provider implementation.
Here you find annotation processor names:
- EclipseLink
- org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProcessor
- Hibernate
- org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor
- OpenJPA
- org.apache.openjpa.persistence.meta.AnnotationProcessor6
We can find processor parameters and switches in javadocs, in EclipseLink case, processor is in internal package, that makes finding parameters and switches a little bit harder, but we can check source code, or use Google.
I try to use third one and second one as fallback for people which use different IDE than IntelliJ, but I’m not happy with that solution.
How do you processĀ JPA2 metamodel classes?
Comments
krzychu
I agree with what has been said. I would like to add that I’m not a fan of new criteria API either. I found mentioned API very complicated/unclear comparing to Hibernate’s one. I try to avoid it whenever it’s possible:)
Anyway, great post Pedro.
Keep up the good work!
Marcin
Thanks Pedro for a great blog entry.
Proposal 1)
Makes sense if IDE will keep metamodel synchronized with JPA classes. If so, the metamodel could be stored in SCM. But as I know, Eclipse doesn’t support automatic metamodel generation and keeping it in sync.
Proposal 2)
It is even worse than you mentioned. For me, code generation must be explicit, but APT does it implicit, code is generated during compilation and than compile generate code in second pass (or the bytecode is created without intermediate sources). Maven comes with m-processor-p to solve this implicit generation/compilation. This plugin adds additional source directory with generated metamodel, which is also confusing (in Maven ecosystem).
Metamodel generation is also time consuming, I prefer to move JPA model (and metamodel generation) to separate project module.
And the last but not least, I can’t stand metamodel criteria API. Sophisticated but really hard to read and understand.
Marcin