高级映射(Advanced Mappings)

优质
小牛编辑
130浏览
2023-12-01

JPA是一个随Java规范发布的库。 因此,它支持实体持久性的所有面向对象的概念。 到目前为止,我们已经完成了对象关系映射的基础知识。 本章将指导您完成对象和关系实体之间的高级映射。

继承策略

继承是面向对象语言的核心概念,因此我们可以使用实体之间的继承关系或策略。 JPA支持三种类型的继承策略,例如SINGLE_TABLE,JOINED_TABLE和TABLE_PER_CONCRETE_CLASS。

让我们考虑一下Staff,TeachingStaff,NonTeachingStaff类及其关系的示例,如下所示:

继承战略

在上面显示的图中,Staff是一个实体,TeachingStaff和NonTeachingStaff是Staff的子实体。 这里我们将在所有三种继承策略中讨论上面的例子。

单表策略

单表策略采用所有类字段(超类和子类)并将它们映射到称为SINGLE_TABLE策略的单个表中。 这里鉴别器值在区分一个表中三个实体的值方面起着关键作用。

让我们考虑上面的例子,TeachingStaff和NonTeachingStaff是类Staff的子类。 提醒继承的概念(是一种通过子类继承超类属性的机制),因此sid,sname是属于TeachingStaff和NonTeachingStaff的字段。 创建一个JPA项目。 该项目的所有模块如下:

创建实体

'src'包下创建一个名为'cn.xnip.eclipselink.entity' 'src'包。 在给定的包下创建一个名为Staff.java的新java类。 Staff实体类如下所示:

package cn.xnip.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)字段。

cn.xnip.eclipselink.entity包下创建名为TeachingStaff.java Staff类的子类(类)。 TeachingStaff Entity类如下所示:

package cn.xnip.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;
   }
}

cn.xnip.eclipselink.entity包下创建名为NonTeachingStaff.java Staff类的子类(类)。 NonTeachingStaff Entity类如下所示:

package cn.xnip.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>cn.xnip.eclipselink.entity.Staff</class>
      <class>cn.xnip.eclipselink.entity.NonTeachingStaff</class>
      <class>cn.xnip.eclipselink.entity.TeachingStaff</class>
      <properties>
         <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"/>
      </properties>
   </persistence-unit>
</persistence>

服务类

服务类是业务组件的实现部分。 在'src'包下创建一个名为'cn.xnip.eclipselink.service' 'src'包。

在给定包下创建一个名为SaveClient.java的类,以存储Staff,TeachingStaff和NonTeachingStaff类字段。 SaveClient类如下所示:

package cn.xnip.eclipselink.service;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import cn.xnip.eclipselink.entity.NonTeachingStaff;
import cn.xnip.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工作台的输出。 表格格式的输出如下所示:

希德类型SNAMEAreaexpertise合格Subjectexpertise
1TSGopalMSC MEDMaths
2TSManishaBSC BEDEnglish
3NSSatishAccounts
4NSKrishna办公室管理员

最后,您将获得包含所有三个类的字段的单个表,并且与名为'Type' (字段)的标识符列不同。

加入表策略

连接表策略是共享包含唯一值的引用列,以加入表并进行简单的事务处理。 让我们考虑与上面相同的例子。

创建JPA项目。 所有项目模块如下所示:

创建实体 (Creating Entities)

'src'包下创建一个名为'cn.xnip.eclipselink.entity' 'src'包。 在给定的包下创建一个名为Staff.java的新java类。 Staff实体类如下所示:

package cn.xnip.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;
   }
}

cn.xnip.eclipselink.entity包下创建名为TeachingStaff.java Staff类的子类(类)。 TeachingStaff Entity类如下所示:

package cn.xnip.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;
   }
}

cn.xnip.eclipselink.entity包下创建名为NonTeachingStaff.java Staff类的子类(类)。 NonTeachingStaff Entity类如下所示:

package cn.xnip.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>cn.xnip.eclipselink.entity.Staff</class>
      <class>cn.xnip.eclipselink.entity.NonTeachingStaff</class>
      <class>cn.xnip.eclipselink.entity.TeachingStaff</class>
      <properties>
         <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"/>
      </properties>
   </persistence-unit>
</persistence>

服务类

服务类是业务组件的实现部分。 在'src'包下创建一个名为'cn.xnip.eclipselink.service' 'src'包。

在给定包下创建一个名为SaveClient.java的类,以存储Staff,TeachingStaff和NonTeachingStaff类字段。 然后SaveClient类如下:

package cn.xnip.eclipselink.service;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import cn.xnip.eclipselink.entity.NonTeachingStaff;
import cn.xnip.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表结果如下所示:

希德D型SNAME
1TeachingStaffGopal
2TeachingStaffManisha
3NonTeachingStaffSatish
4NonTeachingStaffKrishna

以表格格式表示的TeachingStaff表的结果如下所示:

希德合格Subjectexpertise
1MSC MEDMaths
2BSC BEDEnglish

在上面的表中,sid是外键(引用字段表格staff表)表格格式的NonTeachingStaff表的结果如下所示:

希德Areaexpertise
3Accounts
4办公室管理员

最后,这三个表分别使用它们的字段创建,SID字段由所有三个表共享。 在员工表中,SID是主键,在剩余(TeachingStaff和NonTeachingStaff)表中,SID是外键。

每班策略表

每类策略的表是为每个子实体创建一个表。 将创建staff表,但它将包含空记录。 Staff表的字段值必须由TeachingStaff和NonTeachingStaff表共享。

让我们考虑与上面相同的例子。 该项目的所有模块如下所示:

创建实体 (Creating Entities)

'src'包下创建一个名为'cn.xnip.eclipselink.entity' 'src'包。 在给定的包下创建一个名为Staff.java的新java类。 Staff实体类如下所示:

package cn.xnip.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;
   }
}

cn.xnip.eclipselink.entity包下创建名为TeachingStaff.java Staff类的子类(类)。 TeachingStaff Entity类如下所示:

package cn.xnip.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;
   }
}

cn.xnip.eclipselink.entity包下创建名为NonTeachingStaff.java Staff类的子类(类)。 NonTeachingStaff Entity类如下所示:

package cn.xnip.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>cn.xnip.eclipselink.entity.Staff</class>
      <class>cn.xnip.eclipselink.entity.NonTeachingStaff</class>
      <class>cn.xnip.eclipselink.entity.TeachingStaff</class>
      <properties>
         <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"/>
      </properties>
   </persistence-unit>
</persistence>

服务类

服务类是业务组件的实现部分。 在'src'包下创建一个名为'cn.xnip.eclipselink.service' 'src'包。

在给定包下创建一个名为SaveClient.java的类,以存储Staff,TeachingStaff和NonTeachingStaff类字段。 SaveClient类如下所示:

package cn.xnip.eclipselink.service;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import cn.xnip.eclipselink.entity.NonTeachingStaff;
import cn.xnip.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的结果如下所示:

希德合格SNAMESubjectexpertise
1MSC MEDGopalMaths
2BSC BEDManishaEnglish

上表TeachingStaff包含Staff和TeachingStaff实体的字段。

表格格式的NonTeachingStaff结果如下所示:

希德AreaexpertiseSNAME
3AccountsSatish
4办公室管理员Krishna

上表NonTeachingStaff包含Staff和NonTeachingStaff实体的字段。