JPA links: http://docs.oracle.com/javaee/6/api/javax/persistence/package-summary.html http://docs.oracle.com/javaee/6/api/javax/persistence/PersistenceContext.html http://docs.oracle.com/javaee/6/api/javax/persistence/MapKeyJoinColumn.html http://docs.oracle.com/javaee/6/api/javax/persistence/MapKeyEnumerated.html http://en.wikibooks.org/wiki/Java_Persistence/Relationships http://jpa-quiz.rhcloud.com/JPA.Collection.Mapping.jsp -------------------------------------------- JPA Architecture PersistenceContextType: PersistenceContextType.TRANSACTION: - "shared EntityManager" proxy. - [POJOs fetched via queries outside transactions are detached when returned, posterior POJO lazy loaded field call would throw an exception] - [Spring’s transactionManager create the EntityManager/Session for each request, then it starts, processes, and commits a transaction, and finally closes the EntityManager/Session.] PersistenceContextType.EXTENDED: - client (not spring) in charge of EntityManager/Session managment, spring simply creates/closes it on startup/shutdown. - usefull in/do it for limited scenarios: long-running session / session-per-conversation: Wizards with multiple delayed requests in the same session (saves/avoid some detaching and merging process), and close the session at the end of process. - not thread-safe and hence must not be used in a concurrently accessed AntiPattern: - session-per-application * Each DAO gets a different instance of the EntityManager so you can’t do any meaningful work that involves two DAOs. If you insert a records with one EntityManager and try to use it in another one – it won’t work. The first hasn’t been flushed, and the second does not have the 1st level cache. * If a session does not get closed it accumulates entities (it stores them in memory so that it doesn’t have to fetch them multiple times from the DB). Which is a pure memory leak. * It is not thread-safe. The Session and EntityManager objects are not thread-safe. - each DAO got its own [entity manager and underlying session] (-> Hibernate Session wrapping with an EntityManager interface implementation) instance. - Messing around with detached objects (SaveOrUpdate or Merge plus some messy code) instead of using DTO's (bof, ça dépend des cas...) -------------------------------------------- JPA MetaModel & TypeSafe queries http://www.ibm.com/developerworks/java/library/j-typesafejpa/ A query for persistent Java™ objects is typesafe if a compiler can verify it for syntactic correctness. Version 2.0 of the Java Persistence API (JPA) introduces the Criteria API, which brings the power of typesafe queries to Java applications for the first time and provides a mechanism for constructing queries dynamically at run time. This article describes how to write dynamic, typesafe queries using the Criteria API and the closely associated Metamodel API. 1) use the Criteria API to develop queries that a Java compiler can check for correctness to reduce run-time errors, in contrast to string-based Java Persistence Query Language (JPQL) queries. Added power of programmatic query-construction mechanics compared to JPQL queries that use a predefined grammar. JPQL — being a string-based query language with a definite grammar — has a few limitations. Effectively, the JPQL code compile happily, but can fail at run time because of JPQL query string syntactically incorrect. Unfortunately, the Java compiler has no way to detect such an error. (depending on whether the JPA provider parses a JPQL string according to JPQL grammar during query construction or execution). != CriteriaBuilder has API methods for constructing all kinds of query expressions that are supported in traditional JPQL grammar, plus a few more A CriteriaQuery is generically typed (Generics) --- CriteriaBuilder qb = em.getCriteriaBuilder(); CriteriaQuery c = qb.createQuery(Person.class); Root p = c.from(Person.class); Predicate condition = qb.gt(p.get(Person_.age), 20); c.where(condition); TypedQuery q = em.createQuery(c); List result = q.getResultList(); --- CriteriaQuery is a tree of query-expression nodes that are used to specify query clauses such as FROM, WHERE, and ORDER BY in a traditional string-based query language CriteriaQuery encapsulates the clauses of a traditional query The query expressions are generically typed. A few typical expressions are: - Root, which is equivalent to a FROM clause. - Predicate, which evaluates to a Boolean value of true or false. (In fact, it is declared as interface Predicate extends Expression.) - Path, which denotes a persistent attribute navigated from a Root expression. Root is a special Path with no parent. CriteriaBuilder is the factory for CriteriaQuery and query expressions of all sorts. Root is generically typed the Java language can be judiciously used to define an API that allows you to express what is correct and prohibits what is not p.get(Person_.age) is a path expression. A path expression is the result of navigation from a root expression via one or more persistent attribute(s) TypedQuery q = em.createQuery(c); CriteriaQuery carries richer type information, the result is a TypedQuery that is an extension of the familiar javax.persistence.Query. The TypedQuery, as the name suggests, knows the type it returns as a result of its execution CriteriaQuery is transferred to an executable query with its type information preserved so that the elements of the selected list can be accessed without any run-time casting. 2) Person_.age is a public static field in the Person_ class, and Person_ is the static, instantiated, canonical metamodel class corresponding to the original Person entity class A metamodel class describes the meta information of a persistent class. A metamodel class is canonical if the class describes the meta information of a persistent entity in the exact manner stipulated by the JPA 2.0 specification. A canonical metamodel class is static in the sense all its member variables are declared static (and public). You instantiate the canonical class by generating a concrete Person_.java at a source-code level at development time. Through such instantiation, it is possible to refer to persistent attributes of Person at compile time, rather than at run time, in a strongly typed manner. -> fournit le mm niveau déclaratif d'information que la Class You can use reflection to obtain the meta information about an instance of a java.lang.Class, but meta information about Person.class cannot be referred to in a way that a compiler can verify. -> sauf que c'est utilisé par le Compiler, ? pourquoi le Compiler n'utilise pas la Class pour vérifier ces infos (identiques) ? Reflection will not work for what JPA 2.0's typesafe query API wants to accomplish. A typesafe query API must enable your code to refer to the persistent attribute named age in a Person class in a way that a compiler can verify at compile time. The solution that JPA 2.0 provides is the ability to instantiate a metamodel class named Person_ that corresponds to Person by exposing the same persistent attributes statically. I can refer to the persistent attribute of domain.Person named age — not via the Reflection API, but as a direct reference to the static Person_.age field — at compile time. The compiler can then enforce type checking based on the declared type of the attribute named age. I've already cited an example of such a restriction: CriteriaBuilder.gt(p.get(Person_.age), "xyz") will cause a compiler error because the compiler can determine from the signature of CriteriaBuilder.gt(..) and type of Person_.age that a Person's age is a numeric field and cannot be compared against a String. -> utilisation plus structurée, et compilation compliant, plutôt que de passer par une String donnant le nom de la propriété. SingularAttribute is one of the interfaces defined in the JPA Metamodel API The metamodel class is annotated as @StaticMetamodel(domain.Person.class) to designate it as a metamodel class corresponding to the original persistent domain.Person entity. metamodel class as a description of a persistent entity class. Just as the Reflection API requires other interfaces — such as java.lang.reflect.Field or java.lang.reflect.Method — to describe the constituents of java.lang.Class, so the JPA Metamodel API requires other interfaces, such as SingularAttribute, PluralAttribute, to describe a metamodel class's types and their attributes. The interfaces of JPA's Metamodel API are more specialized than those of the Java Reflection API. This finer distinction is required to express rich meta information about persistence. For example, the Java Reflection API represents all Java types as java.lang.Class. That is, no special distinction is made via separate definitions among concepts such as class, abstract class, and an interface. Of course, you can ask a Class whether it is an interface or if it is abstract — but that is not the same as representing the concept of interface differently from an abstract class via two separate definitions. JPA Metamodel API harnesses that power to introduce strong typing for persistent entities. Before JPA 2.0, this semantic distinction was represented via corresponding class-level annotations in the persistent-class definition. JPA Metamodel describes three separate interfaces — MappedSuperclassType, EntityType, and EmbeddableType — in the javax.persistence.metamodel package to bring their semantic specialties into sharper focus. Similarly, the persistent attributes are distinguished at type-definition level via interfaces such as SingularAttribute, CollectionAttribute, and MapAttribute. Run-time scope java.lang.Class instances are scoped by java.lang.ClassLoader at run time. A set of Java class instances that reference one another must all be defined under the scope of a ClassLoader (else: ClassNotFoundException or NoClassDef FoundError) This notion of run-time scope as a strict set of mutually referable classes is captured in JPA 1.0 as a persistence unit. In JPA 2.0, the scope is made available to the developer at run time via the javax.persistence.metamodel.Metamodel interface. The Metamodel interface is the holder of all persistent entities known to a specific persistence unit EntityManagerFactory emf = ...; Metamodel metamodel = emf.getMetamodel(); EntityType pClass = metamodel.entity(Person.class); ClassLoader classloader = Thread.currentThread().getContextClassLoader(); Class clazz = classloader.loadClass("domain.Person"); Essentially, the persistent attribute that the application can refer to at run time via the Metamodel API is made available to a Java compiler by instantiation of the static canonical metamodel Person_ class. the Metamodel API also allows access to all the known metamodel classes (Metamodel.getManagedTypes()) or access to a metamodel class by its persistence-specific information In JPA, the meta information about a POJO is further attributed with persistent specific meta information — such as whether a class is embedded or which fields are used as primary key — with source-code level annotations (or XML descriptors). The persistent meta information falls into two broad categories: for persistence (such as @Entity) and for mapping (such as @Table). In JPA 2.0, the metamodel captures the metadata only for persistence annotations — not for the mapping annotation. Hence, with the current version of the Metamodel API, it's possible to know which fields are persistent, but it's not possible to find out which database columns they are mapped to. Canonical vs. non-canonical You may have noticed that the public static fields are only declared in canonical metamodel but not initialized. The declaration makes it possible to refer to these fields during development of a CriteriaQuery. But they must be assigned a value to be useful at run time. While it is the responsibility of the JPA provider to assign values to these fields for canonical metamodel, similar warranty is not extended for non-canonical metamodel. 3) JPQL To contrast the usage of parameters to that of JPQL: the parameter expression is created with explicit type information to be an Integer and is directly used to bind a value of 20 to the executable query. The extra type information is often useful for reducing run-time errors, because it prohibits the parameter from being compared against an expression of an incompatible type or being bound with a value of an inadmissible type. Neither form of compile-time safety is warranted for the parameters of a JPQL query. Integral position in a (linear) JPQL query string makes some intuitive sense, but the notion of an integral position cannot be carried forward in the context of CriteriaQuery, where the conceptual model is a tree of query expressions. ------------------- addtional links: http://docs.jboss.org/hibernate/stable/jpamodelgen/reference/en-US/html_single/ génération des meta infos avec hibernate MetaModel generation tool (via eclipse annotation processor) --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Library for object mapping/copy automation: entities to DO/DTO http://dozer.sourceforge.net/ http://dozer.sourceforge.net/documentation/annotations.html# (mapping @nnotation based approach -> better than xml or implemented approach) http://beanlib.sourceforge.net/ http://beanlib.svn.sourceforge.net/viewvc/beanlib/trunk/beanlib-doc/hibernate-bean-replicator.html (hibernate automation) http://beanlib.svn.sourceforge.net/viewvc/beanlib/trunk/beanlib-doc/hibernate3-dto-copier.html (hibernate objets copying strategies) http://beanlib.svn.sourceforge.net/viewvc/beanlib/trunk/beanlib-doc/faq.html