JPA - 高階對映



JPA 是一個隨 Java 規範釋出的庫。因此,它支援實體持久化的所有面向物件概念。到目前為止,我們已經完成了物件關係對映的基礎知識。本章將帶您瞭解物件和關係實體之間的高階對映。

繼承策略

繼承是面嚮物件語言的核心概念,因此我們可以在實體之間使用繼承關係或策略。JPA 支援三種類型的繼承策略,例如 SINGLE_TABLE、JOINED_TABLE 和 TABLE_PER_CONCRETE_CLASS。

讓我們考慮一個 Staff、TeachingStaff、NonTeachingStaff 類及其關係的示例,如下所示

Inheritance Strategy

在上圖中,Staff 是一個實體,TeachingStaff 和 NonTeachingStaff 是 Staff 的子實體。在這裡,我們將討論上述示例在所有三種繼承策略中的應用。

單表策略

單表策略獲取所有類的欄位(超類和子類),並將它們對映到一個稱為 SINGLE_TABLE 策略的單個表中。這裡,鑑別器值在區分一個表中三個實體的值方面起著關鍵作用。

讓我們考慮上面的例子,TeachingStaff 和 NonTeachingStaff 是 Staff 類的子類。回想一下繼承的概念(是從子類繼承超類屬性的機制),因此 sid、sname 是屬於 TeachingStaff 和 NonTeachingStaff 的欄位。建立一個 JPA 專案。該專案的所有模組如下所示

建立實體

‘src’ 包下建立一個名為 ‘com.tutorialspoint.eclipselink.entity’ 的包。在給定包下建立一個名為 Staff.java 的新 Java 類。Staff 實體類如下所示

package com.tutorialspoint.eclipselink.entity;

import java.io.Serializable;

import javax.persistence.DiscriminatorColumn;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;

@Entity
@Table
@Inheritance( strategy = InheritanceType.SINGLE_TABLE )
@DiscriminatorColumn( name = "type" )

public class Staff implements Serializable {
   @Id
   @GeneratedValue( strategy = GenerationType.AUTO )
   
   private int sid;
   private String sname;
   
   public Staff( int sid, String sname ) {
      super( );
      this.sid = sid;
      this.sname = sname;
   }
   
   public Staff( ) {
      super( );
   }
   
   public int getSid( ) {
      return sid;
   }
   
   public void setSid( int sid ) {
      this.sid = sid;
   }
   
   public String getSname( ) {
      return sname;
   }
   
   public void setSname( String sname ) {
      this.sname = sname;
   }
}

在上面的程式碼中,@DescriminatorColumn 指定欄位名稱 (type),其值顯示其餘的(Teaching 和 NonTeachingStaff)欄位。

com.tutorialspoint.eclipselink.entity 包下,建立一個名為 TeachingStaff.java 的 Staff 類的子類(類)。TeachingStaff 實體類如下所示

package com.tutorialspoint.eclipselink.entity;

import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;

@Entity
@DiscriminatorValue( value="TS" )
public class TeachingStaff extends Staff {

   private String qualification;
   private String subjectexpertise;

   public TeachingStaff( int sid, String sname, 
   
   String qualification,String subjectexpertise ) {
      super( sid, sname );
      this.qualification = qualification;
      this.subjectexpertise = subjectexpertise;
   }

   public TeachingStaff( ) {
      super( );
   }

   public String getQualification( ){
      return qualification;
   }

   public void setQualification( String qualification ){
      this.qualification = qualification;
   }

   public String getSubjectexpertise( ) {
      return subjectexpertise;
   }

   public void setSubjectexpertise( String subjectexpertise ){
      this.subjectexpertise = subjectexpertise;
   }
}

com.tutorialspoint.eclipselink.entity 包下,建立一個名為 NonTeachingStaff.java 的 Staff 類的子類(類)。NonTeachingStaff 實體類如下所示

package com.tutorialspoint.eclipselink.entity;

import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;

@Entity
@DiscriminatorValue( value = "NS" )

public class NonTeachingStaff extends Staff {
   private String areaexpertise;

   public NonTeachingStaff( int sid, String sname, String areaexpertise ) {
      super( sid, sname );
      this.areaexpertise = areaexpertise;
   }

