-->
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: Java Bean problem
PostPosted: Mon Jun 20, 2005 9:17 am 
Newbie

Joined: Wed Nov 12, 2003 3:49 pm
Posts: 19
Folks,

Has anybody been able to use hibernate to load a java bean that has multiple set methods for the same property? Many of my business objects have multiple single argument setters, and the only way that I can keep hibernate from choking is to eliminate all but one of them.

I have reviewed the java bean spec, the hibernate doc, and Hibernate in Action, and have not found anything that indicates that muliple setters are not allowed.

The only think that I can think of is that I need to explicitly specify which set method to use in such cases. But, it seems like Hibernate should be able to select the appropriate method based on the signature.

Has anybody had any success with multiple setters?

Thanks,
Dave


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 20, 2005 9:35 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
It should work.


how does your mapping and code signature look like ?

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 20, 2005 8:35 pm 
Newbie

Joined: Wed Nov 12, 2003 3:49 pm
Posts: 19
max wrote:
It should work.


how does your mapping and code signature look like ?


Max -

Sorry that it took a while to get back to you - once you say "it should work", I wanted to dig deeper before I gave up.

I have whittled my example just about down to the bare minimum - two columns are being mapped into the javabean.

I can't figure out what I am doing that is directing Hibernate to use the setExperimentNumber(Exp_Nbr7) method instead of one of the methods that accept an int or an Integer.

Thanks in advance,
Dave

Mapping Code:
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
  "-//Hibernate?Hibernate Mapping DTD//EN"
  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
  <class name="dtpitb.businessobjects.invivo.InvivoExperiment" table="I_EXP">
    <id name="experimentNumber" column="EXP_NBR" type="integer" </id>
    <property name="expID" column="EXPID" type="string" />

  </class>
</hibernate-mapping>

java bean code
Code:
package dtpitb.businessobjects.invivo;

import dtpitb.wrappers.ITBWrapperException;
import dtpitb.wrappers.Exp_Nbr7;
import dtpitb.wrappers.ExpIDInvivo;
import dtpitb.businessobjects.DTPExperiment;
import java.io.Serializable;


public class InvivoExperiment extends DTPExperiment  implements Serializable {

    public InvivoExperiment() {}

    public ExpIDInvivo getExpID() {
        return expID;
    }

    public void setExpID(ExpIDInvivo expID) {
        this.expID = expID;
    }

    public void setExpID(String expID){  // this is the signature that I want to use

            try {
                this.expID = new ExpIDInvivo(expID);
            }
            catch (ITBWrapperException ex) {
                throw new RuntimeException("error in InvivoExperiemtn.setExpID(String expID)");
            }

    }


    public Exp_Nbr7 getExperimentNumber() {
        return this.experimentNumber;
    }

    public void setExperimentNumber(Exp_Nbr7 experimentNumber) {  // this is the one I don't want to use
        this.experimentNumber = experimentNumber;
    }

    public void setExperimentNumber(int experimentNumber)  { 
        try {
            this.experimentNumber = new Exp_Nbr7(experimentNumber);
        }
        catch (ITBWrapperException ex) {
                throw new RuntimeException("handle this");
        }
    }

    public void setExperimentNumber(Integer experimentNumber)  {
        try {
            this.experimentNumber = new Exp_Nbr7(experimentNumber);
        }
        catch (ITBWrapperException ex) {
                throw new RuntimeException("handle this");
        }
    }

    private ExpIDInvivo expID;
    private Exp_Nbr7 experimentNumber;

}

