-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 
Author Message
 Post subject: Null value retrieved for non-id attribute from a proxy.
PostPosted: Wed Mar 19, 2008 5:55 am 
Newbie

Joined: Mon Aug 27, 2007 2:43 am
Posts: 8
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.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 19, 2008 7:34 am 
Senior
Senior

Joined: Tue Jul 25, 2006 9:05 am
Posts: 163
Location: Stuttgart/Karlsruhe, Germany
Hi,

In you SubjectDAO could you not just use a join fetch between Subject and Exam, this will eagerly load the exam.

Cheers,

Andy

_________________
Rules are only there to be broken


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 19, 2008 9:09 am 
Newbie

Joined: Mon Aug 27, 2007 2:43 am
Posts: 8
Accessing the Exam associated to the Subject appears to be more intuitive than writing a separate join query to achieve the same.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 20, 2008 12:54 am 
Newbie

Joined: Mon Aug 27, 2007 2:43 am
Posts: 8
I modified the Subject class to add @LazyToOne(LazyToOneOption.FALSE) or @Fetch(FetchMode.JOIN) annotation around the exam attribute. Clearly this works because the annotations override the lazy loading behavior of Exam and do not create a proxy for the Exam class.

I want it to work with the lazy loading behavior. Can somebody from the Hibernate team explain this behavior and why the code is not able to retrieve values from the proxy class?

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)
  @LazyToOne(LazyToOneOption.FALSE)
//  @Fetch(FetchMode.JOIN)
  @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;
}
}


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 24, 2008 8:01 am 
Newbie

Joined: Mon Nov 05, 2007 11:08 am
Posts: 4
I am also facing the same problem...., Kindly suggest the solution


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.