SpringBoot整合MyBatis教程(註解版)

本教程主要詳細講解SpringBoot整合MyBatis進行數據庫操作,本次講解我們使用純註解方式進行。

基礎環境


技術 版本
Java 1.8+
SpringBoot 2.x.x
MyBatis 3.5.x

創建項目


  • 初始化項目
mvn archetype:generate -DgroupId=com.edurt.sli.slisma -DartifactId=spring-learn-integration-springboot-mybatis-annotations-DarchetypeArtifactId=maven-archetype-quickstart -Dversion=1.0.0 -DinteractiveMode=false
  • 修改pom.xml增加MyBatis
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <parent>
        <artifactId>spring-learn-integration-springboot-mybatis</artifactId>
        <groupId>com.edurt.sli</groupId>
        <version>1.0.0</version>
    </parent>

    <modelVersion>4.0.0</modelVersion>

    <artifactId>spring-learn-integration-springboot-mybatis-annotations</artifactId>

    <name>SpringBoot整合MyBatis教程(註解版)</name>

    <properties>
        <system.java.version>1.8</system.java.version>
        <plugin.maven.compiler.version>3.3</plugin.maven.compiler.version>
        <springboot.common.version>2.1.3.RELEASE</springboot.common.version>
        <springboot.mybatis.common.version>2.1.1</springboot.mybatis.common.version>
        <mysql.version>5.1.47</mysql.version>
        <lombox.version>1.18.8</lombox.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>${springboot.common.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <version>${springboot.common.version}</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>${springboot.mybatis.common.version}</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.version}</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombox.version}</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>${springboot.common.version}</version>
                <configuration>
                    <fork>true</fork>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${plugin.maven.compiler.version}</version>
                <configuration>
                    <source>${system.java.version}</source>
                    <target>${system.java.version}</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

mybatis-spring-boot-starter:該starter是我們使用SpringBoot整合MyBatis的依賴整合包

  • src/main/java目錄下新建com.edurt.sli.slisma目錄並在該目錄下新建SpringBootMyBatisIntegration類文件,在文件輸入以下內容
package com.edurt.sli.slisma;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.stereotype.Component;

@SpringBootApplication
@Component(value = "com.edurt.sli.slisma")
public class SpringBootMyBatisIntegration {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootMyBatisIntegration.class, args);
    }

}

構建基本使用的SQL文件


src/main目錄下新建example.sql文件,鍵入以下內容

create database spring;

use spring;

drop table if exists user;
create table user (
    id       int(20) auto_increment,
    userName varchar(20),
    primary key (id)
)
    default charset 'utf8';

我們運行該sql文件進行創建數據庫/數據表操作.

配置MyBatis數據源

  • /src/main/java/com/edurt/sli/slisma目錄下創建config目錄,並在該目錄下新建MyBatisConfig配置類,鍵入以下代碼
package com.edurt.sli.slisma.config;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.mybatis.spring.boot.autoconfigure.ConfigurationCustomizer;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;

@Configuration
@MapperScan(value = {"com.edurt.sli.slisma.mapper"})
public class MyBatisConfig {