   public NonTeachingStaff( ) {
      super( );
   }

   public String getAreaexpertise( ) {
      return areaexpertise;
   }

   public void setAreaexpertise( String areaexpertise ){
      this.areaexpertise = areaexpertise;
   }
}

persistence.xml

persistence.xml 檔案包含資料庫配置資訊和實體類的註冊資訊。xml 檔案如下所示

<?xml version="1.0" encoding="UTF-8"?>

<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
   xsi:schemaLocation="http://java.sun.com/xml/ns/persistence 
   http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">

   <persistence-unit name="Eclipselink_JPA" transaction-type="RESOURCE_LOCAL">
   
      <class>com.tutorialspoint.eclipselink.entity.Staff</class>
      <class>com.tutorialspoint.eclipselink.entity.NonTeachingStaff</class>
      <class>com.tutorialspoint.eclipselink.entity.TeachingStaff</class>
      
      <properties>
         <property name="javax.persistence.jdbc.url" value="jdbc:mysql://:3306/jpadb"/>
         <property name="javax.persistence.jdbc.user" value="root"/>
         <property name="javax.persistence.jdbc.password" value="root"/>
         <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
         <property name="eclipselink.logging.level" value="FINE"/>
         <property name="eclipselink.ddl-generation" value="create-tables"/>
      </properties>
      
   </persistence-unit>
</persistence>

服務類

服務類是業務元件的實現部分。在 ‘src’ 包下建立一個名為 ‘com.tutorialspoint.eclipselink.service’ 的包。

在給定包下建立一個名為 SaveClient.java 的類,以儲存 Staff、TeachingStaff 和 NonTeachingStaff 類的欄位。SaveClient 類如下所示

package com.tutorialspoint.eclipselink.service;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import com.tutorialspoint.eclipselink.entity.NonTeachingStaff;
import com.tutorialspoint.eclipselink.entity.TeachingStaff;

public class SaveClient {

   public static void main( String[ ] args ) {
   
      EntityManagerFactory emfactory = Persistence.createEntityManagerFactory( "Eclipselink_JPA" );
      EntityManager entitymanager = emfactory.createEntityManager( );
      entitymanager.getTransaction( ).begin( );

      //Teaching staff entity 
      TeachingStaff ts1=new TeachingStaff(1,"Gopal","MSc MEd","Maths");
      TeachingStaff ts2=new TeachingStaff(2, "Manisha", "BSc BEd", "English");
      
      //Non-Teaching Staff entity
      NonTeachingStaff nts1=new NonTeachingStaff(3, "Satish", "Accounts");
      NonTeachingStaff nts2=new NonTeachingStaff(4, "Krishna", "Office Admin");

      //storing all entities
      entitymanager.persist(ts1);
      entitymanager.persist(ts2);
      entitymanager.persist(nts1);
      entitymanager.persist(nts2);
      
      entitymanager.getTransaction().commit();
      
      entitymanager.close();
      emfactory.close();
   }
}

編譯並執行上述程式後,您將在 Eclipse IDE 的控制檯面板中收到通知。檢查 MySQL Workbench 以獲取輸出。輸出以表格格式顯示如下

Sid 型別 Sname 專業領域 資格 學科專業
1 TS Gopal MSC MED 數學
2 TS Manisha BSC BED 英語
3 NS Satish 會計
4 NS Krishna 辦公室行政

最後,您將獲得一個包含所有三個類欄位的單表,並由名為 ‘Type’(欄位)的鑑別器列區分。

連線表策略

連線表策略是共享包含唯一值的引用列,以連線表並簡化事務。讓我們考慮與上面相同的示例。

建立一個 JPA 專案。所有專案模組如下所示

建立實體

‘src’ 包下建立一個名為 ‘com.tutorialspoint.eclipselink.entity’ 的包。在給定包下建立一個名為 Staff.java 的新 Java 類。Staff 實體類如下所示

package com.tutorialspoint.eclipselink.entity;

import java.io.Serializable;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;

@Entity
@Table
@Inheritance( strategy = InheritanceType.JOINED )

public class Staff implements Serializable {

   @Id
   @GeneratedValue( strategy = GenerationType.AUTO )
   
   private int sid;
   private String sname;
   
