11

I seem to be getting this error and have no idea why I'm getting this error. I don't even understand why Hibernate needs that getter for the User class because it's not supposed to be doing any actions with that class directly anyway...

2012-12-30 09:38:56,713 [main] ERROR org.hibernate.property.BasicPropertyAccessor$BasicGetter - HHH000122: IllegalArgumentException in class: com.nortal.pirs.datamodel.User, getter method of property: idUser 2012-12-30 09:38:56,714 [main] ERROR com.nortal.pirs.businesslogic.logic.VisitManagerLogic - IllegalArgumentException occurred calling getter of com.nortal.pirs.datamodel.User.idUser java.lang.IllegalArgumentException: object is not an instance of declaring class

The full stacktrace looks like this:

    Hibernate: select max(idVisit) from Visit
2012-12-30 09:38:56,713 [main] ERROR org.hibernate.property.BasicPropertyAccessor$BasicGetter - HHH000122: IllegalArgumentException in class: com.nortal.pirs.datamodel.User, getter method of property: idUser
2012-12-30 09:38:56,714 [main] ERROR com.nortal.pirs.businesslogic.logic.VisitManagerLogic - IllegalArgumentException occurred calling getter of com.nortal.pirs.datamodel.User.idUser
java.lang.IllegalArgumentException: object is not an instance of declaring class
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.hibernate.property.BasicPropertyAccessor$BasicGetter.get(BasicPropertyAccessor.java:164)
    at org.hibernate.tuple.entity.AbstractEntityTuplizer.getIdentifier(AbstractEntityTuplizer.java:341)
    at org.hibernate.persister.entity.AbstractEntityPersister.getIdentifier(AbstractEntityPersister.java:4491)
    at org.hibernate.persister.entity.AbstractEntityPersister.isTransient(AbstractEntityPersister.java:4213)
    at org.hibernate.engine.internal.ForeignKeys.isTransient(ForeignKeys.java:209)
    at org.hibernate.engine.internal.ForeignKeys$Nullifier.isNullifiable(ForeignKeys.java:165)
    at org.hibernate.engine.internal.ForeignKeys$Nullifier.nullifyTransientReferences(ForeignKeys.java:94)
    at org.hibernate.engine.internal.ForeignKeys$Nullifier.nullifyTransientReferences(ForeignKeys.java:72)
    at org.hibernate.action.internal.AbstractEntityInsertAction.nullifyTransientReferencesIfNotAlready(AbstractEntityInsertAction.java:128)
    at org.hibernate.action.internal.AbstractEntityInsertAction.makeEntityManaged(AbstractEntityInsertAction.java:139)
    at org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:209)
    at org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:183)
    at org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:136)
    at org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:328)
    at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:287)
    at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:193)
    at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:136)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:204)
    at org.hibernate.event.internal.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:55)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:189)
    at org.hibernate.event.internal.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:49)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:90)
    at org.hibernate.internal.SessionImpl.fireSave(SessionImpl.java:756)
    at org.hibernate.internal.SessionImpl.save(SessionImpl.java:748)
    at org.hibernate.internal.SessionImpl.save(SessionImpl.java:744)
    at com.nortal.pirs.persistence.dbhibernate.visits.VisitDaoHibernate.addVisit(VisitDaoHibernate.java:46)
    at com.nortal.pirs.businesslogic.logic.VisitManagerLogic.addVisit(VisitManagerLogic.java:39)
    at com.nortal.pirs.test.persistence.filldata.FillVisits.fill(FillVisits.java:31)
    at com.nortal.pirs.test.persistence.filldata.FillVisits.main(FillVisits.java:21)

This error occurs when trying to add a Visit, which has a field idPatient, which is of type long and is supposed to be the id of the patient that the visit is being registered for, so the method where I'm getting this at looks like this (class VisitDaoHibernate):

@Override
    public void addVisit(Visit visit) {
        session = connection.getSession();
        session.beginTransaction();
        session.save(visit); // here it happens...
        session.getTransaction().commit();
    }

The Visit class:

    /**
 * @(#) Visit.java
 */

package com.nortal.pirs.datamodel;

import java.util.Date;

import com.nortal.pirs.datamodel.enumeration.VisitState;

public class Visit {
    private long idVisit;
    private long idPatient;
    private long idSpiProfessional;
    private long idProfession;
    private Date visitDate = new Date();
    private String reason = "";
    private VisitState visitState = VisitState.REGISTERED;


    /**
     * @param patient
     * @param spiProfessional
     * @param visitDate
     * @param reason
     * @param visitState
     * @param visitProfession
     */
    public Visit() {
    }   

    public Visit(Visit visit) {
        this.idPatient = visit.getIdPatient();
        this.idSpiProfessional = visit.getIdSpiProfessional();
        this.idProfession = visit.getIdProfession();
        this.visitDate = visit.getVisitDate();
        this.reason = visit.getReason();
        this.visitState = visit.getVisitState();
    }

