Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate hql inner join eager fetch on one to many, fetching redundant parent objects

Tags:

java

hibernate

I have entities as follows

Class ProgressNote

@Entity
public class ProgressNote implements Serializable{

    @Id
    private NotesKey notesKey = new NotesKey();

    private Set<PatientObjective> patientObjectives;

    public NotesKey getNotesKey() {
        return notesKey;
    }
    public void setNotesKey(NotesKey notesKey) {
        this.notesKey = notesKey;
    }


    @OneToMany(fetch=FetchType.LAZY)
    @Access(AccessType.PROPERTY)
    @JoinColumns({
        @JoinColumn(name="noteNumber",referencedColumnName="noteNumber"),
        @JoinColumn(name="ddate",referencedColumnName="ddate"),
        @JoinColumn(name="patient_id",referencedColumnName="patient_id")
    })
    public Set<PatientObjective> getPatientObjectives() {
        return patientObjectives;
    }
    public void setPatientObjectives(Set<PatientObjective> patientObjectives) {
        this.patientObjectives = patientObjectives;
    }


}

Class NotesKey

@Embeddable
public class NotesKey implements Serializable{

    private Byte noteNumber;

    @Temporal(javax.persistence.TemporalType.DATE)
    @Column(name="ddate")
    private Date noteDate;

    private Patient patient;

    public Byte getNoteNumber() {
        return noteNumber;
    }

    public void setNoteNumber(Byte noteNumber) {
        this.noteNumber = noteNumber;
    }

    public Date getNoteDate() {
        return noteDate;
    }

    public void setNoteDate(Date noteDate) {
        this.noteDate = noteDate;
    }

    @ManyToOne(fetch=FetchType.LAZY)
    @Access(AccessType.PROPERTY)
    public Patient getPatient() {
        return patient;
    }

    public void setPatient(Patient patient) {
        this.patient = patient;
    }

    @Override
    public int hashCode() {
        ........
    }

    @Override
    public boolean equals(Object obj) {
        ........
    }

}

Class PatientObjective

@Entity
public class PatientObjective implements Serializable{

    @Id
    private PatientObjectiveKey patientObjectiveKey;


    public PatientObjectiveKey getPatientObjectiveKey() {
        return patientObjectiveKey;
    }
    public void setPatientObjectiveKey(PatientObjectiveKey patientObjectiveKey) {
        this.patientObjectiveKey = patientObjectiveKey;
    }

}

Class PatientObjectiveKey

@Embeddable
public class PatientObjectiveKey implements Serializable{

    private Objective objective;

    private Byte noteNumber;

    @Temporal(javax.persistence.TemporalType.DATE)
    @Column(name="ddate")
    private Date noteDate;

    private Patient patient;

    @ManyToOne(fetch=FetchType.LAZY)
    @Access(AccessType.PROPERTY)
    public Objective getObjective() {
        return objective;
    }

    public void setObjective(Objective objective) {
        this.objective = objective;
    }

    public Byte getNoteNumber() {
        return noteNumber;
    }

    public void setNoteNumber(Byte noteNumber) {
        this.noteNumber = noteNumber;
    }

    public Date getNoteDate() {
        return noteDate;
    }

    public void setNoteDate(Date noteDate) {
        this.noteDate = noteDate;
    }

    @ManyToOne(fetch=FetchType.LAZY)
    @Access(AccessType.PROPERTY)
    public Patient getPatient() {
        return patient;
    }

    public void setPatient(Patient patient) {
        this.patient = patient;
    }

    @Override
    public int hashCode() {
        .......
    }

    @Override
    public boolean equals(Object obj) {
        ........
    }

}

After I use this named query

@NamedQuery(name = "findAllProgressNoteWithObjective", query = "from ProgressNote p inner join fetch p.patientObjectives as o where p.notesKey.patient.id = :patientId)") using spring hibernate template findByNamedQueryAndNamedParam

In table I have 2 ProgressNotes with one having single Objective and other having 17 Objectives. I get the result in Java as follows.

Debug Information From Eclipse

Query Generated as

select progressno0_.ddate as ddate46_0_, progressno0_.noteNumber as noteNumber46_0_, progressno0_.patient_id as patient17_46_0_, patientobj1_.ddate as ddate36_1_, patientobj1_.noteNumber as noteNumber36_1_, patientobj1_.objective_id as objective5_36_1_, patientobj1_.patient_id as patient6_36_1_, progressno0_.assessment as assessment46_0_, progressno0_.bloodPressure1 as bloodPre4_46_0_, progressno0_.bloodPressure2 as bloodPre5_46_0_, progressno0_.creationDate as creation6_46_0_, progressno0_.height as height46_0_, progressno0_.lastUpdatedDate as lastUpda8_46_0_, progressno0_.plans as plans46_0_, progressno0_.status as status46_0_, progressno0_.subject as subject46_0_, progressno0_.temprature as temprature46_0_, progressno0_.tempratureUnit as temprat13_46_0_, progressno0_.lastid as lastid46_0_, progressno0_.waist as waist46_0_, progressno0_.weight as weight46_0_, progressno0_.weightUnit as weightUnit46_0_, patientobj1_.remark as remark36_1_, patientobj1_.value as value36_1_, patientobj1_.ddate as ddate46_0__, patientobj1_.noteNumber as noteNumber46_0__, patientobj1_.patient_id as patient6_46_0__, patientobj1_.ddate as ddate0__, patientobj1_.noteNumber as noteNumber0__, patientobj1_.objective_id as objective5_0__, patientobj1_.patient_id as patient6_0__ from pnheader progressno0_ inner join pnobjremark patientobj1_ on progressno0_.ddate=patientobj1_.ddate and progressno0_.noteNumber=patientobj1_.noteNumber and progressno0_.patient_id=patientobj1_.patient_id where progressno0_.patient_id=? 

Question

Problem I see is why I am getting multiple single instance of ProgressNote(id=152).Is there a way I can avoid this duplication?

I'll really appreciate if someone explains or points me in right direction.

Using Hibernate 3.6, Mysql 5.6.10

like image 829
baba.kabira Avatar asked Apr 19 '13 05:04

baba.kabira


1 Answers

Use distinct:

select distinct p from ProgressNote p 
inner join fetch p.patientObjectives as o 
where p.notesKey.patient.id = :patientId)
like image 151
JB Nizet Avatar answered Nov 05 '22 06:11

JB Nizet