   public Staff( int sid, String sname ) {
      super( );
      this.sid = sid;
      this.sname = sname;
   }
   
   public Staff( ) {
      super( );
   }
   
   public int getSid( ) {
      return sid;
   }
   
   public void setSid( int sid ) {
      this.sid = sid;
   }
   
   public String getSname( ) {
      return sname;
   }
   
   public void setSname( String sname ) {
      this.sname = sname;
   }
}

com.tutorialspoint.eclipselink.entity 包下,建立一個名為 TeachingStaff.java 的 Staff 類的子類(類)。TeachingStaff 實體類如下所示

package com.tutorialspoint.eclipselink.entity;

import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;

@Entity
@PrimaryKeyJoinColumn(referencedColumnName="sid")

public class TeachingStaff extends Staff {
   private String qualification;
   private String subjectexpertise;

   public TeachingStaff( int sid, String sname, 
   
   String qualification,String subjectexpertise ) {
      super( sid, sname );
      this.qualification = qualification;
      this.subjectexpertise = subjectexpertise;
   }

   public TeachingStaff( ) {
      super( );
   }

   public String getQualification( ){
      return qualification;
   }

   public void setQualification( String qualification ){
      this.qualification = qualification;
   }

   public String getSubjectexpertise( ) {
      return subjectexpertise;
   }

   public void setSubjectexpertise( String subjectexpertise ){
      this.subjectexpertise = subjectexpertise;
   }
}

com.tutorialspoint.eclipselink.entity 包下,建立一個名為 NonTeachingStaff.java 的 Staff 類的子類(類)。NonTeachingStaff 實體類如下所示

package com.tutorialspoint.eclipselink.entity;

import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;

@Entity
@PrimaryKeyJoinColumn(referencedColumnName="sid")

public class NonTeachingStaff extends Staff {
   private String areaexpertise;

   public NonTeachingStaff( int sid, String sname, String areaexpertise ) {
      super( sid, sname );
      this.areaexpertise = areaexpertise;
   }

   public NonTeachingStaff( ) {
      super( );
   }

   public String getAreaexpertise( ) {
      return areaexpertise;
   }

   public void setAreaexpertise( String areaexpertise ) {
      this.areaexpertise = areaexpertise;
   }
}

persistence.xml

persistence.xml 檔案包含資料庫配置資訊和實體類的註冊資訊。xml 檔案如下所示

<?xml version = "1.0" encoding = "UTF-8"?>

<persistence version = "2.0" xmlns = "http://java.sun.com/xml/ns/persistence" 
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" 
   xsi:schemaLocation = "http://java.sun.com/xml/ns/persistence 
   http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
   
   <persistence-unit name = "Eclipselink_JPA" transaction-type = "RESOURCE_LOCAL">
      <class>com.tutorialspoint.eclipselink.entity.Staff</class>
      <class>com.tutorialspoint.eclipselink.entity.NonTeachingStaff</class>
      <class>com.tutorialspoint.eclipselink.entity.TeachingStaff</class>
      
      <properties>
         <property name = "javax.persistence.jdbc.url" value = "jdbc:mysql://:3306/jpadb"/>
         <property name = "javax.persistence.jdbc.user" value = "root"/>
         <property name = "javax.persistence.jdbc.password" value = "root"/>
         <property name = "javax.persistence.jdbc.driver" value = "com.mysql.jdbc.Driver"/>
         <property name = "eclipselink.logging.level" value = "FINE"/>
         <property name = "eclipselink.ddl-generation" value = "create-tables"/>
      </properties>
      
   </persistence-unit>
</persistence>

服務類

服務類是業務元件的實現部分。在 ‘src’ 包下建立一個名為 ‘com.tutorialspoint.eclipselink.service’ 的包。

在給定包下建立一個名為 SaveClient.java 的類,以儲存 Staff、TeachingStaff 和 NonTeachingStaff 類的欄位。然後 SaveClient 類如下所示

package com.tutorialspoint.eclipselink.service;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import com.tutorialspoint.eclipselink.entity.NonTeachingStaff;
import com.tutorialspoint.eclipselink.entity.TeachingStaff;

