Mybatis XML与注解的比较

9

我已经阅读了Mybatis的书籍和文档,包括XML和注解两种方式,但是从Mybatis官方网站上来看,他们声称XML是更好的Mapper实现方式,因为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;

}

我想知道这个限制是什么?对我来说似乎没有明显的显示。


阅读此文章以了解注释仅限于基于Xml配置与基于注释的配置。就MyBatis而言,文档指出,对于最高级别的映射仍需要XML映射。嵌套连接映射就是其中的一个例子。 - Lucky
还可以阅读有关Mybatis在复杂应用程序中的注释的相关问题。 - Lucky
3个回答

16
在嵌套连接映射之上,Pitchers提到,XML格式的resultMap支持继承,而这在注释中是无法实现的。需要每次重写。此外,@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 Mappers

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引用。

3
现在可以实现@Results的重用。如果您在@Results中提供了一个id,则可以从@ResultMap中引用它。 请参阅文档GitLab问题 - Stim

3

是的,Mybatis 的文档提醒我们,在小型、简单的项目中,注解可以更简单易读。但是,与 XML 配置相比,注解存在一定的限制。如果您的项目包含复杂对象或复杂的数据库结构,请考虑使用 XML 配置而不是 Java 注解。

在 MyBatis 中,最高级别的映射如嵌套连接映射仍然需要使用 XML 映射。


1
我相信注解可以实现嵌套的连接映射,不是吗? - user5324782

1
有很多情况下,使用 .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>

这种方法不容易出错,而且复制/粘贴的情况也少得多(你可以在这里查看)。
条件、迭代等也应该被提到。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接