JPA高级映射 JPA JPQL JPA实体关系 JPA是一个随Java规范发布的库。因此,它支持所有面向对象的实体持久化概念。到目前为止,我们已经完成了对象关系映射的基础知识。本章将指导您完成对象和关系实体之间的高级映射。 继承策略 继承是面向对象语言的核心概念,因此我们可以使用实体之间的继承关系或策略。JPA支持三种类型的继承策略,例如SINGLE_TABLE,JOINED_TABLE和TABLE_PER_CONCRETE_CLASS。 让我们考虑一下Staff,TeachingStaff,NonTeachingStaff类及其关系如下: 在上面的图表中,员工是一个实体,TeachingStaff和NonTeachingStaff是员工的子实体。这里我们将在所有三种继承策略中讨论上面的例子。 单桌战略 单表战略采用所有类字段(超类和子类)并将它们映射到一个称为SINGLE_TABLE策略的表中。这里,鉴别器价值在区分一个表中三个实体的价值方面起着关键作用。 让我们考虑上面的例子,TeachingStaff和NonTeachingStaff是Staff类的子类。提醒继承的概念(是通过子类继承超类属性的机制),因此sid,sname是属于TeachingStaff和NonTeachingStaff的字段。创建一个JPA项目。该项目的所有模块如下: 创建实体 在 'src' 包下创建一个名为 'com.CodingDict.eclipselink.entity' 的 包。在给定的包下创建一个名为 Staff.java 的新Java类。职员实体类显示如下: package com.CodingDict.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)字段。 在 com.CodingDict.eclipselink.entity 包下创建一个名为 TeachingStaff.java的 Staff类的子类(class) 。TeachingStaff实体类如下所示: ** package com. CodingDict.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.CodingDict.eclipselink.entity 包下创建一个名为 NonTeachingStaff.java的 Staff类的子类(class) 。NonTeachingStaff实体类如下所示: ** package com. CodingDict.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.CodingDict.eclipselink.entity.Staff</class> <class>com.CodingDict.eclipselink.entity.NonTeachingStaff</class> <class>com.CodingDict.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> 服务类 服务类是业务组件的实现部分。在名为 'com.CodingDict.eclipselink.service'的 'src' 包下创建一个包。 ** 在给定包下创建一个名为SaveClient.java的类来存储Staff,TeachingStaff和NonTeachingStaff类字段。 SaveClient类如下所示: package com.CodingDict.eclipselink.service; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import com.CodingDict.eclipselink.entity.NonTeachingStaff; import com.CodingDict.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 最后,你将得到单个表,其中包含所有三个类的字段,并且与名为 '类型' (字段)的鉴别器列不同。 加入桌面策略 联合表策略是共享包含唯一值的引用列以加入表并轻松实现交易。让我们考虑一下上面的例子。 创建一个JPA项目。所有的项目模块如下所示: 创建实体 在 'src' 包下创建一个名为 'com.CodingDict.eclipselink.entity' 的 包。在给定的包下创建一个名为 Staff.java 的新Java类。职员实体类显示如下: package com.CodingDict.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.CodingDict.eclipselink.entity 包下创建一个名为 TeachingStaff.java的 Staff类的子类(class) 。TeachingStaff实体类如下所示: ** package com. CodingDict.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.CodingDict.eclipselink.entity 包下创建一个名为 NonTeachingStaff.java的 Staff类的子类(class) 。NonTeachingStaff实体类如下所示: ** package com. CodingDict.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.CodingDict.eclipselink.entity.Staff</class> <class>com.CodingDict.eclipselink.entity.NonTeachingStaff</class> <class>com.CodingDict.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> 服务类 服务类是业务组件的实现部分。在名为 'com.CodingDict.eclipselink.service'的 'src' 包下创建一个包。 ** 在给定包下创建一个名为SaveClient.java的类来存储Staff,TeachingStaff和NonTeachingStaff类字段。 然后SaveClient类如下所示: package com.CodingDict.eclipselink.service; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import com.CodingDict.eclipselink.entity.NonTeachingStaff; import com.CodingDict.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工作台,如下所示: 这里创建了三个表格,表格格式的 工作人员 表格的结果如下所示: 希德 D型 SNAME 1 教学人员 戈帕尔 2 教学人员 MANISHA 3 NonTeachingStaff 萨蒂什 4 NonTeachingStaff 克里希纳 以表格格式显示 TeachingStaff 表的结果如下所示: 希德 合格 Subjectexpertise 1 MSC MED 数学 2 BSC BED 英语 在上表中sid是外键(参考字段形式staff表)表格格式的 NonTeachingStaff 表的结果如下所示: 希德 Areaexpertise 3 帐号 4 Office Admin 最后,三个表分别使用它们的字段创建,SID字段由所有三个表共享。在员工表中,SID是主键,其余(TeachingStaff和NonTeachingStaff)表中的SID是外键。 表每类战略 每个类策略的表是为每个子实体创建一个表。职员表将被创建,但它将包含空记录。Staff表中的字段值必须由TeachingStaff和NonTeachingStaff表共享。 让我们考虑一下上面的例子。该项目的所有模块如下所示: 创建实体 在 'src' 包下创建一个名为 'com.CodingDict.eclipselink.entity' 的 包。在给定的包下创建一个名为 Staff.java 的新Java类。职员实体类显示如下: package com.CodingDict.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.CodingDict.eclipselink.entity 包下创建一个名为 TeachingStaff.java的 Staff类的子类(class) 。TeachingStaff实体类如下所示: ** package com. CodingDict.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.CodingDict.eclipselink.entity 包下创建一个名为 NonTeachingStaff.java的 Staff类的子类(class) 。NonTeachingStaff实体类如下所示: ** package com. CodingDict.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.CodingDict.eclipselink.entity.Staff</class> <class>com.CodingDict.eclipselink.entity.NonTeachingStaff</class> <class>com.CodingDict.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> 服务类 服务类是业务组件的实现部分。在名为 'com.CodingDict.eclipselink.service'的 'src' 包下创建一个包。 ** 在给定包下 创建一个名为 SaveClient.java 的类来存储Staff,TeachingStaff和NonTeachingStaff类字段。SaveClient类如下所示: package com.CodingDict.eclipselink.service; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import com.CodingDict.eclipselink.entity.NonTeachingStaff; import com.CodingDict.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 的结果如下所示: 希德 合格 SNAME Subjectexpertise 1 MSC MED 戈帕尔 数学 2 BSC BED MANISHA 英语 上表TeachingStaff包含Staff和TeachingStaff实体的字段。 的结果 NonTeachingStaff 以表格格式如下所示: 希德 Areaexpertise SNAME 3 帐号 萨蒂什 4 Office Admin 克里希纳 上表NonTeachingStaff包含Staff和NonTeachingStaff实体的字段。 JPA JPQL JPA实体关系