public class SaveClient {
   public static void main( String[ ] args ) {
      EntityManagerFactory emfactory = Persistence.createEntityManagerFactory( "Eclipselink_JPA" );
      EntityManager entitymanager = emfactory.createEntityManager( );
      entitymanager.getTransaction( ).begin( );

      //Teaching staff entity 
      TeachingStaff ts1 = new TeachingStaff(1,"Gopal","MSc MEd","Maths");
      TeachingStaff ts2 = new TeachingStaff(2, "Manisha", "BSc BEd", "English");
      
      //Non-Teaching Staff entity
      NonTeachingStaff nts1 = new NonTeachingStaff(3, "Satish", "Accounts");
      NonTeachingStaff nts2 = new NonTeachingStaff(4, "Krishna", "Office Admin");

      //storing all entities
      entitymanager.persist(ts1);
      entitymanager.persist(ts2);
      entitymanager.persist(nts1);
      entitymanager.persist(nts2);

      entitymanager.getTransaction().commit();
      entitymanager.close();
      emfactory.close();
   }
}

編譯並執行上述程式後,您將在 Eclipse IDE 的控制檯面板中收到通知。要檢視輸出,請檢查 MySQL Workbench,如下所示

這裡建立了三個表,staff 表的結果以表格格式顯示如下

Sid Dtype Sname
1 TeachingStaff Gopal
2 TeachingStaff Manisha
3 NonTeachingStaff Satish
4 NonTeachingStaff Krishna

TeachingStaff 表的結果以表格格式顯示如下

Sid 資格 學科專業
1 MSC MED 數學
2 BSC BED 英語

在上表中,sid 是外部索引鍵(來自 staff 表的引用欄位)。NonTeachingStaff 表的結果以表格格式顯示如下

Sid 專業領域
3 會計
4 辦公室行政

最後,使用各自的欄位建立了三個表,並且 SID 欄位由所有三個表共享。在 staff 表中,SID 是主鍵,在其餘的(TeachingStaff 和 NonTeachingStaff)表中,SID 是外部索引鍵。

每個類表策略

每個類表策略是為每個子實體建立一個表。將建立 staff 表,但它將包含空記錄。Staff 表的欄位值必須由 TeachingStaff 和 NonTeachingStaff 表共享。

讓我們考慮與上面相同的示例。該專案的所有模組如下所示

建立實體

‘src’ 包下建立一個名為 ‘com.tutorialspoint.eclipselink.entity’ 的包。在給定包下建立一個名為 Staff.java 的新 Java 類。Staff 實體類如下所示

package com.tutorialspoint.eclipselink.entity;

import java.io.Serializable;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;

@Entity
@Table
@Inheritance( strategy = InheritanceType.TABLE_PER_CLASS )

public class Staff implements Serializable {

   @Id
   @GeneratedValue( strategy = GenerationType.AUTO )

   private int sid;
   private String sname;

   public Staff( int sid, String sname ) {
      super( );
      this.sid = sid;
      this.sname = sname;
   }

   public Staff( ) {
      super( );
   }

   public int getSid( ) {
      return sid;
   }

   public void setSid( int sid ) {
      this.sid = sid;
   }

   public String getSname( ) {
      return sname;
   }

   public void setSname( String sname ) {
      this.sname = sname;
   }
}

com.tutorialspoint.eclipselink.entity 包下,建立一個名為 TeachingStaff.java 的 Staff 類的子類(類)。TeachingStaff 實體類如下所示

package com.tutorialspoint.eclipselink.entity;

import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;

@Entity
public class TeachingStaff extends Staff {
   private String qualification;
   private String subjectexpertise;

   public TeachingStaff( int sid, String sname, String qualification, String subjectexpertise ) {
      super( sid, sname );
      this.qualification = qualification;
      this.subjectexpertise = subjectexpertise;
   }

   public TeachingStaff( ) {
      super( );
   }

   public String getQualification( ){
      return qualification;
   }
   
   public void setQualification( String qualification ) {
      this.qualification = qualification;
   }

   public String getSubjectexpertise( ) {
      return subjectexpertise;
   }

   public void setSubjectexpertise( String subjectexpertise ){
      this.subjectexpertise = subjectexpertise;
   }
}

com.tutorialspoint.eclipselink.entity 包下,建立一個名為 NonTeachingStaff.java 的 Staff 類的子類(類)。NonTeachingStaff 實體類如下所示

