我使用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_ID
和STUDENT_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。
答案 0 :(得分:0)
问题在于,学生的ID是由数据库在触发器中生成的,而Hibernate会尝试自己创建值。
对于oracle数据库,GenerationType.AUTO
将使用一个序列。 Hibernate访问该序列,该序列分配值(在将学生实际插入数据库之前)。
要使Hibernate使用您的序列,请添加
@SequenceGenerator(name = "sequence-generator", sequenceName = "STUDENT_SEQUENCE")
并删除触发器。
当您要使用触发器时,需要将其映射为GenerationType.IDENTITY
。 (不过不推荐。)