Hibernate 有时不提取 uuid 引用的实体
Hibernate sometimes doesn't extract uuid referenced entity
我有两个实体,我们将它们命名为 University
和 Student
,Student
是单向的 ManyToOne
和 University
它们都扩展了基础 class BasicUUIDEntity
:
@MappedSuperclass
public class BasicUUIDEntity implements Serializable {
protected UUID id;
@Id
@Column(name = "id", columnDefinition = "binary(16)")
@GeneratedValue(generator = "uuid2")
@GenericGenerator(name = "uuid2", strategy = "uuid2")
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
BasicUUIDEntity that = (BasicUUIDEntity) o;
return id == null || id.equals(that.id);
}
@Override
public int hashCode() {
return id != null ? id.hashCode() : 0;
}
}
Student
和University
的结构并不重要,重要的是:
Student.class:
@Entity
@Table(name = "students")
public static class Student extends BasicUUIDEntity {
private University univ;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "univ_id", referencedColumnName = "id")
public University getUniversity() {
return univ;
}
public void setUniversity(University univ) {
this.univ = univ;
}
}
University.class:
@Entity
@Table(name = "universities")
public static class University extends BasicUUIDEntity {
//of course it does contain some fields, but they are strings, etc.
}
table的创建方式如下:
CREATE TABLE students
(
id BINARY(16) NOT NULL,
univ_id BINARY(16),
PRIMARY KEY (id),
CONSTRAINT FK_STUDENT_UNIV
FOREIGN KEY (univ_id) REFERENCES memory_type (id)
ON DELETE SET NULL
)
ENGINE = InnoDB
DEFAULT CHARSET = utf8;
CREATE TABLE universities
(
id BINARY(16) NOT NULL,
PRIMARY KEY (id)
)
ENGINE = InnoDB
DEFAULT CHARSET = utf8;
问题有时是,在极少数情况下,Hibernate 不会将 University
实体与 Student
一起提取,这意味着当我 student.getUniversity()
它 return s null
,在调试器中也是null
。但是 students
table 包含与此 student
的预期 University
完全相同的 univ_id
,大学也包含 id
。我完全确定 hibernate 会话没有关闭,并且我尝试执行与 hibernate 完全相同的查询,并且它确实 return expected id
of the university,加入他们等等。事情是大多数时候它确实运行良好,并且由于未知原因这种问题很少发生,更奇怪的是 table 确实包含该 ID,所以它似乎不是 MySQL 问题。
另外值得一提的是,我正在使用 Spring Data JPA。
有没有人遇到过这种行为?难道是因为 Inheritance/Data JPA/Java 9/还有其他原因吗?
PS。
请忽略代码中的任何错字,这只是一个例子
版本:
Hibernate: 5.2.12.Final,
Spring Data JPA: 2.0.5.RELEASE,
HikariCP: 2.7.8,
MySQL connector: 6.0.6,
Java: 9
MySQL: Ver 14.14 Distrib 5.7.21
终于解决了
tl;dr
将 fetch = FetchType.LAZY
与 ManyToOne
关系,所以在我的示例中它变为:
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "univ_id", referencedColumnName = "id")
public University getUniversity() {
return univ;
}
描述
我仍然不确定它为什么会这样,但似乎 Hibernate 根本不提取 many-to-one
关系,如果它们很急切的话。它有一定的意义,因为这样会有循环依赖,但我认为 PersistenceSet
会处理这样的问题。更奇怪的是 - 如果我使用 Long 而不是 UUID,实际上相同的结构无需急切提取即可工作。
我有两个实体,我们将它们命名为 University
和 Student
,Student
是单向的 ManyToOne
和 University
它们都扩展了基础 class BasicUUIDEntity
:
@MappedSuperclass
public class BasicUUIDEntity implements Serializable {
protected UUID id;
@Id
@Column(name = "id", columnDefinition = "binary(16)")
@GeneratedValue(generator = "uuid2")
@GenericGenerator(name = "uuid2", strategy = "uuid2")
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
BasicUUIDEntity that = (BasicUUIDEntity) o;
return id == null || id.equals(that.id);
}
@Override
public int hashCode() {
return id != null ? id.hashCode() : 0;
}
}
Student
和University
的结构并不重要,重要的是:
Student.class:
@Entity
@Table(name = "students")
public static class Student extends BasicUUIDEntity {
private University univ;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "univ_id", referencedColumnName = "id")
public University getUniversity() {
return univ;
}
public void setUniversity(University univ) {
this.univ = univ;
}
}
University.class:
@Entity
@Table(name = "universities")
public static class University extends BasicUUIDEntity {
//of course it does contain some fields, but they are strings, etc.
}
table的创建方式如下:
CREATE TABLE students
(
id BINARY(16) NOT NULL,
univ_id BINARY(16),
PRIMARY KEY (id),
CONSTRAINT FK_STUDENT_UNIV
FOREIGN KEY (univ_id) REFERENCES memory_type (id)
ON DELETE SET NULL
)
ENGINE = InnoDB
DEFAULT CHARSET = utf8;
CREATE TABLE universities
(
id BINARY(16) NOT NULL,
PRIMARY KEY (id)
)
ENGINE = InnoDB
DEFAULT CHARSET = utf8;
问题有时是,在极少数情况下,Hibernate 不会将 University
实体与 Student
一起提取,这意味着当我 student.getUniversity()
它 return s null
,在调试器中也是null
。但是 students
table 包含与此 student
的预期 University
完全相同的 univ_id
,大学也包含 id
。我完全确定 hibernate 会话没有关闭,并且我尝试执行与 hibernate 完全相同的查询,并且它确实 return expected id
of the university,加入他们等等。事情是大多数时候它确实运行良好,并且由于未知原因这种问题很少发生,更奇怪的是 table 确实包含该 ID,所以它似乎不是 MySQL 问题。
另外值得一提的是,我正在使用 Spring Data JPA。
有没有人遇到过这种行为?难道是因为 Inheritance/Data JPA/Java 9/还有其他原因吗?
PS。 请忽略代码中的任何错字,这只是一个例子
版本:
Hibernate: 5.2.12.Final,
Spring Data JPA: 2.0.5.RELEASE,
HikariCP: 2.7.8,
MySQL connector: 6.0.6,
Java: 9
MySQL: Ver 14.14 Distrib 5.7.21
终于解决了
tl;dr
将 fetch = FetchType.LAZY
与 ManyToOne
关系,所以在我的示例中它变为:
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "univ_id", referencedColumnName = "id")
public University getUniversity() {
return univ;
}
描述
我仍然不确定它为什么会这样,但似乎 Hibernate 根本不提取 many-to-one
关系,如果它们很急切的话。它有一定的意义,因为这样会有循环依赖,但我认为 PersistenceSet
会处理这样的问题。更奇怪的是 - 如果我使用 Long 而不是 UUID,实际上相同的结构无需急切提取即可工作。