Oracle Table def
Code:
SQL> desc exp
Name                                      Null?    Type
----------------------------------------- -------- --------------------
EXPID                                     NOT NULL VARCHAR2(9)
COMP_CODE                                 NOT NULL VARCHAR2(1)
SCR                                       NOT NULL VARCHAR2(2)
EXP_NBR                                   NOT NULL NUMBER(7)
PANELNBR                                           NUMBER(2)
CELLNBR                                            NUMBER(3)
PASSAGE_CODE                                       VARCHAR2(12)
TUMOR_START_SIZE                                   NUMBER(4)
TUMOR_END_SIZE                                     NUMBER(4)
TUMOR_START_SIZE_MEAN                              NUMBER(4)
TUMOR_START_SIZE_MED                               NUMBER(4)
ASSAY_TYPE                                NOT NULL VARCHAR2(3)
MEMO_NBR                                           NUMBER
MEMO_DATE                                          DATE
BOOK_NBR                                           VARCHAR2(8)
SEX                                                VARCHAR2(1)
ANIMAL_HOST_CODE                                   VARCHAR2(4)
SINGLE_SOURCE                                      VARCHAR2(1)
ANIMAL_SOURCE_1                                    VARCHAR2(3)
ANIMAL_SOURCE_2                                    VARCHAR2(3)
IMPLANT_DATE                                       DATE
STAGING_DATE                                       DATE
STAGING_DAY                                        NUMBER(3)
FINAL_EVAL_DATE                                    DATE
FINAL_EVAL_DAY                                     NUMBER(3)
IMPLANT_SITE                                       VARCHAR2(2)
IMPLANT_TISSUE                                     VARCHAR2(1)
IMPLANT_LEVEL                                      VARCHAR2(2)
NUMBER_OF_GROUPS                                   NUMBER(3)
ANIMALS_PER_TEST_GROUP                             NUMBER(2)
CONTROL_TYPE                                       VARCHAR2(1)
APP_LVL                                            VARCHAR2(2)
SC_APP_DATE                                        DATE
PO_APP_DATE                                        DATE
APP_END_POINT                                      NUMBER(5)
PO_NOTIF_DATE                                      DATE
TREATMENT_BY                                       VARCHAR2(1)
IMPLANT_VOLUME                                     NUMBER(2,1)
NBR_INVITRO_SAMPLES                                NUMBER(2)
FIBER_TYPE                                         VARCHAR2(2)
CULTURE_DURATION                                   NUMBER(1)
CALC_DATE                                          DATE


Runtime exception:
Code:
Hibernate: select invivoexpe0_.EXP_NBR as EXP1_, invivoexpe0_.EXPID as EXPID0_ from I_EXP invivoexpe0_ where exp_nbr=63419 order by invivoexpe0_.EXPID desc

20:19:52,843 DEBUG AbstractBatcher:378 - preparing statement

20:19:53,062 DEBUG AbstractBatcher:306 - about to open ResultSet (open ResultSets: 0, globally: 0)

20:19:53,062 DEBUG Loader:405 - processing result set

20:19:53,062 DEBUG Loader:410 - result set row: 0

20:19:53,078 DEBUG IntegerType:86 - returning '63419' as column: EXP1_

20:19:53,078 DEBUG Loader:828 - result row: EntityKey[dtpitb.businessobjects.invivo.InvivoExperiment#63419]

20:19:53,078 ERROR BasicPropertyAccessor:62 - IllegalArgumentException in class: dtpitb.businessobjects.invivo.InvivoExperiment, setter method of property: experimentNumber

20:19:53,093 ERROR BasicPropertyAccessor:66 - expected type: dtpitb.wrappers.Exp_Nbr7, actual value: java.lang.Integer

20:19:53,093 DEBUG AbstractBatcher:313 - about to close ResultSet (open ResultSets: 1, globally: 1)

20:19:53,187 DEBUG AbstractBatcher:298 - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)

20:19:53,187 DEBUG AbstractBatcher:416 - closing statement