package com.tutorialspoint.eclipselink.entity;

import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;

@Entity
public class NonTeachingStaff extends Staff {
   private String areaexpertise;

   public NonTeachingStaff( int sid, String sname, String areaexpertise ) {
      super( sid, sname );
      this.areaexpertise = areaexpertise;
   }

   public NonTeachingStaff( ) {
      super( );
   }

   public String getAreaexpertise( ) {
      return areaexpertise;
   }

   public void setAreaexpertise( String areaexpertise ) {
      this.areaexpertise = areaexpertise;
   }
}

persistence.xml

persistence.xml 檔案包含資料庫配置資訊和實體類的註冊資訊。xml 檔案如下所示

<?xml version="1.0" encoding = "UTF-8"?>
<persistence version = "2.0" xmlns = "http://java.sun.com/xml/ns/persistence"
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" 
   xsi:schemaLocation = "http://java.sun.com/xml/ns/persistence 
   http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">

   <persistence-unit name = "Eclipselink_JPA" transaction-type = "RESOURCE_LOCAL">
      <class>com.tutorialspoint.eclipselink.entity.Staff</class>
      <class>com.tutorialspoint.eclipselink.entity.NonTeachingStaff</class>
      <class>com.tutorialspoint.eclipselink.entity.TeachingStaff</class>
      
      <properties>
         <property name = "javax.persistence.jdbc.url" value = "jdbc:mysql://:3306/jpadb"/>
         <property name = "javax.persistence.jdbc.user" value = "root"/>
         <property name = "javax.persistence.jdbc.password" value = "root"/>
         <property name = "javax.persistence.jdbc.driver" value = "com.mysql.jdbc.Driver"/>
         <property name = "eclipselink.logging.level" value = "FINE"/>
         <property name = "eclipselink.ddl-generation" value="create-tables"/>
      </properties>
      
   </persistence-unit>
</persistence>

服務類

服務類是業務元件的實現部分。在 ‘src’ 包下建立一個名為 ‘com.tutorialspoint.eclipselink.service’ 的包。

在給定包下建立一個名為 SaveClient.java 的類,以儲存 Staff、TeachingStaff 和 NonTeachingStaff 類的欄位。SaveClient 類如下所示

package com.tutorialspoint.eclipselink.service;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import com.tutorialspoint.eclipselink.entity.NonTeachingStaff;
import com.tutorialspoint.eclipselink.entity.TeachingStaff;

public class SaveClient {
   public static void main( String[ ] args ) {
      EntityManagerFactory emfactory = Persistence.createEntityManagerFactory( "Eclipselink_JPA" );
      EntityManager entitymanager = emfactory.createEntityManager( );
      entitymanager.getTransaction( ).begin( );

      //Teaching staff entity 
      TeachingStaff ts1 = new TeachingStaff(1,"Gopal","MSc MEd","Maths");
      TeachingStaff ts2 = new TeachingStaff(2, "Manisha", "BSc BEd", "English");
      
      //Non-Teaching Staff entity
      NonTeachingStaff nts1 = new NonTeachingStaff(3, "Satish", "Accounts");
      NonTeachingStaff nts2 = new NonTeachingStaff(4, "Krishna", "Office Admin");

      //storing all entities
      entitymanager.persist(ts1);
      entitymanager.persist(ts2);
      entitymanager.persist(nts1);
      entitymanager.persist(nts2);

      entitymanager.getTransaction().commit();
      entitymanager.close();
      emfactory.close();
   }
}

編譯並執行上述程式後,您將在 Eclipse IDE 的控制檯面板中收到通知。要檢視輸出,請檢查 MySQL Workbench,如下所示

這裡建立了三個表,Staff 表包含空記錄。

TeachingStaff 的結果以表格格式顯示如下

Sid 資格 Sname 學科專業
1 MSC MED Gopal 數學
2 BSC BED Manisha 英語

上表 TeachingStaff 包含 Staff 和 TeachingStaff 實體的欄位。

NonTeachingStaff 的結果以表格格式顯示如下

Sid 專業領域 Sname
3 會計 Satish
4 辦公室行政 Krishna

上表 NonTeachingStaff 包含 Staff 和 NonTeachingStaff 實體的欄位。

廣告

© . All rights reserved.