Failed to map to class with member objects when used with Lombok

43 Views Asked by At

The Task class has an instance of TaskPayload as a member object.

@Data
@Builder
public class Task {
    private int id;
    private TaskPayload payload;
    // skipping other members
}

@Data
@Builder
public class TaskPayload {
    private PayloadType payloadType;
    private PayloadEncoding payloadEncoding;
    private String data;
}

I am trying to insert a Task element to the table task_queue and return the inserted element.

    <select id="save" parameterType="com.prod.transponder.entity.Task" resultMap="taskResultMap">
        INSERT INTO task_queue(
            payload_type,
            payload_encoding,
            payload_text
        )
        VALUES
            (
                #{payload.payloadType},
                #{payload.payloadEncoding},
                #{payload.data}
            )
        RETURNING *
    </select>

    <resultMap id="taskPayloadMap" type="com.prod.transponder.model.TaskPayload">
        <result column="payload_encoding" property="payloadEncoding" />
        <result column="payload_type" property="payloadType"/>
        <result column="payload_text" property="data"/>
    </resultMap>

    <resultMap id="taskResultMap" type="com.prod.transponder.entity.Task">
        <id column="id" property="id"/>
        <association property="payload" resultMap="taskPayloadMap"/>
    </resultMap>

But when I test this I get the following error;

Caused by: org.apache.ibatis.executor.result.ResultMapException: Error attempting to get column 'id' from result set.  Cause: java.lang.IllegalArgumentException: No enum constant com.prod.transponder.constants.PayloadType.2

2 is the autogenerated Id of the inserted element.

1

There are 1 best solutions below

0
mig001 On

The error itself is not intuitive enough to solve this issue. The actual problem lies with Lombok's annotations. Mybatis is using Reflection to set values to fields. It needs a no-argument constructor (or no constructor at all) to map the values of the member object. So adding the @NoArgsConstructor annotation on top of the TaskPayload should solve the problem. But since @Builder requires a constructor with all members, one must add @AllArgsConstructor also. Hence modifying TaskPayload like this will fix the issue;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class TaskPayload {
    private PayloadType payloadType;
    private PayloadEncoding payloadEncoding;
    private String data;
}

Also, defining the resultMap is unnecessary here. Setting Task as resultType should work aswell.