org.hibernate.PropertyAccessException: IllegalArgumentException occurred while calling setter of dtpitb.businessobjects.invivo.InvivoExperiment.experimentNumber

   at org.hibernate.property.BasicPropertyAccessor$BasicSetter.set(BasicPropertyAccessor.java:70)

   at org.hibernate.tuple.AbstractTuplizer.setIdentifier(AbstractTuplizer.java:130)

   at org.hibernate.tuple.AbstractTuplizer.instantiate(AbstractTuplizer.java:223)

   at org.hibernate.persister.entity.BasicEntityPersister.instantiate(BasicEntityPersister.java:2959)

   at org.hibernate.impl.SessionImpl.instantiate(SessionImpl.java:1049)

   at org.hibernate.impl.SessionImpl.instantiate(SessionImpl.java:1041)

   at org.hibernate.loader.Loader.instanceNotYetLoaded(Loader.java:933)

   at org.hibernate.loader.Loader.getRow(Loader.java:855)

   at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:305)

   at org.hibernate.loader.Loader.doQuery(Loader.java:412)

   at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:218)

   at org.hibernate.loader.Loader.doList(Loader.java:1593)

   at org.hibernate.loader.Loader.list(Loader.java:1577)

   at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:395)

   at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:271)

   at org.hibernate.impl.SessionImpl.list(SessionImpl.java:844)

   at org.hibernate.impl.QueryImpl.list(QueryImpl.java:74)

   at dtpitb.businessobjects.invivo.InvivoHibernateTestProgram.main(InvivoHibernateTestProgram.java:33)

Caused by: java.lang.IllegalArgumentException: argument type mismatch

   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

   at java.lang.reflect.Method.invoke(Method.java:324)

   at org.hibernate.property.BasicPropertyAccessor$BasicSetter.set(BasicPropertyAccessor.java:40)

   ... 17 more

20:19:53,203 DEBUG JDBCContext:322 - after autocommit

Exception in thread "main"


Top
 Profile  
 
 Post subject: I think I got it
PostPosted: Tue Jun 21, 2005 11:13 pm 
Newbie

Joined: Wed Nov 12, 2003 3:49 pm
Posts: 19
I think that this is the deal. ..

Hibernate selects the setter signature based on the return type of the getter. So, even if you have multiple setters, and one of them is consistent with the Hibernate type specified in the .hbm file, Hibernate will always select the one with a signature that is consistent with the return type of the (single) setter - regardless of the type specified in the .hbm file.

So, if you have POJOs that use custom classes as properties, you have two choices:

1. implement the UserType interface in your custom classes, and specify them in the hbm files, or

2. Add a private get/set pair for each property with a different name and use this "virtual property" in the .hbm files

Option 1 requires a fair amount of work at both the java level as well in all of your mapping files. And if you are going to set up multiple mapping files/pojo for purposes of altering the fetching behavior, this could turn into quite a bit of work. I am also a bit wary of this approach because I'm not that confident in my understanding of the methods specified by the interface... (like Dirty Harry says - "A man's got to know his limitations.")

Option 2 looks a bit tacky, but if you make the methods private, who's to know?

So, if my existing bean property looks like this:
Code:
public void setSomeProp(MyCustomClass someProp);
public MyCustomClass getSomeProp();


I added methods that looked like this:

Code:
private void setSomePropString(String someProp){}
private String getSomePropString(){}


The bodies of the private get/set pair translate between MyCustomClass and String. In the mapping file, I map to the private "virtual property" like this:

<property name="somePropString" column="someColumn" type="string" />

This may not be the most elegant solution, but after about 1000 trial and error attempts, this seems like the most straight forward approach.

One more thing - be sure to check for null before returning a value for the virtual property.

I don't think that this is a bug - I think that this behavior is consistent with the java bean spec.

If anybody has a better approach, please post it!

Thanks,
Dave


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 18, 2008 11:12 am 
Newbie

Joined: Thu Oct 30, 2008 5:52 am
Posts: 5
Location: Germany
Hi DaveSegal,

I had the same problem by the overloading setter methods. After a search on the forum, I firstly found your topic under:

http://forum.hibernate.org/viewtopic.php?t=943652

Unfortunately there were no responses to your question. So it seems so that Hibernate cannot fetch the correct Method even if the parameter types are given correctly. This is actually weird since this is a very base, simple but an important point which as a developer I would expect it to be fetched perfectly.

So for now I'm gonna use your suggestion and rename my set method and make it private. Pity that sometimes there are no suggestive responses for good questions here...

_________________
The identity of a person is what s/he thinks.


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.