6

In a spring mvc application using hibernate and MySQL, I am getting an error which seems to indicate that a Name entity cannot find the setter for the id property of the BaseEntity superclass of the Patient entity.

How can I resolve this error?

Here is the error message:

Caused by: org.hibernate.PropertyAccessException: could not set a field value by  
reflection setter of myapp.mypackage.Name.patient

Here is the line of code that triggers the error:

ArrayList<Name> names = (ArrayList<Name>) this.clinicService.findNamesByPatientID(patntId);

Here is the BaseEntity, which is the superclass of both Patient and Name:

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@DiscriminatorFormula("(CASE WHEN dtype IS NULL THEN 'BaseEntity' ELSE dtype END)")
public class BaseEntity {

    @Transient
    private String dtype = this.getClass().getSimpleName();

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    protected Integer id;

    public void setId(Integer id) {this.id = id;}
    public Integer getId() {return id;}

    public void setDtype(String dt){dtype=dt;}
    public String getDtype(){return dtype;}

    public boolean isNew() {return (this.id == null);}

}

Here is the Patient entity:

@Entity
@Table(name = "patient")
public class Patient extends BaseEntity{

    @OneToMany(mappedBy = "patient")
    private Set<Name> names;

    protected void setNamesInternal(Set<Name> nms) {this.names = nms;}

    protected Set<Name> getNamesInternal() {
        if (this.names == null) {this.names = new HashSet<Name>();}
        return this.names;
    }

    public List<Name> getNames() {
        List<Name> sortedNames = new ArrayList<Name>(getNamesInternal());
        PropertyComparator.sort(sortedNames, new MutableSortDefinition("family", true, true));
        return Collections.unmodifiableList(sortedNames);
    }

    public void addName(Name nm) {
        getNamesInternal().add(nm);
        nm.setPatient(this);
    }

    //other stuff
}

Here is the Name entity:

@Entity
@Table(name = "name")
public class Name extends BaseEntity{

    @ManyToOne
    @JoinColumn(name = "patient_id")
    private Patient patient;

    public Patient getPatient(){return patient;}
    public void setPatient(Patient ptnt){patient=ptnt;}

//other stuff

}

The complete stack trace can be viewed at this link.

The SQL generated by Hibernate for the above query is:

select distinct hl7usname0_.id as id1_0_0_, givennames1_.id as id1_45_1_,  
hl7usname0_.family as family1_44_0_, hl7usname0_.patient_id as patient3_44_0_,
hl7usname0_.person_id as person4_44_0_, hl7usname0_.suffix as suffix2_44_0_,  
hl7usname0_.usecode as usecode5_44_0_, hl7usname0_.codesystem as codesyst6_44_0_,  
givennames1_.given as given2_45_1_, givennames1_.name_id as name3_45_1_,  
givennames1_.name_id as name3_0_0__, givennames1_.id as id1_45_0__  
from hl7_usname hl7usname0_  
left outer join hl7_usname_given givennames1_ on hl7usname0_.id=givennames1_.name_id  
where hl7usname0_.patient_id=1

When I run this query through the MySQL command line client, it returns the only record in the test database table.

CodeMed
  • 9,527
  • 70
  • 212
  • 364
  • What does the full stack trace look like? For this particular error message, there is usually a more precise, granular error at the lower half of the stack trace. – ivan.sim Aug 13 '14 at 20:50
  • @isim I have a similar question. Are you willing to help me with it? Here is the link: http://stackoverflow.com/questions/25316761/duplicate-entry-string1-string2-for-key-primary – CodeMed Aug 14 '14 at 20:48

1 Answers1

3

That's not what the stack trace says. The stack trace doesn't say that the ID can't be set. It says:

Caused by: java.lang.IllegalArgumentException: Can not set org.springframework.samples.knowledgemanager.model.HL7Patient field org.springframework.samples.knowledgemanager.model.HL7USName.patient to org.springframework.samples.knowledgemanager.model.HL7USName

So, your HL7USName class has a field named patient of type HL7Patient, and it's impossible to set this field with a value of type HL7USName.

This means that your database contains a Name that has a foreign key to a row of type Name instead of a row of type Patient.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • No. I managed to make this translation by myself. Have you read my answer? – JB Nizet Aug 13 '14 at 21:08
  • @JB You beat me to it ;) – ivan.sim Aug 13 '14 at 21:09
  • Your entity says that a Name has a Patient. In the table "name", you have a column named "patient_id". This column is thus supposed to contain the ID of a patient. But at least one row has the ID of another name in this column. – JB Nizet Aug 13 '14 at 21:12
  • Patient and Name are both instances of the entity BaseEntity. Suppose you call `session.get(BaseEntity.class, 1)`. What should Hibernate return? The patient or the name? They both have the same ID. That is invalid. Since they are both BaseEntity instances, a Name may not have the same ID as a Patient. Why is BaseEntity an `@Entity`, and not a `@MappedSuperclass`? – JB Nizet Aug 13 '14 at 21:31
  • Then your entities may not have identical IDs. An ID is supposed to uniquely identify an entity. – JB Nizet Aug 13 '14 at 21:45
  • They shouldn't have an auto-increment, since their ID is supposed to be generated from the sequence number stored in the table used by `GenerationType.TABLE`. Use this table in your scripts as well, or a counter, or whatever, but make sure IDs don't conflict. – JB Nizet Aug 13 '14 at 21:52
  • @JBNizet I added a second edit with more code to my similar posting. I am trying to understand how hibernate manages manytoone relationships. Are you willing to help me with it? Here is the link: http://stackoverflow.com/questions/25316761/duplicate-entry-string1-string2-for-key-primary – CodeMed Aug 15 '14 at 20:36