Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 466
user5324782 Avatar asked Sep 17 '15 13:09

user5324782


People also ask

Which is better annotation or XML in spring?

From my own experience annotations better than xml configuration. I think in any case you can override xmls and use annotations. Also Spring 4 give us a huge support for annotations, we can override security from xml to annotations e.t.c, so we will have not 100 lines xml but 10 lines Java Code.

What is the difference between iBATIS and MyBatis?

MyBatis is a fork from iBATIS, and according to Wikipedia most of iBATIS' developers moved over to MyBatis too. The iBATIS project is currently marked as Inactive, therefore you should go with MyBatis for new projects and only use iBATIS if you're maintaining an existing project which already uses iBATIS.

How does MyBatis work?

MyBatis is an open source persistence framework which simplifies the implementation of database access in Java applications. It provides the support for custom SQL, stored procedures and different types of mapping relations. Simply put, it's an alternative to JDBC and Hibernate.

What is Mapper XML?

Mapper XML is an important file in MyBatis, which contains a set of statements to configure various SQL statements such as select, insert, update, and delete. These statements are known as Mapped Statements or Mapped SQL Statements. All the statements have unique id.


3 Answers

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

like image 139
Junchen Liu Avatar answered Oct 21 '22 15:10

Junchen Liu


Yes,the documentation for Mybatis cautions that annotations can be much simpler and easier to read for smaller, simpler projects. However, annotations are limited compared to the XML configuration. If your project includes complex objects or a complex database structure, consider using the XML configuration instead of the Java annotations.

XML mapping is still required for the most advanced mappings like Nested Join Mapping in MyBatis.

like image 3
Bacteria Avatar answered Oct 21 '22 15:10

Bacteria


There are plenty use cases when using .xml can be much more consice and cleaner approach. Say, you can create some Common.xml, define a bunch of queries, like

 <sql id="inStmt">
    IN
    <foreach item="id" collection="ids" separator="," open="(" close=")">
        #{id}
    </foreach>
</sql>

and reuse this code in your project.

Moreover, the template query can be defined, e.g.:

<sql id="selectDistinct">
    SELECT DISTINCT(${column}), #{param}
    FROM ${entityTable}
</sql>

And then you can reference it via

 <include refid="Common.selectDistinct">
        <property name="column" value="id"/>
        <property name="entityTable" value="some_table"/>
 </include>

This approach is less error-prone and much less copy/pasted. (you can have a look here).

Conditions, iterating, etc should also be mentioned, too.

like image 1
Alexander Davliatov Avatar answered Oct 21 '22 16:10

Alexander Davliatov