I have a project where every Student can be tested by a Tester, and a single tester can test many students.
I need students to know their testers - so this is a unidirectional Many to One.
Tester:
@Entity
public class Tester
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String name;
public Tester(String name)
{
this.name = name;
}
protected Tester(){}
public String getName()
{
return this.name;
}
@Override
public String toString()
{
return String.format("Tester [id=%s, name=%s]", this.id, this.name);
}
}
Student:
@Entity
public class Student
{
@Id
private Long id; //this shouldn't be auto incremented
@Column(nullable = false)
private int age;
@ManyToOne(cascade = CascadeType.PERSIST)
@JoinColumn(name = "tester_id")
private Tester tester;
public Student(Long id, int age, Tester tester)
{
this.id = id;
this.age = age;
this.tester = tester;
}
protected Student(){}
public int getAge()
{
return this.age;
}
public Tester getTester()
{
return this.tester;
}
@Override
public String toString()
{
return String.format("Student [id=%s, age=%s, tester=%s]", this.id, this.age, this.tester);
}
}
When I run this code:
Tester tester = new Tester("Tester");
Student student = new Student(1L, 27, tester);
this.studentRepository.save(student);
I expect both entities to be saved due to the cascade, but instead I get an sql error because the tester's name is magically null?!?
If I remove the nullable = false from the column, the tester entity is saved but with null in the name column...
What the hell did I do wrong?
Please don't recommend saving the Tester first, it's not helping because I want to understand what's wrong with my code.
Answer from comment. As per the Spring docs, the student is assumed to already exist as it has an id:
This can be fixed by adding a version column or by using a @Transient flag that controls if the entity is new or not (described in more detail in the linked document).
Alternatively, the entity manager's persist method can be used without Spring.