Mybatis XML vs 注解

Mybatis XML vs Annotation

我看过关于Mybatis的书和文档,XML和Annotation都是我想要的,但是从myBatis官方网站上,他们声称XML是做Mappers的更好方法,因为Java 注释有局限性。

我个人更喜欢注释,例如

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;

}

请问限制是什么?对我来说似乎没有什么是显而易见的。

是的,Mybatis 的文档警告说,对于更小、更简单的项目,注释可以更简单、更容易阅读。但是,与 XML 配置相比,注释是有限的。如果您的项目包含复杂对象或复杂数据库结构考虑使用XML配置而不是Java注释 .

XML映射对于像MyBatis中的Nested Join Mapping这样最高级的映射仍然是必需的

在Pitchers说的Nested Join Mapping之上,XML格式的resultMap支持继承,这是annotation无法做到的,每次都要rewrite。 @Results 注释也是 Mapper XML 元素 <resultMap> 的对应项。但是,从 MyBatis 3.2.2 开始,我们无法为 @Results 注解提供 ID。因此,与 <resultMap> XML 元素不同,我们不能在不同的映射语句中重用 @Results 声明。这意味着您需要复制 @Results 配置,即使它是相同的。例如,请参阅以下 findStudentBy()findAllStudents() 方法:

@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();

这里的@Results配置对于两个语句都是相同的,但我们需要复制它。也有解决此问题的方法。我们可以创建一个 Mapper XML 文件并配置 <resultMap> 元素并使用 @ResultMap 注释引用 resultMap

StudentMapper.xml.

中使用 ID StudentResult 定义 <resultMap>
<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 使用注释的映射器

StudentMapper.java 中,使用 @ResultMap 引用 resultMap 属性 StudentResult

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();

引自Java-Persistence-with-MyBatis3

使用 .xml 有很多用例可以是更简洁、更简洁的方法。 比如说,你可以创建一些 Common.xml,定义一堆查询,比如

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

并在您的项目中重用此代码。

此外,还可以定义模板查询,例如:

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

然后您可以通过

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

这种方法更不容易出错,而且更少 copy/pasted。 (大家可以看看here

还应提及条件、迭代等。