I have tried to give a hypothetical example for the actual problem. Consider 3 classes Student, Subject and Exam. Such that Student has a one to one relationship with Exam. And Subject has a bidirectional many to one with Exam.
The code with the JPA/Hibernate/Spring annotations is as follows -
Student class:
Code:
@Entity
@Table(name = "STUDENT", schema = "ME", uniqueConstraints = {})
@SequenceGenerator(
name = "SEQ_STORE",
sequenceName = "ME.HIBERNATE_SEQUENCE")
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_STORE")
@Column(name = "STUDENT_ID", unique = true, nullable = false, insertable = true, updatable = true, precision = 22, scale = 0)
private Long studentId;
@OneToOne(cascade = {}, fetch = FetchType.LAZY)
@LazyToOne(LazyToOneOption.NO_PROXY)
@JoinColumn(name = "EXAM_NAME", unique = false, nullable = false, insertable = true, updatable = true, referencedColumnName = "EXAM_NAME")
private Exam exam;
public Long getStudentId() {
return studentId;
}
public void setStudentId(Long studentId) {
this.studentId = studentId;
}
public Exam getExam() {
return exam;
}
public void setExam(Exam exam) {
this.exam = exam;
}
}
Subject class:Code:
@Entity
@Table(name = "SUBJECT", schema = "ME")
public class Subject {
@Id
@Column(name = "SUBJECT_ID", unique = true, nullable = false, insertable = true, updatable = true)
private Long subjectId;
@Column(name = "SUBJECT_NAME", unique = false, nullable = false)
private String subjectName;
@ManyToOne(cascade = {}, fetch = FetchType.LAZY)
@JoinColumn(name = "EXAM_ID", unique = false, nullable = false, insertable = true, updatable = true)
private Exam exam;
public Long getSubjectId() {
return subjectId;
}
public void setSubjectId(Long subjectId) {
this.subjectId = subjectId;
}
public String getSubjectName() {
return subjectName;
}
public void setSubjectName(String subjectName) {
this.subjectName = subjectName;
}
public Exam getExam() {
return exam;
}
public void setExam(Exam exam) {
this.exam = exam;
}
}
Exam class:Code:
@Entity
@Table(name = "EXAM", schema = "ME")
public class Exam {
@Id
@Column(name = "EXAM_ID", unique = true, nullable = false, insertable = true, updatable = true)
private Long examId;
@Column(name = "EXAM_NAME")
private String examName;
@OneToMany(cascade = {CascadeType.ALL}, fetch = FetchType.LAZY, mappedBy = "exam")
private Set<Subject> subject = new HashSet<Subject>();
public Long getExamId() {
return examId;
}
public void setExamId(Long examId) {
this.examId = examId;
}
public Set<Subject> getSubject() {
return subject;
}
public void setSubject(Set<Subject> subject) {
this.subject = subject;
}
public String getExamName() {
return examName;
}
public void setExamName(String examName) {
this.examName = examName;
}
}
Test class:Code:
public class Work {
@Transactional
public void work(ClassPathXmlApplicationContext ctx) {
Student t = new Student();
SubjectDAO sDao = (SubjectDAO)ctx.getBean("subjectDAO");
List<Subject> subjectList = sDao.findByName("Management");
Exam exam = subjectList.get(0).getExam();
System.out.println(exam.getExamName());//prints the exam name.
t.setExam(exam);
StudentDAO tDao = (StudentDAO)ctx.getBean("studentDAO");
tDao.save(t);
}
}
My business logic requires me to query the subject and get the exam from it and set it to the student object before persisting the student.
As per the mapping, I expect the not nullable EXAM_NAME column to be inserted into the STUDENT table.
But the problem seems to be that while dehydrating (or binding values with the prepared statement) the org.hibernate.tuple.component.AbstractComponentTuplizer. getPropertyValue(..) method is unable to retrieve the value of examName from the
Exam proxy class (created for the lazy loading from Subject) .
This results in SQLException.
Will be grateful for any suggestions.