JPA高級映射

JPA是一種發佈使用Java規範的庫。因此,它支持所有的面向對象的概念實體,持久性。到現在爲止,我們已經完成了對象關係映射的基本知識。本章將完成對象和關係單位之間的高級映射。

繼承策略

繼承是任何面嚮對象語言的核心理念,因此我們可以用實體之間的繼承關係和策略。JPA支持三種類型的繼承策略:SINGLE_TABLE,JOINED_TABLE和TABLE_PER_CONCRETE_CLASS。

讓我們考慮一個例子。下圖顯示了三個等級,即Staff, TeachingStaff, and NonTeachingStaff和他們之間的關係。

Inheritance Strategy

在上面的圖中,員工是一個實體,而TeachingStaff和NonTeachingStaff是工作人員的子實體。在這裏,我們將使用上面的例子來演示繼承的全部三個策略。

單一表策略

單表策略採取所有類的字段(包括超級亞類),並將它們映射成稱爲SINGLE_TABLE策略一個表。這裏的鑑別值起着區分在一個表中三個實體的值的關鍵作用。

讓我們考慮上面的例子。TeachingStaff和NonTeachingStaff是Staff的子類。按照繼承的概念,一個子類繼承其超類中的屬性。因此sid和sname屬於TeachingStaff和NonTeachingStaff 字段。創建JPA項目。在這個項目中的所有模塊,如下所示:

創建實體

創建一個名爲「src」(源)在「com.yiibai.eclipselink.entity'包下。創建一個名爲Staff.java新的Java類。工作人員實體類如下所示:

package com.yiibai.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指定字段名稱(類型)和它的值顯示剩餘(Teaching和NonTeachingStaff)字段。

創建Staff類的一個子類叫TeachingStaff.java在com.yiibai.eclipselink.entity包下。TeachingStaff 實體類如下所示:

package com.yiibai.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; } }

創建Staff 的一個子類(類)類叫NonTeachingStaff.java 在 com.yiibai.eclipselink.entity 包下。NonTeachingStaff實體類如下所示:

package com.yiibai.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文件如下所示:

<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"> com.yiibai.eclipselink.entity.Staff com.yiibai.eclipselink.entity.NonTeachingStaff com.yiibai.eclipselink.entity.TeachingStaff <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost: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"/>

服務類

服務類業務組件的實現部分。創建com.yiibai.eclipselink.service「包在'src」下。

創建一個給定的包下名爲SaveClient.java用來存儲Staff,TeachingStaff和NonTeachingStaff類字段類。SaveClient類如下所示:

package com.yiibai.eclipselink.service; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import com.yiibai.eclipselink.entity.NonTeachingStaff; import com.yiibai.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工作臺的輸出。以表格格式的輸出如下所示:

Sid

Type

Sname

Areaexpertise

Qualification

Subjectexpertise

1

TS

Gopal

MSC MED

Maths

2

TS

Manisha

BSC BED

English

3

NS

Satish

Accounts

4

NS

Krishna

Office Admin

最後,會得到一個包含所有三個類字段鑑別列命名類型(字段)一個表。

註冊策略表

連接表的策略是共享引用的列包含唯一值的加入表並進行便捷事務。讓我們考慮與上述相同的例子。

創建JPA項目。所有工程的模塊如下所示。

創建實體

在「src」下創建一個名爲 com.yiibai.eclipselink.entity' 的包。創建一個名爲Staff.java新的Java類。Staff 實體類如下所示:

package com.yiibai.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; } }

創建Staff類的一個子類叫TeachingStaff.java在com.yiibai.eclipselink.entity包下。TeachingStaff 實體類如下所示:

package com.yiibai.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; } }

創建Staff的一個子類(類)類叫NonTeachingStaff.java在com.yiibai.eclipselink.entity包下。NonTeachingStaff實體類如下所示:

package com.yiibai.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文件如下所示:

<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"> com.yiibai.eclipselink.entity.Staff com.yiibai.eclipselink.entity.NonTeachingStaff com.yiibai.eclipselink.entity.TeachingStaff <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost: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"/>

服務類

服務類業務組件的實現部分。在src下創建一個包com.yiibai.eclipselink.service「。

創建一個名爲SaveClient.java給定的包來存儲Staff ,TeachingStaff,NonTeachingStaff類來存儲字段。然後SaveClient類如下所示:

package com.yiibai.eclipselink.service; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import com.yiibai.eclipselink.entity.NonTeachingStaff; import com.yiibai.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工作臺。

在這裏,將創建三個表和工作人員表的結果顯示在表格格式。

Sid

Dtype

Sname

1

TeachingStaff

Gopal

2

TeachingStaff

Manisha

3

NonTeachingStaff

Satish

4

NonTeachingStaff

Krishna

TeachingStaff表的結果顯示如下:

Sid

Qualification

Subjectexpertise

1

MSC MED

Maths

2

BSC BED

English

在上表中的sid是外鍵(參考字段工作人員表單表)NonTeachingStaff 表的結果顯示如下:

Sid

Areaexpertise

3

Accounts

4

Office Admin

最後,使用各自字段中創建三個表和SID字段由所有三個表共享。在員工表中,SID是主鍵。在剩下的兩個表(TeachingStaff和NonTeachingStaff),SID是外鍵。

每個類表策略

表每個類策略是創建一個表中爲每個子實體。 Staff表將被創建,但它會包含空值。Staff 表的字段值必須同時由TeachingStaff和NonTeachingStaff表共享。

讓我們考慮與上述相同的例子。

創建實體

在src下創建一個名爲「com.yiibai.eclipselink.entity'的包。創建一個名爲Staff.java爲一個新的Java類。Staff實體類如下所示:

package com.yiibai.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; } }

創建Staff類的一個子類叫TeachingStaff.java 在com.yiibai.eclipselink.entity包下。該TeachingStaff實體類如下所示:

package com.yiibai.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; } }

創建Staff 的一個子類(類)類叫NonTeachingStaff.java在com.yiibai.eclipselink.entity包下。NonTeachingStaff實體類如下所示:

package com.yiibai.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文件如下所示:

<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"> com.yiibai.eclipselink.entity.Staff com.yiibai.eclipselink.entity.NonTeachingStaff com.yiibai.eclipselink.entity.TeachingStaff <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost: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"/>

服務類

服務類業務組件的實現部分。在src下創建一個包com.yiibai.eclipselink.service「。

創建一個給定的包下名爲SaveClient.java用來存儲Staff,TeachingStaff和NonTeachingStaff 類字段類。該SaveClient類如下所示:

package com.yiibai.eclipselink.service; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import com.yiibai.eclipselink.entity.NonTeachingStaff; import com.yiibai.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的工作臺。

這裏創建了三個表並且Staff表的記錄爲空。

TeachingStaff的結果顯示如下:

Sid

Qualification

Sname

Subjectexpertise

1

MSC MED

Gopal

Maths

2

BSC BED

Manisha

English

上表TeachingStaff包含Staff和TeachingStaff實體字段。

NonTeachingStaff的結果顯示如下:

Sid

Areaexpertise

Sname

3

Accounts

Satish

4

Office Admin

Krishna

上表NonTeachingStaff包含Staff和NonTeachingStaff實體字段。