I have two entities, let's name them University
and Student
, Student
is unidirectional ManyToOne
with University
they both extends base 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;
}
}
The structure of Student
and University
doesn't really matters, the important things is:
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.
}
The tables are created as follows:
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;
The Issue is sometimes, on really rare occasions Hibernate doesn't extract that University
entity along with Student
, meaning that when I do student.getUniversity()
it returns null
, and in debugger it is also null
. BUT the students
table contains exactly the same univ_id
as expected University
of this student
, and so does university contains that id
. I am completely sure that hibernate session is not closed, and I've tried to execute exactly the same query as hibernate does, and it does return expected id
of the university, joins them, etc. The thing is that most of the time It does work well, and such issue happens very rarely due to unknown reasons, what is more strange is that the table does contains that id, so it seems like it is not an MySQL issue.
Also worth mention, I am using Spring Data JPA.
Have anyone encountered such behavior? Could it be due to Inheritance/Data JPA/Java 9/Anything other?
PS. Please ignore any typo in the code, it is just an example
Versions:
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
Solved, finally
tl;dr
Put fetch = FetchType.LAZY
to ManyToOne
relation, so in my example it becomes:
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "univ_id", referencedColumnName = "id")
public University getUniversity() {
return univ;
}
Description
I am not still sure why it behaves like this, but it seems that Hibernate does not extract many-to-one
relations at all, if they're eager. It have some sense as this way there will be circular dependencies, but I thought that PersistenceSet
will deal with such issues. What is even more strange - just the same structure actually works without eager extraction if I use Long instead of UUID.