    @Bean(name = "transactionManager")
    public DataSourceTransactionManager transactionManager(
            @Qualifier("dataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = "sqlSessionFactory")
    @ConditionalOnMissingBean(name = "sqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) throws Exception {
        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        return sessionFactory.getObject();
    }

    @Bean
    ConfigurationCustomizer mybatisConfigurationCustomizer() {
        return configuration -> {
            configuration.setMapUnderscoreToCamelCase(Boolean.TRUE);
            configuration.setLogPrefix("com.edurt.sli.slismat");
        };
    }

}

該代碼中有3個Bean分別是:transactionManager(用於構建事務管理器),sqlSessionFactory(用於構建sqlSession工廠提供查詢操作),mybatisConfigurationCustomizer(定製化MyBatis信息)

@MapperScan註解用於指定我們Mapper文件所在的位置

配置Mapper支持數據插入(@Insert)


  • /src/main/java/com/edurt/sli/slisma目錄下創建model目錄,並在該目錄下新建UserModel實體類,鍵入以下代碼
package com.edurt.sli.slisma.model;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class UserModel {

    private Integer id;
    private String userName;

}
  • /src/main/java/com/edurt/sli/slisma目錄下創建mapper目錄,並在該目錄下新建UserMapper映射類,用於映射數據庫和實體類,鍵入以下代碼
package com.edurt.sli.slisma.mapper;

import com.edurt.sli.slisma.model.UserModel;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Options;
import org.apache.ibatis.annotations.Param;

@Mapper
public interface UserMapper {

    @Insert("INSERT INTO user (username) VALUES (#{user.userName})")
    @Options(useGeneratedKeys = true, keyColumn = "id", keyProperty = "user.id")
    Integer insertModel(@Param(value = "user") UserModel model);

}

我們在Mapper中提供了一個添加數據方法,我們使用到了@Insert@Options註解

@Insert註解用於標誌我們要進行數據插入操作

@Options該註解比較特殊,主要是用於標記我們對插入後返回數據的操作,比如我們指定了useGeneratedKeys=truekeyColumn = “id”,這樣的話我們插入數據的時候會自動生成主鍵,keyProperty = "user.id"標記着我們插入數據成功後返回當前插入數據庫表中的id數據.需要注意的是我們如果在傳遞參數的時候使用@Param修飾參數後,那麼keyProperty需要指定修飾的域名,如果未進行修飾的話,我們可以直接使用實體類中的字段名稱.

  • 接下來我們在/src/test/java目錄下新建com.edurt.sli.slisma目錄,並在該目錄下新建UserMapperTest測試文件,鍵入以下內容
package com.edurt.sli.slisma.mapper;

import com.edurt.sli.slisma.SpringBootMyBatisIntegration;
import com.edurt.sli.slisma.model.UserModel;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@SpringBootTest(
        classes = SpringBootMyBatisIntegration.class,
        webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT
)
public class UserMapperTest {

    private UserModel user;
    private String value = "UserMapperTest";

    @Autowired
    private UserMapper userMapper;

    @Before
    public void before() {
        user = new UserModel();
        user.setUserName(value);
    }

    @After
    public void after() {

    }

    @Test
    public void testInsertModel() {
        Assert.assertTrue(this.userMapper.insertModel(user) > 0);
    }

}

我們在@Before中初始化了一個新的實體信息

然後使用testInsertModel方法進行測試我們UserMapper提供的插入數據方法是否有效

  • /src/main/resources資源目錄下創建一個application.properties的配置文件,用於數據庫連接配置,鍵入以下內容
server.port=8989
spring.datasource.url=jdbc:mysql://localhost:3306/spring?useSSL=false
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=123456

此時我們直接運行單元測試便可看到數據庫表中新增的數據信息

數據查詢操作(@Select)


  • UserMapper文件中鍵入以下內容支持查詢操作
@Results(value = {
        @Result(property = "id", column = "id", id = true),
        @Result(property = "userName", column = "username")
})
@Select(value = "SELECT id, username FROM user WHERE username = #{userName}")
UserModel findByUserName(@Param(value = "userName") String userName);

將頂部引入的包import org.apache.ibatis.annotations.XXXX修改爲import org.apache.ibatis.annotations.*

  • UserMapperTest文件中鍵入以下內容支持數據查詢測試
@Test
public void testFindByUserName() {
    Assert.assertNotNull(this.userMapper.findByUserName(value));
}

然後使用testFindByUserName方法進行測試我們UserMapper提供的查詢數據方法是否有效

數據查詢操作(@Select)動態條件判斷


我要想使用類似xml中的if-else的話我們需要用到<script></script>區間塊標誌.

  • 修改UserMapper文件中鍵入以下內容支持自定義script查詢操作
@Results(value = {
        @Result(property = "id", column = "id", id = true),
        @Result(property = "userName", column = "username")
})
@Select(value = "<script>" +
        "SELECT id, username FROM user WHERE 1=1" +
        "<if test='userName != null'> and username=#{userName} </if>" +
        "</script>")
UserModel findByUserNameAndCustomScript(@Param(value = "userName") String userName);

我們在<script></script>區間塊可以使用xml配置中的if語句

  • UserMapperTest文件中鍵入以下內容支持自定義腳本數據查詢測試
@Test
public void testFindByUserNameAndCustomScript() {
    Assert.assertNotNull(this.userMapper.findByUserNameAndCustomScript(value));
}

注意: 如果字段類型是String的話test裏面的字符串必需要轉義,如果使用單引號的話是不支持的

數據查詢操作(@Select)共享Results結果數據


在實際開發中很多時候我們在不同的方法中會返回相同的結果信息,那麼這個時候我們就要使用到了共享Results結果數據,共享結果數據很簡單,我們只需要修改@Results在裏面增加id屬性(該id值是唯一的)後期在其他方法中使用即可.

  • 修改UserMapper文件中的findByUserName方法在@Results中增加id屬性,內容如下
@Results(id = "userRequiredResults", value = {
        @Result(property = "id", column = "id", id = true),
        @Result(property = "userName", column = "username")
})
@Select(value = "SELECT id, username FROM user WHERE username = #{userName}")
UserModel findByUserName(@Param(value = "userName") String userName);

我們定義了一個id爲userRequiredResults的返回全局結果集

  • 修改UserMapper文件中鍵入以下內容支持共享結果查詢操作
@ResultMap(value = "userRequiredResults")
@Select(value = "<script>" +
        "SELECT id, username FROM user WHERE 1=1" +
        "<if test='userName != null'> and username=#{userName} </if>" +
        "</script>")
UserModel findByUserNameAndCommonResult(@Param(value = "userName") String userName);

注意此時我們使用的是@ResultMap註解,該註解只有一個屬性,那就是value,指定的是我們需要使用的是返回哪個數據結果集

  • UserMapperTest文件中鍵入以下內容支持共享結果集數據查詢測試
    @Test
public void testFindByUserNameAndCommonResult() {
    Assert.assertNotNull(this.userMapper.findByUserNameAndCommonResult(value));
}

關於分頁的功能,我們後續會有單獨文章詳解

數據修改操作(@Update)


  • UserMapper文件中鍵入以下內容支持修改操作
@Update(value = "UPDATE user SET userName = #{user.userName} WHERE id = #{user.id}")
void updateModel(@Param(value = "user") UserModel model);
  • UserMapperTest文件中鍵入以下內容支持數據修改測試
@Test
public void testUpdateModel() {
    user.setId(1);
    user.setUserName("Modify");
    this.userMapper.updateModel(user);
}

運行我們的測試示例,在此查詢即可看到數據已經被修改

目前@Update值只支持返回受影響的行數,只需要修改返回值爲Integer類型即可,不需要的話直接設置爲void

數據刪除操作(@Delete)


  • UserMapper文件中鍵入以下內容支持刪除操作
@Delete(value = "DELETE FROM user WHERE id = #{id}")
Integer deleteModel(@Param(value = "id") Integer id);
  • UserMapperTest文件中鍵入以下內容支持數據刪除測試
@Test
public void testDeleteModel() {
    this.userMapper.deleteModel(1);
}

目前@Delete值只支持返回受影響的行數,只需要修改返回值爲Integer類型即可,不需要的話直接設置爲void

在MyBatis中@Select, @Update, @Delete, @Insert都是支持自定義script的

打包文件部署


  • 打包數據
mvn clean package -Dmaven.test.skip=true -X

運行打包後的文件即可

java -jar target/spring-learn-integration-springboot-mybatis-annotations-1.0.0.jar

源碼地址


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章