天天看點

最簡單的SpringBoot整合MyBatis教程

前面兩篇文章和讀者聊了Spring Boot中最簡單的資料持久化方案JdbcTemplate,JdbcTemplate雖然簡單,但是用的并不多,因為它沒有MyBatis友善,在Spring+SpringMVC中整合MyBatis步驟還是有點複雜的,要配置多個Bean,Spring Boot中對此做了進一步的簡化,使MyBatis基本上可以做到開箱即用,本文就來看看在Spring Boot中MyBatis要如何使用。

工程建立

首先建立一個基本的Spring Boot工程,添加Web依賴,MyBatis依賴以及MySQL驅動依賴,如下:

最簡單的SpringBoot整合MyBatis教程

建立成功後,添加Druid依賴,并且鎖定MySQL驅動版本,完整的依賴如下:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.0.0</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.1.10</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.28</version>
    <scope>runtime</scope>
</dependency>
           

如此,工程就算是建立成功了。讀者注意,MyBatis和Druid依賴的命名和其他庫的命名不太一樣,是屬于xxx-spring-boot-stater模式的,這表示該starter是由第三方提供的。

基本用法

MyBatis的使用和JdbcTemplate基本一緻,首先也是在application.properties中配置資料庫的基本資訊:

spring.datasource.url=jdbc:mysql:///test01?useUnicode=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
           

配置完成後,MyBatis就可以建立Mapper來使用了,例如我這裡直接建立一個UserMapper2,如下:

public interface UserMapper2 {
    @Select("select * from user")
    List<User> getAllUsers();

    @Results({
            @Result(property = "id", column = "id"),
            @Result(property = "username", column = "u"),
            @Result(property = "address", column = "a")
    })
    @Select("select username as u,address as a,id as id from user where id=#{id}")
    User getUserById(Long id);

    @Select("select * from user where username like concat('%',#{name},'%')")
    List<User> getUsersByName(String name);

    @Insert({"insert into user(username,address) values(#{username},#{address})"})
    @SelectKey(statement = "select last_insert_id()", keyProperty = "id", before = false, resultType = Integer.class)
    Integer addUser(User user);

    @Update("update user set username=#{username},address=#{address} where id=#{id}")
    Integer updateUserById(User user);

    @Delete("delete from user where id=#{id}")
    Integer deleteUserById(Integer id);
}
           

這裡是通過全注解的方式來寫SQL,不寫XML檔案,@Select、@Insert、@Update以及@Delete四個注解分别對應XML中的select、insert、update以及delete标簽,@Results注解類似于XML中的ResultMap映射檔案(getUserById方法給查詢結果的字段取别名主要是向小夥伴們示範下

@Results

注解的用法),另外使用@SelectKey注解可以實作主鍵回填的功能,即當資料插入成功後,插入成功的資料id會指派到user對象的id屬性上。

UserMapper2建立好之後,還要配置mapper掃描,有兩種方式,一種是直接在UserMapper2上面添加

@Mapper

注解,這種方式有一個弊端就是所有的Mapper都要手動添加,要是落下一個就會報錯,還有一個一勞永逸的辦法就是直接在啟動類上添加Mapper掃描,如下:

@SpringBootApplication
@MapperScan(basePackages = "org.sang.mybatis.mapper")
public class MybatisApplication {
    public static void main(String[] args) {
        SpringApplication.run(MybatisApplication.class, args);
    }
}
           

好了,做完這些工作就可以去測試Mapper的使用了。

mapper映射

當然,開發者也可以在XML中寫SQL,例如建立一個UserMapper,如下:

public interface UserMapper {
    List<User> getAllUser();

    Integer addUser(User user);

    Integer updateUserById(User user);

    Integer deleteUserById(Integer id);
}
           

然後建立UserMapper.xml檔案,如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.sang.mybatis.mapper.UserMapper">
    <select id="getAllUser" resultType="org.sang.mybatis.model.User">
        select * from t_user;
    </select>
    <insert id="addUser" parameterType="org.sang.mybatis.model.User">
        insert into user (username,address) values (#{username},#{address});
    </insert>
    <update id="updateUserById" parameterType="org.sang.mybatis.model.User">
        update user set username=#{username},address=#{address} where id=#{id}
    </update>
    <delete id="deleteUserById">
        delete from user where id=#{id}
    </delete>
</mapper>
           

将接口中方法對應的SQL直接寫在XML檔案中。

那麼這個UserMapper.xml到底放在哪裡呢?有兩個位置可以放,第一個是直接放在UserMapper所在的包下面:

最簡單的SpringBoot整合MyBatis教程

放在這裡的UserMapper.xml會被自動掃描到,但是有另外一個Maven帶來的問題,就是java目錄下的xml資源在項目打包時會被忽略掉,是以,如果UserMapper.xml放在包下,需要在pom.xml檔案中再添加如下配置,避免打包時java目錄下的XML檔案被自動忽略掉:

<build>
    <resources>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.xml</include>
            </includes>
        </resource>
        <resource>
            <directory>src/main/resources</directory>
        </resource>
    </resources>
</build>
           

當然,UserMapper.xml也可以直接放在resources目錄下,這樣就不用擔心打包時被忽略了,但是放在resources目錄下,又不能自動被掃描到,需要添加額外配置。例如我在resources目錄下建立mapper目錄用來放mapper檔案,如下:

最簡單的SpringBoot整合MyBatis教程

此時在application.properties中告訴mybatis去哪裡掃描mapper:

mybatis.mapper-locations=classpath:mapper/*.xml
           

如此配置之後,mapper就可以正常使用了。注意第二種方式不需要在pom.xml檔案中配置檔案過濾。

原理分析

在SSM整合中,開發者需要自己提供兩個Bean,一個SqlSessionFactoryBean,還有一個是MapperScannerConfigurer,在Spring Boot中,這兩個東西雖然不用開發者自己提供了,但是并不意味着這兩個Bean不需要了,在

org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration

類中,我們可以看到Spring Boot提供了這兩個Bean,部分源碼如下:

@org.springframework.context.annotation.Configuration
@ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class })
@ConditionalOnSingleCandidate(DataSource.class)
@EnableConfigurationProperties(MybatisProperties.class)
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
public class MybatisAutoConfiguration implements InitializingBean {

  @Bean
  @ConditionalOnMissingBean
  public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
    SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
    factory.setDataSource(dataSource);
    return factory.getObject();
  }
  @Bean
  @ConditionalOnMissingBean
  public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
    ExecutorType executorType = this.properties.getExecutorType();
    if (executorType != null) {
      return new SqlSessionTemplate(sqlSessionFactory, executorType);
    } else {
      return new SqlSessionTemplate(sqlSessionFactory);
    }
  }
  @org.springframework.context.annotation.Configuration
  @Import({ AutoConfiguredMapperScannerRegistrar.class })
  @ConditionalOnMissingBean(MapperFactoryBean.class)
  public static class MapperScannerRegistrarNotFoundConfiguration implements InitializingBean {

    @Override
    public void afterPropertiesSet() {
      logger.debug("No {} found.", MapperFactoryBean.class.getName());
    }
  }
}
           

從類上的注解可以看出,當目前類路徑下存在SqlSessionFactory、 SqlSessionFactoryBean以及DataSource時,這裡的配置才會生效,SqlSessionFactory和SqlTemplate都被提供了。為什麼要看這段代碼呢?下篇文章,松哥和大夥分享Spring Boot中MyBatis多資料源的配置時,這裡将是一個重要的參考。

好了,本文就先說到這裡,

繼續閱讀