<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    城市獵人

    在一網情深的日子里,誰能說得清是苦是甜,只知道確定了就義無反顧
    posts - 1, comments - 7, trackbacks - 0, articles - 89

    EJB3 Persistence API標準化持久性(轉)

    Posted on 2008-07-11 10:26 sailor 閱讀(192) 評論(0)  編輯  收藏 所屬分類: EJB3
            持久性對于大多數企業應用程序都非常關鍵,因為它們需要訪問關系數據庫(例如Oracle Database 10g)。如果您正在使用Java開發應用程序,您可能需要完成一些常規任務(例如數據庫更新和檢索),這是通過編寫JDBC和SQL來完成的。最近幾年,幾種對象關系(O-R)映射框架(例如Oracle TopLink、JBoss Hibernate和BEA Kodo)開始流行,因為它們簡化了持久性問題,將Java開發人員從編寫JDBC代碼的工作中解放出來,從而使他們能夠將精力集中于業務邏輯。一些Java標準(例如EJB 2.x容器管理持久性(CMP)實體bean)也試圖解決持久性挑戰,但是不那么成功。

      雖然存在多種構建應用程序持久層的選擇,但是還沒有一種面向Java平臺的、在Java EE和Java SE環境下均可使用的持久性標準。好消息是EJB3 Java Persistence API (JPA)(它是EJB 3.0規范JSR-220的一部分)的出現,它標準化了面向Java平臺的持久性API。JSR-220為O-R映射供應商(例如TopLink、Hibernate和Kodo)以及其他領先的應用服務器供應商和JDO供應商所廣泛接受。EJB3規范提供了一種極有吸引力的選擇,用于構建企業Java應用程序的持久層。

      在本文中,我將介紹EJB3 Java Persistence API,我將使用一個簡單的域對象模型作為示例。

      域模型

      在構建企業應用程序時,我們首先會設計希望將其保存在數據庫中的域對象模型;然后,與數據庫設計人員合作,確定數據庫模式。域模型表示了持久性對象或實體。實體可以是人、地方或事物,您存儲關于它們的數據。它包含數據和行為。富域模型具有所有面向對象的行為特征,例如繼承性和多態性。

      我們的簡單域模型(圖1)具有Department與Employee實體之間的雙向一對多關系。FullTime和Contractor實體繼承自Employee實體。

    圖1.示例域對象模型
    圖1.示例域對象模型

      O-R框架和EJB3 JPA基礎知識

      如果使用過O-R映射框架(例如Oracle TopLink)構建應用程序持久層,您就會注意到,每種框架都提供三種工具:

      一種聲明式地執行O-R映射的方式。這種方法(稱為O-R映射元數據)允許將對象映射到一個或多個數據庫表。通常,大多數O-R框架使用XML存儲O-R映射元數據。

      一個用于操作實體(例如,執行CRUD操作)的API。此API允許持久化、檢索、更新或移除對象。基于API和O-R映射元數據的使用,O-R框架代表開發人員執行數據庫操作。此API將開發人員從編寫JDBC或SQL代碼以持久化域對象的工作中解放出來。

      一種用于檢索對象的查詢語言。這是持久性最重要的方面,因為非法的SQL語句可能會降低數據庫的速度。此方法也對應用程序屏蔽了混亂地遍布應用程序的的專有SQL。查詢語言允許檢索實體或對象,并將開發人員從編寫SQL SELECT語句的工作中解放出來。

      EJB3 Java Persistence API (JPA)提供一種標準O-R映射機制、一個執行CRUD操作的EntityManager API以及一種擴展EJB-QL以檢索實體的方式,從而標準化了面向Java平臺的持久性的使用。我將在后面討論這三個方面。

      啟用元數據注釋

      Java SE 5.0引入了元數據注釋。Java EE的所有組件(包括EJB3 JPA)大量使用元數據注釋以簡化企業Java開發。要了解關于元數據注釋的更多信息,請參閱Kyle Downey所著的Bridging the Gap: J2SE 5.0 Annotations。在EJB3 JPA中,注釋可以用于定義對象、關系、O-R映射和持久性上下文的注入。JPA還提供使用XML描述符來代替的選擇。我將主要介紹元數據注釋的使用,因為它們大大簡化了開發。不過,您可能更傾向于在生產部署環境中使用XML
            
            標準化JPA中的O-R映射


      定義持久對象:實體

      實體是輕量級的域對象——您希望將其保存在關系數據庫中的Plain Old Java Object (POJO)。像任何POJO一樣,實體可以是抽象或具體類,它能夠擴展另一個POJO。可以使用javax.persistence.Entity注釋將POJO標記為實體。

      以下代碼將使域模型中的Department對象成為實體:

    package onjava;
    import java.io.Serializable;
    import java.util.Collection;
    import javax.persistence.*;
    @Entity
    @NamedQuery(name="findAllDepartment", query="select o from Department o")
    @Table(name="DEPT")
    public class Department implements Serializable {
    @Id
    @Column(nullable=false)
    protected Long deptNo;
    @Column(name="DNAME")
    protected String name;
    @Column(name="LOC")
    protected String location;
    @OneToMany(mappedBy="department")
    protected Collection employees;
    public Department() {
    }
    ...
    public Collection getEmployees() {
    return employees;
    }
    public void setEmployees(Collection employees) {
    this.employees = employees;
    }
    public Employee addEmployee(Employee employee) {
    getEmployees().add(employee);
    employee.setDepartment(this);
    return employee;
    }
    public Employee removeEmployee(Employee employee) {
    getEmployees().remove(employee);
    employee.setDepartment(null);
    return employee;
    }
    }

      每個實體都有一個主鍵;可以在持久字段或屬性上使用Id注釋將其標記為主鍵。實體通過使用字段或屬性(通過setter和getter方法)來保存其狀態。這取決于在哪里使用O-R映射注釋。以上示例使用基于字段的訪問;我們已經使用了具有deptNo字段的Id注釋。要使用基于屬性的訪問,就要使用屬性標記注釋(例如Id),如下所示:

    @Id
    public Long getDeptNo() {
    return deptNo;
    }
    public void setDeptNo(Long deptNo) {
    this.deptNo = deptNo;
    }

      請記住,對一個實體層次結構中的所有實體,必須應用相同的訪問類型(字段或屬性)。

      默認情況下,定義在實體中的每個字段天然就是持久的;如果不希望保存字段/屬性的狀態,則必須將字段/屬性定義為瞬態的,方法是使用@Transient注釋或transient修飾符標記它。

      可嵌入對象

      可嵌入對象是不具有自己標識的持久對象;它是另一個實體的一部分。例如,我們可以假定Address沒有自己的標識,且作為Employee實體的一部分存儲。因此,Address是可嵌入對象的候選。

      可以如下所示創建可嵌入對象:

    @Embeddable
    public class Address {
    protected String streetAddr1;
    protected String streetAddr2;
    protected String city;
    protected String state;
    ..
    }

      以下是將對象定義為目標實體中的可嵌入對象的方法:

    @Entity
    public class Employee {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    protected Long id;
    ...
    @Embedded
    protected Address address;
    ...
    }

    描述符,因為可以使用它們重寫注釋。

                關系

      在一個典型的域模型中,實體是彼此關聯的,或者它們相互之間存在著關系。兩個實體之間的關系可以是一對一、一對多、多對一和多對多的。這些關系可以分別使用OneToOne、OneToMany、ManyToOne或ManyToMany注釋表示。在我們的示例中,Department和Employee實體之間具有雙向OneToMany關系。

      既然我們在實體中使用了基于字段的訪問,我們就在Department實體的關系字段上指定注釋,如下所示:

    @OneToMany(mappedBy="department")
    protected Collection<Employee> employees ;

      對于雙向關系,必須在關系的另一方指定mappedBy元素(如上),方法是指向擁有此關系的字段或屬性的名稱。

      標準化O-R映射

      可以使用Java元數據注釋或XML實現實體的O-R映射。EJB3 JPA定義了多種用于O-R映射的注釋,例如Table、SecondaryTable、Column、JoinColumn和PrimaryKeyJoinColumn。請參閱EJB3 JPA規范,以獲得關于所有注釋的信息。

      在我們的示例中,可以使用Table注釋定義實體被映射到的表,如下所示:

    @Table(name="DEPT")
    public class Department implements Serializable {

      EJB3 JPA嚴重依賴于默認設置,因此如果未定義表映射,則持久性提供程序會假定此實體被映射到與實體類同名的表(在我們的示例中是DEPARTMENT)。如果實體被映射到多個表,則可以使用SecondaryTable注釋。

      可以使用Column注釋將持久字段或屬性映射到數據庫列,如下所示:

    @Column(name="DNAME")
    protected String name;

      這里,DNAME是持久字段名稱所映射到的列的名稱。如果未使用Column注釋定義O-R映射,則持久性引擎會嘗試將其狀態保存在列中(使用與字段或屬性相同的名稱)。

      實體繼承性

      EJB3 JPA支持多種實體繼承性方法。它需要兩種類型的繼承性表映射策略:Single-table-per-entity層次結構策略和Joined-Subclass策略。最好避免使用可選的table-per-class層次結構。

      Single-table-per-entity (SINGLE_TABLE)層次結構策略允許將層次結構中的所有實體映射到一個表。在我們的示例中,FullTime和Contractor擴展了Employee,所有這些都可以映射到一個名為EMP的表。換句話說,所有與Employee、FullTime和Contractor有關的數據都被存儲于相同的表內。

      如果使用Joined Subclass策略,則可以將公共持久數據存儲在超類所映射到的表中(例如Employee),并且可以為層次結構中每個子類創建表,以便存儲特定于子類的持久字段。

      必須在超類中使用Inheritance注釋,以指定繼承類型,如以下代碼所示。此示例展示了使用single-table-per-entity層次結構策略的實體層次結構。

    @Entity
    @Table(name="EMP")
    @Inheritance(strategy=InheritanceType.SINGLE_TABLE)
    @DiscriminatorColumn(name="EMPLOYEE_TYPE",
    discriminatorType=DiscriminatorType.STRING, length=1)
    public abstract class Employee implements Serializable {
    ...
    }

      每個子類必須指定用于該實體類型的鑒別器值,如下所示:

    @Entity
    @DiscriminatorValue(value="F")
    public class FullTime extends Employee {
    @Column(name="SAL")
    protected Double salary;
    @Column(name="COMM")
    protected Double commission;
    @Column(name="DESIG")
    protected String designation;
    ...
    }

      Entity Manager API:用于實體操作的標準API

      javax.persistence.EntityManager管理實體生命周期,并公開了多個在實體上執行CRUD操作的方法。

      EntityManager API在事務上下文中調用。可以在EJB容器外部(例如,從一個Web應用程序)調用它,而無需會話bean外觀。

      在執行任何實體操作之前,必須獲取EntityManager實例。可以使用容器管理或應用程序管理的實體管理器,可以使用JNDI查找或依賴注入來獲取EntityManager實例。正如其名稱所暗示的,Java EE容器管理著容器管理實體管理器的生命周期。它可能主要在企業Java應用程序中使用。

      可以使用PersistenceContext注入獲取容器管理實體管理器實例,如下所示:

    @PersistenceContext(unitName="onjava")
    private EntityManager em;

      如果使用應用程序管理的實體管理器,則必須管理其生命周期。可以創建一個應用程序管理實體管理器實例,如下所示:

    @PersistenceUnit(unitName="onjava")
    private EntityManagerFactory emf;
    private EntityManager em = emf.createEntityManager();

      然后可以使用EntityManager實例在實體上執行CRUD操作。要關閉應用程序管理實體管理器實例,請在完成工作后調用em.close()方法。

      如前所述,必須在事務上下文中執行涉及任何數據庫更改的實體管理器操作。

      下表列出了EntityManager接口的一些用于執行實體操作的關鍵方法。

    方法 用途
    public void persist(Object entity); 持久化實體實例。
    public <T> T merge(T entity); 合并分離的實體實例。
    public void remove(Object entity); 移除實體實例。
    public <T> T find(Class<T> entityClass, Object primaryKey); 通過主鍵檢索實體實例。
    public void flush(); 使實體狀態與數據庫同步。

      可以使用persist()方法持久化實體實例。例如,如果想持久化Contractor實例,請使用以下代碼:

    @PersistenceContext(unitName="onjava")
    private EntityManager em;
    ...
    Contractor pte = new Contractor();
    pte.setName("Nistha")
    pte.setHourlyRate(new Double(100.0));
    em.persist(pte);

      在持久化實體時,如果此關系的CascadeType被設置為PERSIST或ALL,則任何對關聯實體的狀態更改也將被持久化。除非正在使用擴展的持久上下文,否則實體將在事務終止后分離。合并操作允許將分離的實體實例與持久上下文合并;分離實體的狀態將與數據庫同步。這將有助于擺脫EJB 2.x中常見的數據傳輸對象(Data Transfer Object,DTO)反模式,因為作為POJO的實體可以在層與層之間傳輸。惟一的要求是實體類必須實現java.io.Serializable接口。 

            查詢API

      對實體的檢索是持久性的一個重要方面。使用EJB3 JPA時,使用Java持久化查詢語言(Java Persistence Query Language,JPQL)表示查詢。JPQL是EJBQL的擴展,它是作為EJB 2.0規范的一部分而引入的。然而,EJB3 JPA解決了EJBQL的所有局限性,并添加了許多新特性,從而成為一種功能強大的查詢語言。

      JPQL較之EJBQL 2.x的改進

      以下是EJB3 JPA中的JPQL的新特性:

      ·簡化了的查詢語法

      ·JOIN操作

      ·Group By和Having Clause

      ·子查詢

      ·動態查詢

      ·指定參數(named parameter)

      ·批量更新和刪除

      此外,如果希望從特定于數據庫的查詢擴展中獲益,則必須對查詢實體使用原生(native ) SQL。

      動態查詢與指定查詢

      可以使用動態查詢或指定查詢(named query)。指定查詢隨實體存儲,可從應用程序重用。

      要創建動態查詢,請使用實體管理器接口的createQuery方法,如下所示:

    Query query = em.createQuery(
    "select e from Employee e where e.empNo > 1");
    query.setParameter(1,100);
    return query.getResultList();

      如果希望將此查詢用作指定查詢,請在實體中使用NamedQuery注釋,如下所示:

    @Entity
    @NamedQuery(name="findAllEmployee",
    query="select e from Employee e where e.empNo > 1")
    public abstract class Employee implements Serializable {
    }

      要執行指定查詢,首先使用EntityManager接口上的createNamedQuery方法創建一個Query實例,如下所示:

    query = em.createNamedQuery(" findAllEmployee");
    query.setParameter(1,100);
    return query.getResultList();

      指定參數

      可以在EJBQL查詢中使用指定參數(named parameter)代替位置參數(positional parameter)。例如,可以將以上查詢重寫如下:

      "select e from Employee e where e.empNo > :empNo "

      如果在查詢中使用指定參數,則必須設置此參數如下:

    query = em.createNamedQuery("findAllEmployee");
    query.setParameter("empNo",100);
    return query.getResultList();

      打包

      EJB3 JPA標準化了POJO持久性。因此,實體并不局限于EJB模塊;它們能夠打包到Web模塊、ejb-jar模塊、EAR級中的庫模塊或標準jar文件中。也可以在Java SE中使用實體。必須在包含實體的檔案文件中打包描述符(persistence.xml),如下所示:

    <persistence>
    <persistence-unit name="onjava">
    <provider>oracle.toplink.essentials.PersistenceProvider</provider>
    <jta-data-source>jdbc/OracleDS</jta-data-source>
    ...
    </persistence-unit>
    </persistence>

      此描述符標識持久性提供程序、持久單元和持久單元所使用的數據源。正如其名稱所暗示的,持久單元是集中管理的實體的集合。如果有一個定義在特定模塊中的持久單元,就不需要在persistence.xml中標識實體類;它將由持久性提供程序動態發現。

      參考實現

      BEA Kodo以及Oracle TopLink的TopLink Essentials都提供了EJB3 JPA的參考實現。它可分別從Open JPA和GlassFish開源項目中得到。

      您可以在參考實現服務器或其他任何服從EJB3 JPA的應用服務器上使用本文中的代碼。

      EJB3 JPA工具

      開發工具確實能夠幫助構建更好的應用程序,而如果使用XML實現O-R映射,情況可能就不太妙了。Eclipse Dali O-R映射項目,Oracle JDeveloper 10.1.3和BEA Workshop studio之類的工具都支持EJB3 JPA。

      結束語

      EJB3 Java Persistence API標準化了面向Java平臺的持久性API。它通過使用元數據注釋和異常配置方法,簡化了透明持久性的使用。多種應用服務器已支持EJB3規范(編者注:BEA已經發布WebLogic Server EJB 3.0 Tech Preview )。隨著Java EE 5.0和EJB 3.0規范的完成,您將很快看到許多一流的應用服務器和持久性提供程序會實現EJB3 Java Persistence API。您可以使用來自GlassFish項目的 參考實現 來啟用EJB3 Persistence。

            原文:http://dev.yesky.com/396/2498396.shtml
    主站蜘蛛池模板: 亚洲sss综合天堂久久久| 亚洲最新中文字幕| 特级毛片免费播放| www.亚洲色图| 中美日韩在线网免费毛片视频| 四虎永久在线免费观看| 成人精品国产亚洲欧洲| 亚洲Av无码乱码在线播放| 一级毛片aaaaaa视频免费看| 亚洲综合无码精品一区二区三区 | 亚洲乱人伦精品图片| 国产啪精品视频网免费| 亚洲AV成人一区二区三区在线看 | 中国videos性高清免费| 亚洲阿v天堂在线| 91久久青青草原线免费| www.亚洲成在线| 国产一级淫片视频免费看| 国产伦精品一区二区免费| 亚洲av鲁丝一区二区三区| 久久久久av无码免费网| 亚洲AV性色在线观看| 狠狠亚洲婷婷综合色香五月排名| 182tv免费视频在线观看| 最新国产成人亚洲精品影院| 国产又长又粗又爽免费视频| 精品国产免费一区二区三区| 亚洲系列中文字幕| 可以免费观看的一级毛片| a毛片免费全部在线播放**| 国产成+人+综合+亚洲专| 亚洲免费视频一区二区三区| 久久99精品免费视频| 亚洲精品无码久久久久A片苍井空| 国产精品亚洲视频| 国产成人精品免费视频大| 免费大片黄在线观看| 久久久亚洲欧洲日产国码是AV| 日韩成全视频观看免费观看高清| 男女拍拍拍免费视频网站| 亚洲乱码一二三四区乱码|