Quick Guide to MyBatis – MyBatis快速指南

最后修改: 2017年 4月 19日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.介绍

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.

MyBatis是一个开源的持久性框架,它简化了Java应用程序中数据库访问的实现。它提供了对自定义SQL、存储过程和不同类型的映射关系的支持。

Simply put, it’s an alternative to JDBC and Hibernate.

简单地说,它是JDBC和Hibernate的替代品。

2. Maven Dependencies

2.Maven的依赖性

To make use of MyBatis we need to add the dependency to our pom.xml:

为了使用MyBatis,我们需要在我们的pom.xml中添加依赖性:

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.4</version>
</dependency>

The latest version of the dependency can be found here.

最新版本的依赖关系可以在这里找到。

3. Java APIs

3.Java APIs[/strong]

3.1. SQLSessionFactory

3.1.SQLSessionFactory

SQLSessionFactory is the core class for every MyBatis application. This class is instantiated by using SQLSessionFactoryBuilder’s builder() method which loads a configuration XML file:

SQLSessionFactory是每个MyBatis应用程序的核心类。这个类是通过使用SQLSessionFactoryBuilders builder() 方法来实例化的,该方法加载了一个配置XML文件。

String resource = "mybatis-config.xml";
InputStream inputStream Resources.getResourceAsStream(resource);
SQLSessionFactory sqlSessionFactory
  = new SqlSessionFactoryBuilder().build(inputStream);

The Java configuration file includes settings like data source definition, transaction manager details, and a list of mappers which define relations between entities, these together are used to build the SQLSessionFactory instance:

Java配置文件包括数据源定义、事务管理器细节和定义实体间关系的映射器列表等设置,这些都被用来构建SQLSessionFactory实例。

public static SqlSessionFactory buildqlSessionFactory() {
    DataSource dataSource 
      = new PooledDataSource(DRIVER, URL, USERNAME, PASSWORD);

    Environment environment 
      = new Environment("Development", new JdbcTransactionFactory(), dataSource);
        
    Configuration configuration = new Configuration(environment);
    configuration.addMapper(PersonMapper.class);
    // ...

    SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
    return builder.build(configuration);
}

3.2. SQLSession

3.2.SQLSession

SQLSession contains methods for performing database operations, obtaining mappers and managing transactions. It can be instantiated from SQLSessionFactory class. Instances of this class are not thread-safe.

SQLSession包含了用于执行数据库操作、获取映射器和管理事务的方法。它可以从SQLSessionFactory类中实例化。这个类的实例不是线程安全的。

After performing the database operation the session should be closed. Since SqlSession implements the AutoCloseable interface, we can use the try-with-resources block:

在执行数据库操作之后,会话应该被关闭。由于SqlSession实现了AutoCloseable接口,我们可以使用try-with-resources块。

try(SqlSession session = sqlSessionFactory.openSession()) {
    // do work
}

4. Mappers

4.绘图者

Mappers are Java interfaces that map methods to the corresponding SQL statements. MyBatis provides annotations for defining database operations:

映射器是Java接口,将方法映射到相应的SQL语句。MyBatis为定义数据库操作提供注解。

public interface PersonMapper {

    @Insert("Insert into person(name) values (#{name})")
    public Integer save(Person person);

    // ...

    @Select(
      "Select personId, name from Person where personId=#{personId}")
    @Results(value = {
      @Result(property = "personId", column = "personId"),
      @Result(property="name", column = "name"),
      @Result(property = "addresses", javaType = List.class,
        column = "personId", many=@Many(select = "getAddresses"))
    })
    public Person getPersonById(Integer personId);

    // ...
}

5. MyBatis Annotations

5.MyBatis注解

Let’s see some of the main annotations provided by MyBatis:

让我们看看MyBatis提供的一些主要注释。

  • @Insert, @Select, @Update, @Deletethose annotations represent SQL statements to be executed by calling annotated methods:
    @Insert("Insert into person(name) values (#{name})")
    public Integer save(Person person);
    
    @Update("Update Person set name= #{name} where personId=#{personId}")
    public void updatePerson(Person person);
    
    @Delete("Delete from Person where personId=#{personId}")
    public void deletePersonById(Integer personId);
    
    @Select("SELECT person.personId, person.name FROM person 
      WHERE person.personId = #{personId}")
    Person getPerson(Integer personId);
  • @Results – it is a list of result mappings that contain the details of how the database columns are mapped to Java class attributes:
    @Select("Select personId, name from Person where personId=#{personId}")
    @Results(value = {
      @Result(property = "personId", column = "personId")
        // ...   
    })
    public Person getPersonById(Integer personId);
  • @Result – it represents a single instance of Result out of the list of results retrieved from @Results. It includes the details like mapping from database column to Java bean property, Java type of the property and also the association with other Java objects:
    @Results(value = {
      @Result(property = "personId", column = "personId"),
      @Result(property="name", column = "name"),
      @Result(property = "addresses", javaType =List.class) 
        // ... 
    })
    public Person getPersonById(Integer personId);
  • @Manyit specifies a mapping of one object to a collection of the other objects:
    @Results(value ={
      @Result(property = "addresses", javaType = List.class, 
        column = "personId",
        many=@Many(select = "getAddresses"))
    })

    Here getAddresses is the method which returns the collection of Address by querying Address table.

    这里getAddresses是通过查询地址表返回Address集合的方法。

    @Select("select addressId, streetAddress, personId from address 
      where personId=#{personId}")
    public Address getAddresses(Integer personId);

    Similar to @Many annotation, we have @One annotation which specifies the one to one mapping relationship between objects.

    @Many 注解类似,我们有@One 注解,它指定了对象之间的一对一映射关系。

  • @MapKeythis is used to convert the list of records to Map of records with the key as defined by value attribute:
    @Select("select * from Person")
    @MapKey("personId")
    Map<Integer, Person> getAllPerson();
  • @Optionsthis annotation specifies a wide range of switches and configuration to be defined so that instead of defining them on other statements we can @Options to define them:
    @Insert("Insert into address (streetAddress, personId) 
      values(#{streetAddress}, #{personId})")
    @Options(useGeneratedKeys = false, flushCache=true)
    public Integer saveAddress(Address address);

6. Dynamic SQL

6.动态SQL

Dynamic SQL is a very powerful feature provided by MyBatis. With this, we can structure our complex SQL with accuracy.

动态SQL是MyBatis提供的一个非常强大的功能。有了它,我们可以准确地构造我们复杂的SQL。

With traditional JDBC code, we have to write SQL statements, concatenate them with the accuracy of spaces between them and putting the commas at right places. This is very error prone and very difficult to debug, in the case of large SQL statements.

在传统的JDBC代码中,我们必须编写SQL语句,将它们串联起来,并在它们之间准确地添加空格,将逗号放在正确的位置。这很容易出错,而且在大型SQL语句的情况下很难进行调试。

Let’s explore how we can use dynamic SQL in our application:

让我们探讨一下如何在我们的应用程序中使用动态SQL。

@SelectProvider(type=MyBatisUtil.class, method="getPersonByName")
public Person getPersonByName(String name);

Here we have specified a class and a method name which actually constructs and generate the final SQL:

在这里,我们指定了一个类和一个方法名,它实际上是构建和生成最终的SQL。

public class MyBatisUtil {
 
    // ...
 
    public String getPersonByName(String name){
        return new SQL() {{
            SELECT("*");
            FROM("person");
            WHERE("name like #{name} || '%'");
        }}.toString();
    }
}

Dynamic SQL provides all the SQL constructs as a class e.g. SELECT, WHERE etc. With this, we can dynamically change the generation of WHERE clause.

动态SQL将所有的SQL结构作为一个类提供,例如SELECTWHERE等。有了这个,我们可以动态地改变WHERE子句的生成。

7. Stored Procedure Support

7.存储过程支持

We can also execute the stored procedure using @Select annotation. Here we need to pass the name of the stored procedure, the parameter list and use an explicit Call to that procedure:

我们还可以使用@Select注解来执行存储过程。在这里,我们需要传递存储过程的名称、参数列表,并对该存储过程使用明确的Call

@Select(value= "{CALL getPersonByProc(#{personId,
  mode=IN, jdbcType=INTEGER})}")
@Options(statementType = StatementType.CALLABLE)
public Person getPersonByProc(Integer personId);

8. Conclusion

8.结论

In this quick tutorial, we’ve seen the different features provided by MyBatis and how it ease out the development of database facing applications. We have also seen various annotations provided by the library.

在这个快速教程中,我们已经看到了MyBatis提供的不同功能,以及它是如何简化面向数据库的应用程序的开发的。我们还看到了该库所提供的各种注释。

The complete code for this article is available over on GitHub.

本文的完整代码可在GitHub上获得