    public long getIdVisit() {
        return idVisit;
    }

    public void setIdVisit(long idVisit) {
        this.idVisit = idVisit;
    }

    public long getIdPatient() {
        return idPatient;
    }

    public void setIdPatient(long idPatient) {
        this.idPatient = idPatient;
    }

    public long getIdSpiProfessional() {
        return idSpiProfessional;
    }

    public void setIdSpiProfessional(long idSpiProfessional) {
        this.idSpiProfessional = idSpiProfessional;
    }

    public long getIdProfession() {
        return idProfession;
    }

    public void setIdProfession(long idProfession) {
        this.idProfession = idProfession;
    }

    public Date getVisitDate() {
        return visitDate;
    }

    public void setVisitDate(Date visitDate) {
        this.visitDate = visitDate;
    }

    public String getReason() {
        return reason;
    }

    public void setReason(String reason) {
        this.reason = reason;
    }

    public VisitState getVisitState() {
        return visitState;
    }

    public void setVisitState(VisitState visitState) {
        this.visitState = visitState;
    }
}

My User class:

    /**
 * @(#) User.java
 */

package com.nortal.pirs.datamodel;

import java.util.Date;

import com.nortal.pirs.datamodel.enumeration.Gender;
import com.nortal.pirs.datamodel.enumeration.UserState;

public class User {
    private long idUser;
    private String firstName = "";
    private String lastName = "";
    private String personCode = "";
    private Date birthDate = new Date();
    private Gender gender = Gender.MALE;
    private String email = "";
    private String password = "";
    private UserState userState = UserState.UNAPPROVED;

    public User(User user) {
        idUser = user.getIdUser();
        firstName = user.getFirstName();
        lastName = user.getLastName();
        personCode = user.getPersonCode();
        birthDate = user.getBirthDate();
        gender = user.getGender();
        email = user.getEmail();
        password = user.getPassword();
        userState = user.getUserState();
    }

    public User() {

    }

    public boolean sameAs(User user) {
        if (user == null) {
            return false;
        }

        if (this.getEmail().equals(user.getEmail())
                && this.getBirthDate().equals(user.getBirthDate())
                && this.getFirstName().equals(user.getFirstName())
                && this.getLastName().equals(user.getLastName())
                && this.getGender().equals(user.getGender())
                && this.getPassword().equals(user.getPassword())
                && this.getPersonCode().equals(user.getPersonCode())
                && this.getUserState().equals(user.getUserState())) {
            return true;
        } else {
            return false;
        }

    }

