0

Consider the following POJOs that will be used for holding the parameters that will be passed to a query.

public class RegionKey {

        private BigDecimal rgnId;
        private Country country;

        //setters and getters.    

        }

public class Country {

        private BigDecimal cntryId;

        //setters and getters.   

        }

 public class Region extends RegionKey {

        private String rgnNm;
        private String desc;

        //setters and getters


    }

  public class Customer {
            private BigDecimal custId;
            private Region rgn;

        }

Consider the CustomerMapper interface for MyBatis

public interface CustomerMapper {

        int deleteByPrimaryKey(@Param("custRecord") Customer key);
    }

Consider a snippet from the CustomerMapper.xml file (QUery 1)

 <delete id="deleteByPrimaryKey">
            delete from CUSTOMER
            where CUST_ID = #{custRecord.custId,jdbcType=DECIMAL} 
            and RGN_ID =
            cast(#{custRecord.rgn.rgnId,jdbcType=CHAR} as char(10))
    </delete>

The above query works perfectly fine. Modifying the above query with the following if-test works fine as well (Query 2)

 <delete id="deleteByPrimaryKey">
                        delete from CUSTOMER
                        where CUST_ID = #{custRecord.custId,jdbcType=DECIMAL} 
                        <if test="custRecord.rgn.rgnId != null">
                    and RGN_ID = cast(#{custRecord.rgn.rgnId,jdbcType=CHAR} as
                    char(10))
                        </if>                   

                </delete>

Modifying the query as follows causes a runtime exception (Query 3)

<delete id="deleteByPrimaryKey">
                    delete from CUSTOMER
                    where CUST_ID = #{custRecord.custId,jdbcType=DECIMAL} 
                    <if test="custRecord.rgn.country.cntryId != null">
                and CNTRY_ID =
                cast(#{custRecord.rgn.country.cntryId,jdbcType=CHAR} as
                char(10))
                    </if>



            </delete>

I get a org.apache.ibatis.ognl.NoSuchPropertyException at runtime for query number 3. I am unable to understand why this happens. If I can access the rgnId field from custRecord.rgn in query 2, I should technically be able to access the cntryId field from custRecord.rgn.country in query number 3.

Chetan Kinger
  • 15,069
  • 6
  • 45
  • 82
  • 1
    Are you sure the getters/setters are ok? Does `test="custRecord.rgn.country != null"` also throw exception? – leonbloy Apr 23 '13 at 13:46
  • Being new to MyBatis, I had no idea that MyBatis looks for getters and setters with the same name as the property. Renaming the getCntry method to getCountry did the trick. Thanks a lot for the tip. Can you post this as an answer so that I can upvote you and accept the answer? – Chetan Kinger Apr 23 '13 at 14:00

1 Answers1

4

MyBatis expects (as most frameworks do) that "properties" follow the Java Bean specs, so that a property foo is mapped to a getter getFoo() and (optionally) a setter setFoo() (the name of the private field can be different -it can even not exist!- but very often it has same as the property).

So, in you example you should have

public class RegionKey {
      private Country country;
      ...
      public Country getCountry() {
      ...
      }
}

and so on. Java IDEs (eg Eclipse) understand this convention, and allow you to generate these getters/setters for you, so you don't have to type them.

Community
  • 1
  • 1
leonbloy
  • 73,180
  • 20
  • 142
  • 190
  • I had generated the setters and getters using Eclipse. I happened to rename the field but forgot to rename the setters and getters! – Chetan Kinger Apr 24 '13 at 05:33