休眠ManyToMany:在两个表中都不会插入相同的ID

时间:2018-10-08 09:00:05

标签: java oracle hibernate

我使用Hibernate和Oracle数据库建立了(经典的)多对多关系。

我对实体的定义如下。

Student.java

@Entity
@Table
public class Student implements Serializable {

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name = "STUDENT_ID")
private Long studentId;

@ManyToMany
@JoinTable(name = "STUDENT_PROJECT", joinColumns = {
        @JoinColumn(name = "STUDENT_ID") }, inverseJoinColumns = {
                @JoinColumn(name = "PROJECT_ID") })
private Set<Project> projects = new HashSet<>();

Project.java

@Entity
@Table
public class Project implements Serializable {

@Id
@Column(name="PROJECT_ID")
private int projectId;

@ManyToMany(mappedBy="projects")
private Set<Student> students = new HashSet<>();

我的oracle数据库中有一个STUDENT_PROJECT表,该表由两个字段PROJECT_IDSTUDENT_ID组成,上面有一个composite primary key

我在STUDENT表上有一个序列可以自动生成其ID

TRIGGER STUDENT_TRIGGER
BEFORE INSERT ON STUDENT
FOR EACH ROW

BEGIN
 SELECT STUDENT_SEQUENCE.NEXTVAL
 INTO   :STUDENT_ID
 FROM   dual;
END;

现在,我的问题是,当我尝试保留Student实体时,ID表的STUDENT字段与{ {1}}表。

它以某种方式在映射表中保留了Student的ID和另一个ID,我不知道为什么。

这就是我操纵对象的方式

STUDENT_ID

我不得不删除STUDENT_PROJECT的{​​{1}}上 Student student = new Student(); // set some fields Set<Project> projects = new HashSet<>(); // call to a private method to set its projects student.setProjects(projects); studentDao.persist(student); 表中的foreign key(否则约束当然不会让我省钱),最后注意到那是在设置STUDENT_PROJECT的不同之处,但我不明白为什么。

如果您需要更多信息,请告诉我,我试图将其尽量缩小,谢谢。

更新:

我试图删除ID表上的触发器并将其Java配置更改为

STUDENT

我现在得到: ID

它根本不会保存到数据库,并在STUDENT上产生上述异常,我想我的序列有问题,因为它似乎试图使用相同的@Id @GeneratedValue(strategy = GenerationType.AUTO, generator = "G1") @SequenceGenerator(name = "G1", sequenceName= "STUDENT_SEQUENCE") @Column(name = "STUDENT_ID") private Long studentId; (我正在循环保存多个学生及其项目)。

javax.persistence.EntityExistsException: A different object with the same identifier value was already associated with the session : [fr.persistance.data.Student#3037]调用之后,我使用了eclipse调试来检查我的一些persist()对象,它们在Java中具有不同的Student,但是一旦循环和事务结束,就会发生例外,但似乎他们每个人都有一个单独的ID。

1 个答案:

答案 0 :(得分:0)

问题在于,学生的ID是由数据库在触发器中生成的,而Hibernate会尝试自己创建值。

对于oracle数据库,GenerationType.AUTO将使用一个序列。 Hibernate访问该序列,该序列分配值(在将学生实际插入数据库之前)。

要使Hibernate使用您的序列,请添加

@SequenceGenerator(name = "sequence-generator", sequenceName = "STUDENT_SEQUENCE")

并删除触发器。

当您要使用触发器时,需要将其映射为GenerationType.IDENTITY。 (不过不推荐。)