1

I can't map the results from JSON_ARRAYAGG function.

mybatis mapper:

<mapper namespace="com.test.mapper.UserEntityMapper">
    <resultMap id="userMap" type="UserVO">
        <id property="id" column="id" />
        <result property="username" column="username"/>
        <collection property="pictures" ofType="PictureVO">
            <id property="id" column="id" />
            <result property="location" column="location" />
        </collection>
    </resultMap>
    <select id="findUserById" parameterType="map" resultMap="userMap">
        SELECT
        users.id,
        users.username,
        JSON_ARRAYAGG(
            JSON_OBJECT(
                "id",
                pic.id,
                "location",
                pic.location
            ) 
        ) AS pictures
        FROM
            users
            LEFT JOIN pictures pic ON users.id = pic.user_id 
        WHERE
            users.id = 1
    </select>
</mapper>

UserVO model:

@Getter
@Setter
@NoArgsConstructor
public class UserVO {
    private Long id;
    private String username;
    private List<PictureVO> pictures;
}

PictureVO model:

@Getter
@Setter
@NoArgsConstructor
public class PictureVO {
    private Long id;
    private String location;
}

Results from calling the API:

{
    "id": 1,
    "username": "connor",
    "pictures": [
        {
            "id": 1,
            "location": null
        }
    ]
}

As you can see, the pictures only have a id can be map correctly. And there are suppose 2 results in pictures, if I execute the sql directly, and here only 1 returned.

yong ho
  • 3,892
  • 9
  • 40
  • 81

3 Answers3

0

you should set your method's ("findUserById") return type List and MyBatis will complete that automatically. Try to write it in mapper interface:

List<UserVo> findUserById();
Dmitrii B
  • 2,672
  • 3
  • 5
  • 14
0

MyBatis returns Java objects not JSON, so it may be your 'API' that converts the Java objects into JSON.
If I am right, you just need to do the normal MyBatis mapping.

Something like this:

<resultMap id="userMap" type="UserVO">
  <id property="id" column="id" />
  <result property="username" column="username"/>
  <collection property="pictures" ofType="PictureVO">
    <id property="id" column="picture_id" />
    <result property="location" column="location" />
  </collection>
</resultMap>

<select id="findUserById" parameterType="map" resultMap="userMap">
  SELECT
    users.id,
    users.username,
    pic.id picture_id,
    pic.location
  FROM
    users
    LEFT JOIN pictures pic ON users.id = pic.user_id
  WHERE
    users.id = 1
</select>

Note that pic.id needs an alias to distinguish the column from users.id in the result set.

ave
  • 3,244
  • 2
  • 14
  • 20
0

Use typeHandler. For instance:

<resultMap id="userMap" type="UserVO">
        <id property="id" column="id" />
        <result property="username" column="username"/>
        <result property="pictures" column="pictures" 
         typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"
        />
    </resultMap>