Java Passion

Tuesday Apr 01, 2008

Java Persistence API (JPA ) 映射 (四)

(2.2) 显式使用 SINGLE_TABLE 作为继承策略


在本步骤中,我们将通过指定来使用 SINGLE_TABLE 策略。应用程序的行为应该与练习 4.1 相同,因为 SINGLE_TABLE 是默认策略。

1. 根据代码 2.20 修改 Person.java,显式指定 SINGLE_TABLE 策略。需要修改的代码段突出显示为 蓝色的粗体 字。作用是显式指定 SINGLE_TABLE 作为继承策略。

package mypackage;

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;


/**
 * Entity class Person
 *
 * @author sang
 */
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
public class Person implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
   
    // Add a name field to the Person class
    private String name;
   
    /** Creates a new instance of Person */
    public Person() {
    }

    /**
     * Gets the id of this Person.
     * @return the id
     */
    public Long getId() {
        return this.id;
    }

    /**
     * Sets the id of this Person to the specified value.
     * @param id the new id
     */
    public void setId(Long id) {
        this.id = id;
    }

    /**
     * Returns a hash code value for the object.  This implementation computes
     * a hash code value based on the id fields in this object.
     * @return a hash code value for this object.
     */
    @Override
    public int hashCode() {
        int hash = 0;
        hash += (this.id != null ? this.id.hashCode() : 0);
        return hash;
    }

    /**
     * Determines whether another object is equal to this Person.  The result is
     * <code>true</code> if and only if the argument is not null and is a Person object that
     * has the same id field values as this object.
     * @param object the reference object with which to compare
     * @return <code>true</code> if this object is the same as the argument;
     * <code>false</code> otherwise.
     */
    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof Person)) {
            return false;
        }
        Person other = (Person)object;
        if (this.id != other.id && (this.id == null || !this.id.equals(other.id))) return false;
        return true;
    }

    /**
     * Returns a string representation of the object.  This implementation constructs
     * that representation based on the id fields.
     * @return a string representation of the object.
     */
    @Override
    public String toString() {
        return "mypackage.Person[id=" + id + "]";
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
   
}

代码 2.20:显式使用 SINGLE_TABLE 策略


<NetBeans 技巧> 您可能希望使用 NetBeans IDE 对注释的自动完成功能。 
  • 举例来说,只需键入 @Inh 并按 CTRL+空格 键就可以看到以 @Inh 为首的两个注释:@Inheritance@Inherited
  • 选择 @Inheritance(如图 2.21 所示)

图 2.21:@Inheritance 的代码完成
  • 再次按下 CTRL+空格 键。
  • 选择 InheritanceType 策略。(如图 2.22 所示)

图 2.22:策略的代码完成
  • 按 CTRL+空格 键可以看到两种可能的继承策略。
  • 选择 SINGLE_TABLE。(如图 2.23 所示)

图 2.23:SINGLE_TABLE 的代码完成
  • @Inheritance(strategy=InheritanceType.SINGLE_TABLE) 已经完成


2. 右键单击刚才创建的行并选择 修复导入。(如果按 CTRL+空格键启用了代码完成功能,则不需要执行此步骤,因为 NetBeans 将自动添加导入。) 3. 查看 SINGLE_TABLE 继承策略的 JavaDoc。
  • 右键单击 @Inheritance(strategy=InheritanceType.SINGLE_TABLE) 并选择 显示 Javadoc。(如图 2.25 所示)

图 2.25:显示 Javadoc
  • 浏览器将显示 Enum InheritanceType 的 Javadoc。
  • 查看 SINGLE_TABLEJOINED 的说明。(如图 2.26 所示)

图 2.26:SINGLE_TABLE 和 JOINED 的 Javadoc

4. 运行应用程序
  • 右键单击 ORInheritanceSINGLE_TABLE 项目并选择 运行项目
  • 根据练习 1 中的步骤 9 创建一些 Person 实例和 Student 实例。
4. 验证所创建的数据库表。
6. 右键单击 PERSON 数据库表并选择 删除。(用于后续练习) 

                                                                                                                        返回练习顶部


(2.3) 显式使用 JOINED 继承策略


在本步骤中,我们将使用 JOINED 继承策略。此处的操作与步骤 4.2 相似。为避免混淆,我们将两个类命名为 Person2 和 Student2。

在 JOINED 策略中,特定于子类的字段将映射到一个单独的表中,而不是父类的公共字段,并且将执行合并操作实例化子类。

1. 创建一个 NetBeans 项目。(与上面的步骤 4.2 相同)
  • 选择 文件->新建项目(Ctrl+Shift+N)。此时将出现 新建项目 对话框。
  • 选择项目 窗格中,选择 类别 列表中的 Web,并选择 项目 列表中的 Web 应用程序。单击 下一步 按钮。
  • 等待 名称和位置 窗格出现。
  • 项目名称 字段中,键入 ORInheritanceJOINED
  • 单击 下一步 按钮。
  • 等待 框架 窗格出现。
  • 选择 JavaServer Faces
  • 单击 完成 按钮。
