37 * NOTE: As the entity manager is injected by the container, it is 38 * often a proxy. Hence the return value is the class name of the 39 * delegate of the actual injected instance 40 */ 41 public String getProvider() { 42 return em.getDelegate().getClass().getName(); 43 } 44 45 public Message log(String message) { 46 Message result = new Message(message); 47 em.persist(result); 48 return result; 49 } 50 51 }
這個會話bean本身也有不明確的地方。它使用了JPA,但沒有聲明將要使用哪一個特定的持久性提供者(事實上,定義一個工業(yè)標準的持久性API的主要目的之一是為了能夠從一個提供者切換到另一個)。
這個bean并未直接與一個 JPA提供者建立連接,而是依靠容器新獲得的功能(即,從JEE 5以來)在需要時注入JPA連接。另外,有個好消息是Weblogic Server 10.0是第一個兼容JEE 5的應(yīng)用服務(wù)器。
容器能夠以兩種形式向會話Bean注入JPA依賴關(guān)系:@PersistenceUnit或@PersistenceContext注釋。我們所使用的是@PersistenceContext(JPAServiceBean.java的第 30和31行)。
如果讓我將它與JDBC進行粗略的類比,那么@PersistenceUnit相當于一個DataSource,而@PersistenceContext則相當于一個Connection。在JPA術(shù)語當中,這一對概念是由JPA定義的接口EntityManagerFactory和EntityManager分別實現(xiàn)的。
通過這些接口和少數(shù)其他的方式(例如,Query),JPA已經(jīng)定義了一個比傳統(tǒng)的JDBC通過SQL提供的方式更高層的面向?qū)ο蟪橄笈c數(shù)據(jù)庫進行交互。通過JPA,您可以借助面向?qū)ο笠晥D與底層數(shù)據(jù)庫進行交互。應(yīng)用程序可以通過 EntityManager接口中的方法創(chuàng)建、更新、查詢和刪除對象——JPA提供者與應(yīng)用程序協(xié)同工作截聽這些對象級的改變并且適當?shù)貙⑺鼈兣c相應(yīng)的INSERT、UPDATE、SELECT和DELETE數(shù)據(jù)庫操作映射起來。
這個基本的JPA應(yīng)用程序已經(jīng)完成,下面是持久性類。
Message.java
01 package service;
02
03 import java.io.Serializable;
04 import java.util.Date;
05
06 import javax.persistence.*;
07
08 /**
09 * A simple persistent message. The entity is declared to be serializable to
10 * pass across processes.
11 *
12 * The message is assigned an identifier by the persistence provider.
13 * A timestamp is also set to the message when it is constructed.
14 *
15 * Annotates the fields with their persistent properties.
16 *
17 * @author ppoddar
18 *
19 */
20 @SuppressWarnings("serial")
21 @Entity
22 public class Message implements Serializable {
23 /**
24 * Annotates the field as primary identity for this instance. Also the
25 * persistence provider will generate the identity value. That is why
26 * there is no corresponding setter method.
27 */
28 @Id
29 @GeneratedValue
30 private long id;
31
32 /**
33 * Annotates the field to carry a TIMESTAMP value in the database column.
34 * The column name is different than the default value of
timestamp
35 * because many databases will reserve that word.
36 *
37 * The field is immutable by application (no setter method) and set on
38 * construction with current time.
39 */
40 @Temporal(TemporalType.TIMESTAMP)
41 @Column(name="createdOn")
42 private Date timestamp;
43
44 /**
45 * Does not annotate but the field will be persisted nevertheless by
46 * convention of String and primitive types being persistent by default.
47 */
48 private String body;
49
50 protected Message() {
51 this("");
52 }
53
54 public Message(String body) {
55 timestamp = new Date();
56 this.body = (body == null) ? "" : body;
57 }
58
59 public long getId() {
60 return id;
61 }
62
63 public String getBody() {
64 return body;
65 }
66
67 public Date getTimestamp() {
68 return timestamp;
69 }
70 }