    /**
     * @param firstName
     * @param lastName
     * @param personCode
     * @param birthDate
     * @param gender
     * @param email
     * @param password
     * @param userState
     */
    public User(String firstName, String lastName, String personCode,
            Date birthDate, Gender gender, String email, String password,
            UserState userState) {
        super();
        this.firstName = firstName;
        this.lastName = lastName;
        this.personCode = personCode;
        this.birthDate = birthDate;
        this.gender = gender;
        this.email = email;
        this.password = password;
        this.userState = userState;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getPersonCode() {
        return personCode;
    }

    public void setPersonCode(String personCode) {
        this.personCode = personCode;
    }

    public Date getBirthDate() {
        return birthDate;
    }

    public void setBirthDate(Date birthDate) {
        this.birthDate = birthDate;
    }

    public Gender getGender() {
        return gender;
    }

    public void setGender(Gender gender) {
        this.gender = gender;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public UserState getUserState() {
        return userState;
    }

    public void setUserState(UserState userState) {
        this.userState = userState;
    }

    public long getIdUser() {
        return idUser;
    }

    public void setIdUser(long idUser) {
        this.idUser = idUser;
    }

}

My UserMapper xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.nortal.pirs.datamodel">

    <class name="User" table="User">

        <id name="idUser" type="long" column="idUser">
            <generator class="increment"/>
        </id>

        <property name="firstName" />
        <property name="lastName" />
        <property name="personCode" />
        <property name="birthDate" type="date"/>
        <property name="email" />
        <property name="password" />

       <property name="userState" column="userState" length="15">
             <type name="org.hibernate.type.EnumType">
                  <param name="enumClass">com.nortal.pirs.datamodel.enumeration.UserState</param>
                  <param name="type">12</param>
              </type>
        </property>

         <property name="gender" column="gender" length="15">
             <type name="org.hibernate.type.EnumType">
                  <param name="enumClass">com.nortal.pirs.datamodel.enumeration.Gender</param>
                  <param name="type">12</param>
              </type>
        </property>

         <joined-subclass name="Patient" table="Patient">
             <key column="idUser" />
             <property name="additionalInfo" column="additionalInfo" />
         </joined-subclass>

         <joined-subclass name="SpiProfessional" table="SpiProfessional">
                 <key column="idUser" />
         </joined-subclass>

    </class>

</hibernate-mapping>

And my VisitMapper xml: (this is the one, that should be in action actually, I don't even understand why Hibernate needs the getter for user at all...)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.nortal.pirs.datamodel">

    <class name="Visit"
        table="Visit">

        <id name="idVisit">
            <generator class="increment"/>
        </id>

        <property name="visitDate" type="date" />
        <property name="reason" />

       <property name="visitState" column="visitState" length="15">
             <type name="org.hibernate.type.EnumType">
                  <param name="enumClass">com.nortal.pirs.datamodel.enumeration.VisitState</param>
                  <param name="type">12</param>
              </type>
        </property>

        <many-to-one name="idPatient" not-null="false" class="com.nortal.pirs.datamodel.Patient"/>
        <many-to-one name="idSpiProfessional" not-null="false" class="com.nortal.pirs.datamodel.SpiProfessional" />
        <many-to-one name="idProfession" not-null="false" class="com.nortal.pirs.datamodel.Profession" />

I just hope somebody can help me with this. Thanks

frictionlesspulley
  • 11,070
  • 14
  • 66
  • 115
Arturas M
  • 4,120
  • 18
  • 50
  • 80

3 Answers3

19

You're telling Hibernate that the Visit class has a many-to-one association with the Patient class (and with two other classes). It doesn't have such an association. If you had such an assciation, the Visit class would contain

private Patient patient;

public Patient getPatient() {
    return this.patient;
}

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

Instead, what you have in your Visit entity is the ID of a patient. That doesn't constitute an association.

Read the Hibernate documentation about associations, because you've missed what they are, and a great deal of what an ORM actually allows, which is to be able to load, navigate and query graphs of objects.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • Alright, seems a pretty informative answer, thanks, can you supply it, how in this case my problem should be solved? Because in this case I thought it would be too much overhead to store the Patient and SpiProfessional for every single visit, while every patient has many visits... How do I map it correctly? – Arturas M Dec 30 '12 at 15:01
  • Or would it even be OK, if I stored the Patient and SpiProfessional objects inside every visit? – Arturas M Dec 30 '12 at 15:02
  • 2
    Yes, it would be OK. That's how Hibernate is supposed to be used. All associations are lazy by default, so loading a visit will only load the columns in the visit table, until you call `getPatient()` on it, which will automatically load the patient data transparently and return it. – JB Nizet Dec 30 '12 at 15:04
  • Thanks, I see, so this is what lazy associations are. Are there any negative things about it? Memory usage is fine this way too? – Arturas M Dec 30 '12 at 15:59
  • I'll use your way, but I'm still wondering how I would have to manage it if I was to leave these fields as long variables and not objects? what would I have to do to configure it correctly? – Arturas M Dec 30 '12 at 16:02
  • 2
    There are negative things: if you don't understand what's going on behind the scenes, you can end up executing N +1 queries instead of just one to load the same data (i.e. one visit and its N patients). If you understand what's going on and know what you're doing, there's no problem: you can use an appropriate query to load the whole thing at once. – JB Nizet Dec 30 '12 at 16:02
  • 2
    If you wanted to leave it as it is, you would simply have to map the long fields are regular properties/columns, instead of mapping them as associations. – JB Nizet Dec 30 '12 at 16:03
  • Hmm is it OK with bibernate then? And the database itself checks then whether the foreign key values exist in associated tables? – Arturas M Dec 30 '12 at 16:22
  • 1
    You can of course do that. But that's like using a SuperComputer to run notepad. You would leave out lots of useful features, and a much more lightweight solution could be used to achieve the same goal. – JB Nizet Dec 30 '12 at 16:27
  • The only place where you should try to work with plain ids is when you need to loosely couple the entities. And from my experience you should actually avoid loosely coupling entities. – sorencito Dec 30 '12 at 19:55
  • Thanks @JBNizet I was doing the same mistake. Your post enlightened me. Thanks Arturas M for making the mistake much before and asking it on SO. :-) – asgs Jan 02 '16 at 19:39
5

This error can also occur when using the wrong parameter binding method. For example:

select o from Order o where o.client in (:clients)

Using

query.setParameter("clients", clientList);

instead of

query.setParameterList("clients", clientList);

would result in the above error.

isah
  • 5,221
  • 3
  • 26
  • 36
0

In my (I assume, rare) case a similar error was due to the field:

    @MapKey
    public Map<Integer, AttributeValue_> getAttrValues() {
        return attrValues;
    }

and the problem was in that AttributeValue primary key was not Integer. Hence, IllegalArgumentException caused by ClassCastException.

The solution was to make

    @MapKeyColumn(name = "attr_id")

which tied the key of the map to a certain attribute attr_id.

ligett
  • 61
  • 3