2.  为项目创建持久性单元。(与上面的步骤 4.2 相同)
  • 右键单击 ORInheritanceJOINED 项目并选择 新建->持久性单元
  • 等待 提供器和数据库 窗格出现。
  • 对于 数据库连接 字段,从下拉菜单中选择 jdbc/sample
  • 对于 表生成策略 字段,选择 删除并创建。每次运行项目时,都将删除已有表并创建新表。
  • 单击 完成 按钮。
3. 编写 Person2 实体类。(与上面的步骤 4.2 相同)
  • 右键单击 ORInheritanceJOINED 项目并选择 新建->实体类。
  • 等待 名称和位置 窗格出现。
  • 类名 字段中,键入 Person2
  • 字段中,键入 mypackage。 
  • 单击 完成 按钮。
4. 将 name 字段添加到 Person2 实体类中。(与上面的步骤 4.2 相同)
  • 根据上面的代码 2.15 修改 ORInheritanceJOINED->源包->mypackage 中的 Person2.java
  • 在源编辑器中右键单击 name 字段,并选择 重构->封装字段
  • 此时将出现 封装字段 - mypackage.Person 对话框。
  • 单击 下一步 按钮。
  • 输出 区域查看重构的预览效果。
  • 单击 执行重构 确认重构操作。
  • 现在,Person 类在代码末尾部分拥有了 getName() setName() 方法。
5. 通过扩展 Person2 实体类来编写 Student2 实体类。
  • 右键单击 ORInheritanceJOINED 项目并选择 新建->Java 类。
  • 等待 名称和位置 窗格出现。
  • 类名 字段中,键入 Student2
  • 字段中,键入 mypackage
  • 单击 完成 按钮。
  • 根据代码 2.62 修改 Student2.java。需要修改的代码段突出显示为 蓝色的粗体 字。
package mypacakge;

/**
 *
 * @author sang
 */
@Entity
public class Student2 extends Person2 {
   
    /** Creates a new instance of Student2 */
    public Student2() {
    }
   
}
代码 2.62:经过修改的 Student2.java

6. 对 Student2.java.执行 修复导入。(如果按 CTRL+空格键启用了代码完成功能,则不需要执行此步骤,因为 NetBeans 将自动添加导入。)
  • 注意 @Entity 含有 Cannot find Symbol 编译器错误。
  • 右键单击 @Entity 并选择 修复导入
  • 等待 修复导入 对话框出现。
  • 从下拉菜单中选择 javax.persitence.Entity
  • 单击 确定 按钮。
  • 导入语句已添加,并且编译器错误已经从源编辑器中消失。

7. 将 school grade 字段添加到 Student2.java
  • 根据代码 2.63 修改 Student2.java。需要修改的代码段突出显示为 蓝色的粗体 字。
package mypacakge;

import javax.persistence.Entity;

/**
 *
 * @author sang
 */
@Entity
public class Student2 extends Person2 {
   
    String school;
    double grade;
   
    /** Creates a new instance of Student2 */
    public Student2() {
    }
   
}
代码 2.63:经过修改的 Student2.java
  • 右键单击 school 字段并选择 重构->封装字段
  • 此时将打开 封装字段 - mypackage.Student2 对话框。
  • 选中所有复选框并单击 下一步 按钮。
  • 输出 区域查看重构的预览效果。
  • 单击 执行重构 确认重构操作。
  • 现在, getSchool()/setSchool()getGrade()/setGrade() 方法已经添加到代码的末尾部分。
8. 使用 JOINED 继承策略。
  • 根据代码 2.64 修改 Person2.java。需要修改的代码段突出显示为 蓝色的粗体 字。
  • 右键单击新创建的行并选择 修复导入。(如果按 CTRL+空格键启用了代码完成功能,则不需要执行此步骤,因为 NetBeans 将自动添加导入。)
package mypacakge;

import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

/**
 * Entity class Person2
 *
 * @author sang
 */
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
public class Person2 implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
   
    private String name;
   
    /** Creates a new instance of Person2 */
    public Person2() {
    }

    /**
     * Gets the id of this Person2.
     * @return the id
     */
    public Long getId() {
        return this.id;
    }

    /**
     * Sets the id of this Person2 to the specified value.
     * @param id the new id
     */
    public void setId(Long id) {
        this.id = id;
    }

    /**
     * Returns a hash code value for the object.  This implementation computes
     * a hash code value based on the id fields in this object.
     * @return a hash code value for this object.
     */
    @Override
    public int hashCode() {
        int hash = 0;
        hash += (this.id != null ? this.id.hashCode() : 0);
        return hash;
    }

    /**
     * Determines whether another object is equal to this Person2.  The result is
     * <code>true</code> if and only if the argument is not null and is a Person2 object that
     * has the same id field values as this object.
     * @param object the reference object with which to compare
     * @return <code>true</code> if this object is the same as the argument;
     * <code>false</code> otherwise.
     */
    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof Person2)) {
            return false;
        }
        Person2 other = (Person2)object;
        if (this.id != other.id && (this.id == null || !this.id.equals(other.id))) return false;
        return true;
    }

    /**
     * Returns a string representation of the object.  This implementation constructs
     * that representation based on the id fields.
     * @return a string representation of the object.
     */
    @Override
    public String toString() {
        return "mypacakge.Person2[id=" + id + "]";
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
   
}
代码 2.64:使用 JOINED 继承策略

