java Mybatis XML 与注解

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32631438/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 20:31:59  来源:igfitidea点击:

Mybatis XML vs Annotation

javamybatisibatis

提问by user5324782

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.

我已经阅读了有关 Mybatis 的书籍和文档,XML 和 Annotation 都做了我想要的,但是从 myBatis 官方网站,他们声称 XML 是一种更好的 Mappers 方式,因为 Java 注释有局限性。

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.

我想知道限制是什么?在我看来,没有什么是显而易见的。

回答by Junchen Liu

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

在Pitchers所说的Nested Join Mapping之上,resultMapXML格式支持继承,这是annotation无法实现的,每次都要重写。此外,@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();

Here the @Resultsconfiguration 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 resultMapusing the @ResultMapannotation.

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

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

定义<resultMap>与ID StudentResult在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

使用注解的 SQL 映射器

In StudentMapper.java, reference the resultMapattribute StudentResultusing @ResultMap.

在 中StudentMapper.java,使用引用resultMap属性。StudentResult@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

引用自 Java-Persistence-with-MyBatis3

回答by Bacteria

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.

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

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

像MyBatis 中的Nested Join Mapping这样最高级的映射仍然需要 XML 映射。

回答by Alexander Davliatov

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

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

 <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.

还应该提到条件、迭代等。