Mybatis XML vs Annotation

user5324782 picture user5324782 · Sep 17, 2015 · Viewed 12.6k times · Source

I have read the book and documentation about Mybatis, both XML and Annotation does what I want, but from myBatis official website, they claim XML is a better way of doing Mappers, because Java annotation has limitations.

I personally prefer Annotations e.g

public interface PersonDAO {

    String INSERT_PERSON = "insert into person (title,firstName,surName,jobTitle,dob,email,mobile,landPhone,fax,twitter,facebook,linkedin) VALUES  (#{title},#{firstName},#{surName},#{jobTitle},#{dob},#{email},#{mobile},#{landPhone},#{fax},#{twitter},#{facebook},#{linkedin})";
    String UPDATE_PERSON = "update person set title=#{title},firstName=#{firstName},surName=#{surName},jobTitle=#{jobTitle},dob=#{dob},email=#{email},mobile=#{mobile},landPhone=#{landPhone},fax=#{fax},twitter=#{twitter},facebook=#{facebook},linkedin=#{linkedin} where id=#{id}";
    String GET_PERSON_BY_ID = "SELECT * FROM vw_person WHERE id = #{personId}";
    String DELETE_PERSON = "DELETE FROM person WHERE id = #{personId}";

    @Select(GET_PERSON_BY_ID)
    public PersonVO doSelectPerson(long personId) throws Exception;

    @Update(UPDATE_PERSON)@Options(flushCache = true, useCache = true)
    public int doUpdatePerson(PersonVO vo) throws Exception;


    @Insert(INSERT_PERSON)@Options(useGeneratedKeys = true, keyProperty = "id", flushCache = true)
    public int doCreatePerson(PersonVO person) throws Exception;

    @Delete(DELETE_PERSON)@Options(flushCache = true)
    public int doDeletePerson(long personId) throws Exception;

}

I wonder what the limitation is? Nothing seems to appear obvious to me.

Answer

Junchen Liu picture Junchen Liu · Sep 18, 2015

On top of Nested Join Mapping that Pitchers said, resultMap in XML format supports inheritance, which can not be achieved in annotation, you have do rewrite each time. Also the @Results annotation is a counterpart of the Mapper XML element <resultMap>. However, as of MyBatis 3.2.2 we can't give an ID for the @Results annotation. So unlike the <resultMap> XML element, we can't reuse the @Results declaration across different mapped statements. What this means is that you need to duplicate the @Results configuration even though it is the same. For example, see the following findStudentBy() and findAllStudents() methods:

@Select("SELECT * FROM STUDENTS WHERE STUD_ID=#{studId}")
@Results({
  @Result(id=true, column="stud_id", property="studId"),
  @Result(column="name", property="name"),
  @Result(column="email", property="email"),
  @Result(column="addr_id", property="address.addrId")
})
Student findStudentById(int studId);

@Select("SELECT * FROM STUDENTS")
@Results({
  @Result(id=true, column="stud_id", property="studId"),
  @Result(column="name", property="name"),
  @Result(column="email", property="email"),
  @Result(column="addr_id", property="address.addrId")
})
List<Student> findAllStudents();

Here the @Results configuration is same for both the statements, but we need to duplicate it. There is also a work around for this problem. We can create a Mapper XML file and configure the <resultMap> element and reference that resultMap using the @ResultMap annotation.

Define <resultMap> with ID StudentResult in StudentMapper.xml.

<mapper namespace="com.mybatis3.mappers.StudentMapper">
  <resultMap type="Student" id="StudentResult">
    <id property="studId" column="stud_id"/>
    <result property="name" column="name"/>
    <result property="email" column="email"/>
    <result property="phone" column="phone"/>
  </resultMap>
</mapper>

SQL Mappers Using Annotations

In StudentMapper.java, reference the resultMap attribute StudentResult using @ResultMap.

public interface StudentMapper

@Select("SELECT * FROM STUDENTS WHERE STUD_ID=#{studId}")
@ResultMap("com.mybatis3.mappers.StudentMapper.StudentResult")
Student findStudentById(int studId);

@Select("SELECT * FROM STUDENTS")
@ResultMap("com.mybatis3.mappers.StudentMapper.StudentResult")
List<Student> findAllStudents();

quote from Java-Persistence-with-MyBatis3