9. 通过实体类生成 JavaServer Faces (JSF) 页面
  • 右键单击 ORInheritanceJOINED 项目并选择 通过实体类生成 JSF 页面
  • 此时将打开 通过实体类生成 JSF 页面 对话框。
  • 单击 添加所有>>,Person2 Student2 类将移动到右侧的 选定实体类 部分。
  • 单击 下一步 按钮。
  • 此时将出现 生成的 JSF 页面和类 窗格。
  • 接受所有默认设置并点击 完成 按钮。
10. 运行应用程序
  • 右键单击 ORInheritanceJOINED 项目并选择 运行项目
  • 此时将打开浏览器。
  • 添加一些 Person2 实例和 Student2 实例。
11. 验证所创建的数据库表。

在本步骤中,我们将验证所创建的数据库表。在 JOINED 策略中,应该存在两个表,PERSON 表用于保存层次结构中的常用数据字段,STUDENT 表用于保存特定于 Student 实体的字段。
  • 展开 jdbc:derby://localhost:1527/sample [APP 上的 app]
  • 展开 。(如果 已经展开,则右键单击它并选择 刷新
  • 现在,PERSON2 和 STUDENT2 表已经创建。
  • 右键单击 PERSON2 表并选择 查看数据。注意,它只有一个 NAME 列。(如图 2.65 所示)

图 2.65:PERSON2 表
  • 右键单击 STUDENT2 表并选择 查看数据。
  • 它含有 SCHOOL 和 GRADE 列。(如图 2.66 所示)

图2.66:SCHOOL2 表

                                                                                                          返回练习顶部

解决方案


针对此练习的解决方案作为可运行的 NetBeans 项目包含在动手实验室的压缩文件中。
  • ORInheritanceSINGLE_TABLE 项目位于 <LAB_UNZIPPED_DIRECTORY>/jpamapping/solutions/ORInheritanceSINGLE_TABLE
  • ORInheritanceJOINED 项目位于 <LAB_UNZIPPED_DIRECTORY>/jpamapping/solutions/ORInheritanceJOINED

结束语


在本练习中,我们学习了如何使用继承策略以及如何创建相应的数据库表。在 SINGLE_TABLE 策略中,只会为类层次结构创建一个表。

                                                                                                                    返回顶部


课外练习(针对 Sang Shin“Java EE 编程在线课程”的学习者)


1. 课外练习是根据以下要求修改 ORInheritanceJOINED 项目。(可以通过复制 ORInheritanceJOINED 来创建一个新项目 。您可以将该项目命名为任意名称,此处我将使用 MyORInheritanceJOINED。)
  • Person2 实体类中再添加一个名称为 Teacher2 的子类。
  • 将以下两个字段添加到 Teacher2 类中。
    • String subjectToTeach      // Subject he or she teaches
    • int years                            // Number of years he or she have taught

2. J2EEHomework-jpamapping 项目中的文件发送到 j2eehomeworks@sun.com
  • MyORInheritanceJOINED NetBeans 项目的压缩文件。。(其他人应该能够打开它,并能将它作为 NetBeans 项目运行。)您可以使用任意压缩工具,也可以使用 JDK 提供的 jar 实用工具,使用方法如下所示:
    • cd <parent directory that contains MyORInheritanceJOINED directory> (假设您将项目命名为 MyORInheritanceJOINED
    • jar cvf MyORInheritanceJOINED.zip MyORInheritanceJOINED (MyORInheritanceJOINED 应该包含 nbproject 目录)
  • 抓取输出屏幕 - 将它命名为 J2EEHomework-jpamapping.gifJ2EEHomework-jpamapping.jpg (或 J2EEHomework-jpamapping。<任意图像格式都可>
    • 抓取的屏幕截图只需显示程序正常运行即可。
  • 如果决定使用 NetBeans 之外的其他 IDE,则压缩文件应该包含重新编译项目所需的所有文件(含有所需源文件的 War 文件也可以)。

原文链接: http://www.javapassion.com/handsonlabs/jpamapping/

Comments:

Post a Comment:
  • HTML Syntax: NOT allowed

Calendar

Feeds

Search

Links

Navigation

Referrers