ibatis-user-java mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Jeff Butler" <jeffgbut...@gmail.com>
Subject Re: Working with composite objects and the syntax phoneNumbers[0].areaCode
Date Thu, 29 Jun 2006 21:07:16 GMT
It's more complex than that... (and I think Rick is using a List.  I wrote a
test case with a List and got the same error).

When the SqlMap is parsed there is a lot of initialization performed.  One
of these initializations is that the type handlers for all properties are
calculated.  The iBATIS object probes can't see through the List (or array)
- they don't understand the [3] syntax.

It's probably possible to fix this (all things are possible given enough
coding), but it didn't seem too simple to me, so I thought it would be
easier to update the documentation to say "not supported" :)

Clinton was pretty vehement about not supporting this, we should probably
get his opinion about the difficulties involved - that's an area of the code
that I'm still a little murky about.

It's different for the dynamic SQL tags - they are parsed differently and
the type handlers aren't calculated until the statement is run (if I
understand that correctly).  They also have special code to deal with the
[3] syntax.

Jeff Butler



On 6/29/06, Poitras Christian <Christian.Poitras@ircm.qc.ca> wrote:
>
>  Jeff, is it possible that this problem has something to do with the use
> of an array instead of a List?
>
> Rick, you could use a List instead to store the phone numbers. You can use
> a FixedLengthList from Jakarta common collections package if you want a
> fixed length of phone numbers.
> http://jakarta.apache.org/commons/collections/
> Maybe this could correct the problem if you adapt your SQL to return a
> List of phone numbers.
>
> Christian
>
>  ------------------------------
>  *From:* Jeff Butler [mailto:jeffgbutler@gmail.com]
> *Sent:* Thursday, 29 June 2006 14:16
>
> *To:* user-java@ibatis.apache.org
> *Subject:* Re: Working with composite objects and the syntax
> phoneNumbers[0].areaCode
>
>
>  I should have looked before I lept...
>
> I looked into this a little more and as Clinton said, this is not
> supported.  Making it supported is far from a trivial fix to iBATIS.  I'll
> update the documentation accordingly.
>
> Jeff Butler
>
>
>
> On 6/29/06, Rick <ricks_mailinglists@arc-mind.com> wrote:
> >
> >   Thank you for answering my questions. I am new to iBatis and so far
> > really dig it.
> >
> >
> >
> > Comments below….
> >
> >
> >
> > I am willing to update the FAQ (WIKI) with my workaround.
> >  ------------------------------
> >
> > *From:* Jeff Butler [mailto: jeffgbutler@gmail.com]
> > *Sent:* Wednesday, June 28, 2006 8:13 PM
> >
> > *To:* user-java@ibatis.apache.org
> > *Subject:* Re: Working with composite objects and the syntax
> > phoneNumbers[0].areaCode
> >
> >
> >
> > This may be a bug in iBATIS.  I'll take a closer look tomorrow.
> >
> >
> >
> > ** Somebody asked before and was told it is not a bug by Clinton see http://www.mail-archive.com/dev@ibatis.apache.org/msg00521.html
> > .
> >
> >
> >
> > It's a little unusual to use this syntax in a result map - so maybe
> > that's why it's not come up sooner (no excuses - it should work).
> >
> >
> >
> > ** It maybe unusual but according to the developer guide page 50 as of
> > 6/16/2006 this should work. I think iBatis target market is mature database
> > schemas (read legacy).
> >
> > A lot of mature schemas are highly un-normalized for speed. I was
> > surprised that it did not work.
> >
> >
> >
> > *** I am not sure if it is a bug or a feature request. I think it needs
> > to be fixed OR page 50 needs to be reworded a bit since it says this will
> > work. :o)
> >
> > I have a work around so I am not stuck.
> >
> >
> >
> > It is common to use this type of syntax with the dynamic sql tags, I
> > know for sure that it works in that circumstance.
> >
> >
> >
> > ** Good to know. I'll need to work with those as well.
> >
> >
> >
> >
> >
> > Jeff Butler
> >
> >
> >
> > On 6/28/06, *Rick* < ricks_mailinglists@arc-mind.com> wrote:
> >
> > I have a workaround as follows:
> >
> >
> >
> > (Notice I added setPhoneNumber1… and getPhoneNumber1…. It works, but not
> > as clean as the old version. I don't want the object model tied this close
> > to the db structure. )
> >
> >
> >
> > package qcom.cas.mysourcej.poc.model;
> >
> >
> >
> > import java.io.Serializable;
> >
> > import java.util.ArrayList;
> >
> > import java.util.List;
> >
> >
> >
> > public class Contact implements Serializable {
> >
> >             private List phoneNumbers = new ArrayList();
> >
> >
> >
> >
> >
> >             private String name;
> >
> >             private boolean primaryContact;
> >
> >             private String relationship = "Spouse";
> >
> >
> >
> >             public Contact() {
> >
> >                         phoneNumbers.add(new Phone());
> >
> >                         phoneNumbers.add(new Phone());
> >
> >                         phoneNumbers.add(new Phone());
> >
> >                         phoneNumbers.add(new Phone());
> >
> >             }
> >
> >
> >
> >
> >
> >
> >
> >             public Contact(String name) {
> >
> >                         super();
> >
> >                         this.name = name;
> >
> >             }
> >
> >
> >
> >             public Contact(String name, Phone phone) {
> >
> >                         super();
> >
> >                         this.name = name;
> >
> >                         phoneNumbers.add(phone);
> >
> >             }
> >
> >
> >
> >             public Contact(String name, Phone phone, String
> > relationship) {
> >
> >                         this(name, phone);
> >
> >                         this.relationship = relationship;
> >
> >             }
> >
> >
> >
> >             public boolean isPrimaryContact() {
> >
> >                         return primaryContact;
> >
> >             }
> >
> >             public void setPrimaryContact(boolean primaryContact) {
> >
> >                         this.primaryContact = primaryContact;
> >
> >             }
> >
> >             public String getName() {
> >
> >                         return name;
> >
> >             }
> >
> >             public void setName(String name) {
> >
> >                         this.name = name;
> >
> >             }
> >
> >             public List getPhoneNumbers() {
> >
> >                         return phoneNumbers;
> >
> >             }
> >
> >             public void setPhoneNumbers(List phoneNumbers) {
> >
> >                         this.phoneNumbers = phoneNumbers;
> >
> >             }
> >
> >
> >
> >             public String getRelationship() {
> >
> >                         return relationship;
> >
> >             }
> >
> >
> >
> >             public void setRelationship(String relationship) {
> >
> >                         this.relationship = relationship;
> >
> >             }
> >
> >
> >
> >             public void setPhoneNumber1(Phone phone) {
> >
> >                         this.phoneNumbers.set(0, phone);
> >
> >             }
> >
> >             public void setPhoneNumber2(Phone phone) {
> >
> >                         this.phoneNumbers.set(1, phone);
> >
> >             }
> >
> >             public void setPhoneNumber3(Phone phone) {
> >
> >                         this.phoneNumbers.set(2, phone);
> >
> >             }
> >
> >             public void setPhoneNumber4(Phone phone) {
> >
> >                         this.phoneNumbers.set(3, phone);
> >
> >             }
> >
> >
> >
> >             public Phone getPhoneNumber1(){
> >
> >                         return (Phone) this.phoneNumbers.get(0);
> >
> >             }
> >
> >             public Phone getPhoneNumber2(){
> >
> >                         return (Phone) this.phoneNumbers.get(1);
> >
> >             }
> >
> >             public Phone getPhoneNumber3(){
> >
> >                         return (Phone) this.phoneNumbers.get(2);
> >
> >             }
> >
> >             public Phone getPhoneNumber4(){
> >
> >                         return (Phone) this.phoneNumbers.get(3);
> >
> >             }
> >
> >
> >
> > }
> >
> >
> >
> >
> >
> > I am in no hurry for a solution, but I vote that you support the syntax
> > you declare on page 50 of your user doc. (I don't really get a vote but if I
> > did that is how I would vote).
> >
> >
> >
> > Rick Hightower
> >
> >
> >  ------------------------------
> >
> > *From:* Rick [mailto: ricks_mailinglists@arc-mind.com]
> > *Sent:* Wednesday, June 28, 2006 5:22 PM
> > *To:* user-java@ibatis.apache.org
> > *Subject:* Working with composite objects and the syntax
> > phoneNumbers[0].areaCode
> >
> >
> >
> >
> >
> > I have a result set that has phone1, phone2, phone3, phone4, areaCode1,
> > areaCode2, areaCode3, areaCode4.
> >
> >
> >
> > I want to map these to composite objects.
> >
> >
> >
> > I.e., Employee has Contacts, Contact has phone numbers, phone number
> > consist of number and area code.
> >
> >
> >
> > When I try to map this, I get this error:
> >
> >
> >
> >
> >
> > Caused by:
> >
> > com.ibatis.common.beans.ProbeException: There is no WRITEABLE property
> > named 'phoneNumbers[0]' in class 'qcom.cas.mysourcej.poc.model.Contact '
> >
> >             at com.ibatis.common.beans.ClassInfo.getSetterType(
> > ClassInfo.java:174)
> >
> >             at
> > com.ibatis.common.beans.GenericProbe.getClassPropertyTypeForSetter(
> > GenericProbe.java:250)
> >
> >             at
> > com.ibatis.common.beans.GenericProbe.getPropertyTypeForSetter(
> > GenericProbe.java:137)
> >
> >             at
> > com.ibatis.sqlmap.engine.builder.xml.BaseParser.resolveTypeHandler(
> > BaseParser.java:68)
> >
> >             at
> > com.ibatis.sqlmap.engine.builder.xml.SqlMapParser$15.process(
> > SqlMapParser.java:403)
> >
> >             …
> >
> >
> >
> > Here is my mapping file:
> >
> >
> >
> >       <resultMap id= "employee" class ="
> > qcom.cas.mysourcej.poc.model.Employee" groupBy= "emplid" >
> >
> >             <result property= "emplid" column ="emplid" />
> >
> >             <result property= "name" column ="name" />
> >
> >             <result property= "contacts" resultMap ="employee.contacts "
> > />
> >
> >       </resultMap >
> >
> >
> >
> >       <resultMap id= "contacts" class ="
> > qcom.cas.mysourcej.poc.model.Contact" >
> >
> >             <result property= "name" column ="contact_name" />
> >
> >             <result property= "primaryContact" column ="primary_contact"
> >
> >
> >                     typeHandler= "
> > qcom.cas.commons.ibatis.typehandler.StringBooleanTypeHandler" />
> >
> >             <result property= "relationship" column ="relation" />
> >
> >             <result property= "phoneNumbers[0].number" column ="phone1"
> > />
> >
> >             <result property= "phoneNumbers[1].number" column ="phone2"
> > />
> >
> >             <result property= "phoneNumbers[2].number" column ="phone3"
> > />
> >
> >             <result property= "phoneNumbers[3].number" column ="phone4"
> > />
> >
> >             <result property= "phoneNumbers[0].areaCode" column ="areaCode1"
> > />
> >
> >             <result property= "phoneNumbers[1].areaCode" column ="areaCode2"
> > />
> >
> >             <result property= "phoneNumbers[2].areaCode" column ="areaCode3"
> > />
> >
> >             <result property= "phoneNumbers[3].areaCode" column ="areaCode4"
> > />
> >
> >       </resultMap >
> >
> >
> >
> > Page 50 of the iBatis user manual states that the syntax
> > phoneNumbers[3].areaCode  is possible for a mapping.
> >
> >
> >
> > I googled this as follows:
> > http://www.google.com/search?hl=en&lr=lang_en&newwindow=1&rls=GGLG%2CGGLG%3A2006-17%2CGGLG%3Aen&q=%22There+is+no+WRITEABLE+property+named%22+ProbeException
> >
> >
> >
> > I did notice that there was a similar issue at:
> > http://www.mail-archive.com/dev@ibatis.apache.org/msg00521.html
> >
> >
> >
> > It seems this syntax may not be supported even though the documents
> > elude that it is on page 50. How do you do this w/o the above syntax?
> >
> >
> >
> > Here is the object model for reference….
> >
> >
> >
> > package qcom.cas.mysourcej.poc.model;
> >
> >
> >
> > import java.io.Serializable;
> >
> > import java.util.ArrayList;
> >
> > import java.util.List;
> >
> >
> >
> > public class Contact implements Serializable {
> >
> >       private List phoneNumbers = new ArrayList();
> >
> >
> >
> >
> >
> >       private String name;
> >
> >       private boolean primaryContact;
> >
> >       private String relationship = "Spouse";
> >
> >
> >
> >       public Contact() {
> >
> >             phoneNumbers.add(new Phone());
> >
> >             phoneNumbers.add(new Phone());
> >
> >             phoneNumbers.add(new Phone());
> >
> >             phoneNumbers.add(new Phone());
> >
> >       }
> >
> >
> >
> >
> >
> >
> >
> >       public Contact(String name) {
> >
> >             super();
> >
> >             this.name = name;
> >
> >       }
> >
> >
> >
> >       public Contact(String name, Phone phone) {
> >
> >             super();
> >
> >             this.name = name;
> >
> >             phoneNumbers.add(phone);
> >
> >       }
> >
> >
> >
> >       public Contact(String name, Phone phone, String relationship) {
> >
> >             this(name, phone);
> >
> >             this.relationship = relationship;
> >
> >       }
> >
> >
> >
> >       public boolean isPrimaryContact() {
> >
> >             return primaryContact;
> >
> >       }
> >
> >       public void setPrimaryContact(boolean primaryContact) {
> >
> >             this.primaryContact = primaryContact;
> >
> >       }
> >
> >       public String getName() {
> >
> >             return name;
> >
> >       }
> >
> >       public void setName(String name) {
> >
> >             this.name = name;
> >
> >       }
> >
> >       public List getPhoneNumbers() {
> >
> >             return phoneNumbers;
> >
> >       }
> >
> >       public void setPhoneNumbers(List phoneNumbers) {
> >
> >             this.phoneNumbers = phoneNumbers;
> >
> >       }
> >
> >
> >
> >
> >
> >
> >
> >       public String getRelationship() {
> >
> >             return relationship;
> >
> >       }
> >
> >
> >
> >
> >
> >
> >
> >       public void setRelationship(String relationship) {
> >
> >             this.relationship = relationship;
> >
> >       }
> >
> > }
> >
> >
> >
> > package qcom.cas.mysourcej.poc.model;
> >
> >
> >
> > import java.io.Serializable;
> >
> > import java.util.ArrayList;
> >
> > import java.util.List;
> >
> >
> >
> > public class Employee implements Serializable{
> >
> >       private String emplid;
> >
> >       private List directReports = new ArrayList();
> >
> >       private List contacts = new ArrayList();
> >
> >       private Employee boss;
> >
> >       private String name;
> >
> >
> >
> >       public Employee () {
> >
> >
> >
> >       }
> >
> >
> >
> >       public Employee(Employee boss, String name) {
> >
> >             super();
> >
> >             this.boss = boss;
> >
> >             this.name = name;
> >
> >             if (this.boss !=null) {
> >
> >                   boss.addEmployee(this);
> >
> >             }
> >
> >       }
> >
> >
> >
> >       public Employee(Employee boss, String name, Contact contact) {
> >
> >             this(boss, name);
> >
> >             contacts.add(contact);
> >
> >       }
> >
> >
> >
> >       public void addEmployee(Employee employee) {
> >
> >             employee.setBoss(this);
> >
> >             this.directReports.add(employee);
> >
> >       }
> >
> >       public String getName() {
> >
> >             return name;
> >
> >       }
> >
> >       public void setName(String name) {
> >
> >             this.name = name;
> >
> >       }
> >
> >       public List getDirectReports() {
> >
> >             return directReports;
> >
> >       }
> >
> >       public void setDirectReports(List directReports) {
> >
> >             this.directReports = directReports;
> >
> >       }
> >
> >       public Employee getBoss() {
> >
> >             return boss;
> >
> >       }
> >
> >       public void setBoss(Employee boss) {
> >
> >             this.boss = boss;
> >
> >       }
> >
> >       public List getContacts() {
> >
> >             return contacts;
> >
> >       }
> >
> >       public void setContacts(List contacts) {
> >
> >             this.contacts = contacts;
> >
> >       }
> >
> >
> >
> >       public String toString() {
> >
> >             return name;
> >
> >       }
> >
> >
> >
> >       public String getEmplid() {
> >
> >             return emplid;
> >
> >       }
> >
> >
> >
> >       public void setEmplid(String emplid) {
> >
> >             this.emplid = emplid;
> >
> >       }
> >
> > }
> >
> >
> >
> > package qcom.cas.mysourcej.poc.model;
> >
> >
> >
> > import java.io.Serializable;
> >
> >
> >
> > public class Phone implements Serializable{
> >
> >       private String areaCode;
> >
> >       private String number;
> >
> >       private boolean uS=true;
> >
> >
> >
> >       public Phone () {
> >
> >
> >
> >       }
> >
> >
> >
> >       public Phone(String areaCode, String number, boolean us) {
> >
> >             super();
> >
> >             this.areaCode = areaCode;
> >
> >             this.number = number;
> >
> >             uS = us;
> >
> >       }
> >
> >
> >
> >       public String getAreaCode() {
> >
> >             return areaCode;
> >
> >       }
> >
> >       public void setAreaCode(String areaCode) {
> >
> >             this.areaCode = areaCode;
> >
> >       }
> >
> >       public String getNumber() {
> >
> >             return number;
> >
> >       }
> >
> >       public void setNumber(String number) {
> >
> >             this.number = number;
> >
> >       }
> >
> >       public boolean isUS() {
> >
> >             return uS;
> >
> >       }
> >
> >       public void setUS(boolean us) {
> >
> >             uS = us;
> >
> >       }
> >
> >
> >
> >       public String toString() {
> >
> >             if (uS) {
> >
> >                   return this.areaCode + "\\"  + this.number;
> >
> >             } else {
> >
> >                   return this.areaCode + "-"  + this.number;
> >
> >             }
> >
> >       }
> >
> > }
> >
> >
> >
> >
> >
> >
> >
> >
> >
>
>

Mime
View raw message