JPA 2.1 早期草案解释
fmms 13年前
<p><a href="/misc/goto?guid=4958326486061157375">Java Persistence API 2.1 Early Draft</a> 已经发布了一个月左右,JPA2 是 Java EE 7 的首个 JSR。<br /> <br /> 下面是 JPA 2.1 主要的新特性:</p> <ul> <li><span style="font-weight:bold;">支持存储过程</span>: Java 持久化查询语言支持预定义的数据库函数和用户自定义函数<br /> <br /> There are different variants of <code>EntityManager.createXXXStoredProcedureQuery</code> methods that return a <code>StoredProcedureQuery</code> for executing a stored procedure. Just liked <code>@NamedQuery</code>, there is <code>@NamedStoredProcedureQuery</code> that specifies and names a stored procedure, its parameters, and its result type. This annotation can be specified on an entity or mapped superclass. The name specified in the annotation is then used in <code>EntityManager.createNamedStoredProcedureQuery</code>. The IN, OUT, and INOUT parameters can be set and used to retrieve values passed back from the procedure. For example:<br /> <br /> <code>@Entity<br /> @NamedStoredProcedureQuery(name="topGiftsStoredProcedure", procedureName="Top10Gifts")<br /> public class Product {<br /> . . .<br /> }</code><br /> <br /> // In your client<br /> <br /> <code>StoredProcedreQuery query = EntityManager.createNamedStoredProcedureQuery("topGiftsStoredProcedure");<br /> query.registerStoredProcedureParameter(1, String.class, ParameterMode.INOUT);<br /> query.setParameter(1, "top10");<br /> query.registerStoredProcedureParameter(2, Integer.class, ParameterMode.IN);<br /> query.setParameter(2, 100);<br /> // there are other setParameter methods for defining the temporal type of a parameter<br /> . . .<br /> query.execute();<br /> String response = query.getOutputParameterValue(1);</code><br /> <br /> The section 3.8.6 provide more details. </li> <li><span style="font-weight:bold;">可通过 Criteria 批量的更新和删除数据</span>: Added <code>CriteriaUpdate</code>, <code>CriteriaDelete</code>, <code>CommonAbstractQuery</code> interfaces, refactored <code>AbstractQuery</code> interface.<br /> <p>Here is a sample for <code>CriteriaUpdate</code> from section 6.5.15:</p> <p><code>CriteriaUpdate<Customer> q = cb.createCriteriaUpdate(Customer.class); <br /> Root<Customer> c = q.from(Customer.class); <br /> q.set(c.get(Customer_.status), "outstanding")<br /> .where(cb.lt(c.get(Customer_.balance), 10000));</code></p> <p>with the equivalent JPQL of:</p> <p><code>UPDATE Customer c<br /> SET c.status = 'outstanding'<br /> WHERE c.balance < 10000</code></p> <p>This query can then be executed as:</p> <p><code>@PersistenceContext EntityManager em;<br /> Query query = em.createQuery(q);<br /> query.executeUpdate();</code></p> <p>Here is a sample for <code>CriteriaDelete</code> from section 6.5.15:</p> <p><code>CriteriaDelete<Customer> q = cb.createCriteriaDelete(Customer.class); <br /> Root<Customer> c = q.from(Customer.class); <br /> q.where(cb.equal(c.get(Customer_.status), "inactive"),<br /> cb.isEmpty(c.get(Customer_.orders)));</code></p> <p>with the equivalent JPQL of:</p> <code>DELETE FROM Customer c<br /> WHERE c.status = 'inactive'<br /> AND c.orders IS EMPTY</code><br /> <br /> This query can then be executed in similar way as earlier:<br /> <p><code>@PersistenceContext EntityManager em;<br /> Query query = em.createQuery(q);<br /> query.executeUpdate();</code></p> </li> <li><span style="font-weight:bold;">新的保留关键字</span>: 包括:<code>FUNCTION</code>, <code>ON</code>, <code>TREAT</code>. <ul> <li><span style="font-weight:bold;">Pre-defined and user-defined functions using FUNCTION</span>: JPQL provide several in-built functions which may be used in the SELECT, WHERE or HAVING clause of a query such as CONCAT, SUBSTRING, TRIM, LENGTH, ABS, SQRT, and CURRENT_DATE. The section 4.6.17.3 define invocation of predefined and user-defined database functions using the FUNCTION operator. The <code>FUNCTION</code> is used to invoke predefined database functions or user-defined database functions. An example from the section is:<br /> <br /> <code>SELECT c<br /> FROM Customer c<br /> WHERE FUNCTION(‘hasGoodCredit’, c.balance, c.creditLimit)</code></li> <li><span style="font-weight:bold;">Downcasting using TREAT</span>: <code>TREAT</code> is supported for downcasting within path expressions in the FROM and WHERE clauses. Use of the TREAT operator allows access to subclass-specific state. An example from section 4.4.9 is:<br /> <code><br /> SELECT b.name, b.ISBN<br /> FROM Order o JOIN TREAT(o.product AS Book) b</code><br /> <br /> In this example, the join is performed between <code>Order</code> and <code>Product</code> but <code>name</code> and <code>ISBN</code> are attributes of the <code>Book</code> class which is a subclass of the <code>Product</code> class. Another example is:<br /> <br /> <code>SELECT e FROM Employee e<br /> WHERE TREAT(e AS Exempt).vacationDays > 10<br /> OR TREAT(e AS Contractor).hours > 100</code><br /> <br /> Here again <code>vacationDays</code> are attributes for <code>Exempt</code> employees only and <code>hours</code> only for <code>Contractor</code>.<br /> <br /> </li> <li><span style="font-weight:bold;">Join condition using ON</span>: The ON clause in SQL is used to specify the relationship between the tables. It is different from the WHERE clause which specifies the criteria for the rows to be picked. An example from the section 4.4.5.2 shows the JPQL as:<br /> <br /> <code>SELECT s.name, COUNT(p)<br /> FROM Suppliers s LEFT JOIN s.products p<br /> ON p.status = 'inStock'<br /> GROUP BY s.name</code><br /> <br /> The mapped SQL for this will be:<br /> <br /> <code>SELECT s.name, COUNT(p.id)<br /> FROM Suppliers s LEFT JOIN Products p<br /> ON s.id = p.supplierId AND p.status = 'inStock'<br /> GROUP BY s.name</code><br /> <br /> The <code>s.id = p.supplierId</code> condition is generated becase of the LEFT JOIN. The additional JOIN condition of <code>p.status = 'inStock'</code> is also added to the generated SQL because of the ON clause in the JPQL. The result of this query will include all suppliers (with possibly NULL values). This is different from the query below:<br /> <code><br /> SELECT s.name, COUNT(p)<br /> FROM Suppliers s LEFT JOIN s.products p<br /> WHERE p.status = 'inStock'<br /> GROUP BY s.name</code><br /> <br /> The result of this query will not include suppliers that have no products in stock.<br /> <br /> Additional methods are also added to <code>Fetch</code>, <code>Join</code>, <code>CollectionJoin</code>, <code>SetJoin</code>, <code>ListJoin</code>, and <code>MapJoin</code> interfaces to support the ON clause.</li> </ul> </li> <li><span style="font-weight:bold;">透过 CDI 实现实体类的侦听器</span>: Entity Listeners allow to handle cross-cutting lifecycle events in a non-persistent listener class. In JPA 2.1, entity listeners will support dependency injection through CDI. The usual lifecycle callback methods of <code>@PrePersist</code>, <code>@PostPersist</code>, <code>@PreUpdate</code>, and <code>@PreRemove</code> can be used for entities. The entity listeners can also be annotated with <code>@PostConstruct</code> and <code>@PreDestroy</code> for their own lifecycle. The section 3.5.1 provides more details on this.<br /> <br /> Read more details on <a href="/misc/goto?guid=4958326486869738970">jsr338-experts alias archive</a> and <a href="/misc/goto?guid=4958326487670008212">users@jpa-spec</a>.</li> <li><span style="font-weight:bold;">持久化上下文的同步</span>: In JPA 2, the persistence context is synchronized with the underlying resource manager. Any updates made to the persistence context are propagated to the resource manager. JPA 2.1 introduces the concept of unsynchronized persistence contenxt. Here is how you can create a container-managed unsynchronized persistence context:<br /> <br /> <code>@PersistenceContext(synchronization=SynchronizationType.UNSYNCHRONIZED) EntityManager em;</code><br /> <br /> The section 7.6.1 provide more details.</li> <li>Several clarifications in text and javadocs<br /> <br /> </li> </ul> <p>更多相关介绍链接:</p> <ul> <li><a href="/misc/goto?guid=4958326486061157375">JPA 2.1 Specification</a></li> <li><a href="/misc/goto?guid=4958326489202767409">Javadocs</a></li> <li><a href="/misc/goto?guid=4958326489996508253">Implementation in EclipseLink</a></li> </ul> <p>JPA 2.1 将包含在 GlassFish 4.0 中。</p>