Composite keys in MyBatis <collection> mappings

5.8k views Asked by At

I am unable to pass a composite key to a MyBatis <collection> element (using version 3.2.7). The MyBatis documentation states:

Note: To deal with composite keys, you can specify multiple column names to pass to the nested select statement by using the syntax column="{prop1=col1,prop2=col2}". This will cause prop1 and prop2 to be set against the parameter object for the target nested select statement.

However, all my attempts to implement this produce the Exception

org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.reflection.ReflectionException: Error instantiating class java.lang.Integer with invalid types () or values (). Cause: java.lang.NoSuchMethodException: java.lang.Integer.<init>()

The collection (which resides in another ResultsMap) is:

<collection property="foos" ofType="FooObject"
    column="{param1=user_id,param2=foo_id}" select="getFoosByUser" >
        <id property="userId" column="user_id" />
        <id property="foo" column="foo_id" />
        <result property="fooName" column="foo_name" />
</collection>

It should return an ArrayList of Foo objects. The composite key is user_id and foo_id. The select query is:

    <select id="getFoosByUser" parameterType="Integer" resultType="FooObject">
        SELECT
          user_id AS userId,
          foo_id AS fooId, 
          foo_name AS fooName
        FROM foo_table
        WHERE user_id = #{param1}
        AND foo_id = #{param2}
    </select>

The query works correctly if I only use one parameter, e.g. removed foo_id=#{param2} and then use column=user_id in the collection, but I cannot work out how to structure the column attribute correctly for two keys. Any ideas?

1

There are 1 answers

1
Roman-Stop RU aggression in UA On BEST ANSWER

MyBatis is confused by using parameterType when there are more than one parameter. Modify you query mapping like this:

<select id="getFoosByUser" resultType="FooObject">
    SELECT
      user_id AS userId,
      foo_id AS fooId, 
      foo_name AS fooName
    FROM foo_table
    WHERE user_id = #{param1}
    AND foo_id = #{param2}
</select>