【问题标题】:Auto-generate person_id and student_id for SINGLE_TABLE inheritance model为 SINGLE_TABLE 继承模型自动生成 person_id 和 student_id
【发布时间】:2012-01-07 23:23:46
【问题描述】:

我有两个实体personStudent,学生实体扩展了person 并有自己的标识符studentNumber。创建新学生时,我想自动生成两个识别号。

以下 sn-p 失败:person_id 为 NULL

@RooEntity(identifierColumn = "personID", inheritanceType = "SINGLE_TABLE")
@DiscriminatorColumn(name = "TYPE", discriminatorType = DiscriminatorType.STRING, length = 20)
@DiscriminatorValue("P")
public class Person {
}

学生实体

@RooEntity
@DiscriminatorValue("S")
public class Student extends Person {


    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "studentNumber") 
    private long studentNumber;
}

这里是我创建一个新学生并生成了学号但没有生成 personid 的地方?

    private Student student;

    /**
     * @method Create a new student using our persistence model---Not Null variables
     */

    public void CreateNewStudent(String firstName, String lastName, String telephone, Date birthday, GenderType gender){


        student = new Student();
        //set our variables and persist
        student.setFirstName(firstName);
        student.setLastName(lastName);
        student.setTelephone(telephone);
        student.setBirthDay(birthday);
        student.setGender(gender);

        student.persist();
    }
}

有什么方法可以在创建学生时同时创建 studentNumber 和 personID?

【问题讨论】:

  • 我质疑这个设计。为什么在使用单表继承时,父表和派生表都有主键?请显示您的架构。
  • 学号并不是真正标识某条记录,它是一个代表学生身份的数字,person id应该是唯一的主键
  • 嗯,有道理,请参阅下面的答案,了解解决问题的一种方法。

标签: java jpa persistence eclipselink auto-generate


【解决方案1】:

根据您的后续 cmets,您希望拥有一个主键标识符 Person 和一个唯一标识符 Student。请注意,在您当前的设置下,只能自动生成一个键(许多 DBMS 只允许每个表的一列自动递增)。所以我建议您首先为Person 定义主键列:

@Entity
@Table(name="person")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="TYPE", discriminatorType=DiscriminatorType.STRING,length=20)
@DiscriminatorValue("P")
public class Person {
    @Basic
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="personId")
    private Long id;
}

请注意,在您的数据库中,您需要将 personId 列作为自动增量。然后为您的学号定义一个单独的生成值注释。我在下面展示的示例使用了一个表格生成器,但你可以做任何你想做的事情:

@Entity
@DiscriminatorValue("S")
public class Student extends Person {
   @Basic
   @TableGenerator(name="ID_GEN", table="identifier_table", pkColumnName="seq_name",
        valueColumnName="seq_count", pkColumnValue="student_seq")
   @GeneratedValue(strategy = GenerationType.TABLE, generator = "ID_GEN")
   @Column(name = "studentNumber")
   private Long studentNumber;
}

在上面的示例中,您需要支持为学生生成序列号的表的 DDL:

create table identifier_table (
  id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  seq_name VARCHAR(255) NOT NULL,
  seq_count INT NOT NULL DEFAULT 0
);

您最初会使用以下内容填充它:

insert into identifier_table (seq_name, seq_count) VALUES ('student_seq', 0);

当然,更简单的解决方案是将您的学生标识符声明为字符串,然后您可以执行以下更简单的设置:

public class Student extends Person {
    @Basic
    @NotNull
    @Column(name = "studentId")
    private String studentIdentifier;
}

并在保存每条记录之前,将学生 ID 设置为 UUID 类:

aStudent.setStudentIdentifier(UUID.randomUUID().toString());

希望这会有所帮助。

【讨论】:

  • 对于使用 UUID.randUUID() 创建学生标识符的更简单的解决方案,这真的是独一无二的吗?有没有办法我可以从一个随机数 ex.10000 开始,然后对于添加到 person 表的每个新学生,增加 1?
  • 您可以在 Oracle javadoc 页面 - docs.oracle.com/javase/6/docs/api/java/util/UUID.html 上阅读有关 UUID 的更多信息。但我只想说,它非常该死的独一无二。全球范围内。
  • 最后一件事,如果我更改我的 createNewStudent() 方法以创建不是一个人而是一个学生实体,我的数据库不应该为你提到的学生实体生成一个 id 吗?
  • 是的,只要您在数据库中将personId 列定义为自动递增即可。最后一件事我忘了提。不要将 studentId 数据库字段设置为 NOT NULL,因为从概念上讲,您将在表中存储可能不是学生的其他记录。而且您不想在这种情况下设置 studentId 列。
【解决方案2】:

我认为您目前只能拥有一个 GenerateValue。如果你想要两个,你要么不需要使用继承,即 Person 有一个 1-1 到 StudentInfo,或者你可以在事件中或从你的应用程序中分配另一个 id。 EclipseLink Session 上有一个 API 可以获取新生成的 id。

【讨论】:

猜你喜欢
  • 2011-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-31
  • 2017-12-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多