Search code examples
javamybatisibatis

Mybatis XML vs Annotation


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.


Solution

  • 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