SpringBoot整合Mybatis示例

前言

Spring Boot是最近幾年火起來的一個開源框架,經過使用特定方式的配置快速搭建應用開發項目(Spring原來強大並且噁心的xml配置,相信很多人配置過一次就不想搞第二次吧)。java

開發人員經過starter(啓動器)引入所需模塊,無需過度關注其中的依賴處理,Spring Boot會自動發現和組織其中的bean以及自動獲取相關配置。mysql

本示例項目介紹如何在Spring Boot項目中整合Mybatis模塊(使用阿里 druid數據源開源項目),另外在項目中log4j2替換Spring Boot默認日誌模塊、使用MyBatis Generator插件生成Mybatis相關代碼。git


進入正題

>>建立項目

建立一個普通的Maven webapp項目,很簡單,因此...過程略...github

>>添加Maven依賴

在pom.xml文件中添加對應的依賴,需注意的是本人使用jetty替換tomcat容器、使用log4j2替換默認的logback,因此引入spring-boot-starter-web的時候排除累tomcat、logging的starter,不須要可自行調整。具體見如下代碼及註釋。web

在build標籤內增長mybatis-generator-maven-plugin插件,用於生成Mybatis的Model、mapper等文件,程序猿偷懶專用。spring

pom.xmlsql

<?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">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.cent</groupId>
    <artifactId>springBootDemo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.4.0.RELEASE</version>
    </parent>

    <properties>
        <org.mybatis.spring.boot.version>1.1.1</org.mybatis.spring.boot.version>
        <org.aspectj.version>1.6.11</org.aspectj.version>
        <com.alibaba.druid.version>1.0.5</com.alibaba.druid.version>
        <mysql.connector.version>5.1.38</mysql.connector.version>
        <org.mybatis.generator.version>1.3.5</org.mybatis.generator.version>
        <org.spring.framework.orm.version>3.1.0.RELEASE</org.spring.framework.orm.version>
        <com.github.pagehelper.version>4.1.6</com.github.pagehelper.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <!-- 去除tomcat starter -->
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
                <!-- 去除logback starter -->
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
                <!-- 去除jdbc starter -->
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-jdbc</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!-- 使用jetty starter -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jetty</artifactId>
        </dependency>

        <!-- 使用actuator starter(監控和管理模塊) -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <!-- 引入mybatis -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>${org.mybatis.spring.boot.version}</version>
        </dependency>

        <!-- mybatis分頁插件 -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>${com.github.pagehelper.version}</version>
        </dependency>
        <!-- sql解析(mybatis分頁插件需依賴) -->
        <dependency>
            <groupId>com.github.jsqlparser</groupId>
            <artifactId>jsqlparser</artifactId>
            <version>0.9.6</version>
        </dependency>

        <!-- log4j2 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>${org.aspectj.version}</version>
        </dependency>

        <!-- mysql 驅動 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.connector.version}</version>
        </dependency>

        <!-- 數據庫鏈接池(阿里druid開源項目) -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>${com.alibaba.druid.version}</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <!-- mybatis代碼生成器 -->
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>${org.mybatis.generator.version}</version>
                <configuration>
                    <verbose>true</verbose>
                    <overwrite>true</overwrite>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

>>數據源配置

  1. 在src/main/resource路徑下添加jdbc.properties文件,保存數據源相關配置。

jdbc.properties數據庫

demo.jdbc.url=jdbc:mysql://localhost:3306/spring_boot_demo
demo.jdbc.username=root
demo.jdbc.password=123456

demo.jdbc.initialSize=1
demo.jdbc.minIdle=1
demo.jdbc.maxActive=20

demo.jdbc.maxWait=60000
demo.jdbc.timeBetweenEvictionRunsMillis=60000
  1. 增長對應的DataSourceProperties類

DataSourceProperties.classapache

package org.cent.springBootDemo.properties;

import org.springframework.boot.context.properties.ConfigurationProperties;

/**
 * 數據源配置類
 * Created by cent on 2016/9/2.
 */
@ConfigurationProperties(locations = "classpath:jdbc.properties", prefix = "demo.jdbc")
public class DataSourceProperties {

    private String url;

    private String username;

    private String password;

    private Integer initialSize;

    private Integer minIdle;

    private Integer maxActive;

    private Long maxWait;

    private Long timeBetweenEvictionRunsMillis;

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Integer getInitialSize() {
        return initialSize;
    }

    public void setInitialSize(Integer initialSize) {
        this.initialSize = initialSize;
    }

    public Integer getMinIdle() {
        return minIdle;
    }

    public void setMinIdle(Integer minIdle) {
        this.minIdle = minIdle;
    }

    public Integer getMaxActive() {
        return maxActive;
    }

    public void setMaxActive(Integer maxActive) {
        this.maxActive = maxActive;
    }

    public Long getMaxWait() {
        return maxWait;
    }

    public void setMaxWait(Long maxWait) {
        this.maxWait = maxWait;
    }

    public Long getTimeBetweenEvictionRunsMillis() {
        return timeBetweenEvictionRunsMillis;
    }

    public void setTimeBetweenEvictionRunsMillis(Long timeBetweenEvictionRunsMillis) {
        this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
    }
}

>>Mybatis配置

  1. 新建MybatisConfig類,用於配置Mybatis相關Bean(SqlSessionFactory、SqlSessionTemplate等)。

MybatisConfig.classjson

package org.cent.springBootDemo.configs;


import com.alibaba.druid.pool.DruidDataSource;
import com.github.pagehelper.PageHelper;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
import org.apache.ibatis.logging.log4j2.Log4j2Impl;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.logging.log4j.Logger;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.TransactionManagementConfigurer;

import java.util.Properties;

/**
 * Mybatis主配置
 * Created by cent on 2016/9/20.
 */
@Configuration
@EnableTransactionManagement//啓用事務控制
@AutoConfigureAfter(DatasourceConfig.class)
@Import(DatasourceConfig.class)//設置爲在數據源以後初始化,防止數據源爲null致使啓動報錯
public class MybatisConfig implements TransactionManagementConfigurer {

    /**
     * 數據源對象
     */
    @Autowired
    private DruidDataSource dataSource;

    /**
     * 數據庫會話工廠bean
     * @return
     */
    @Bean(name = "sqlSessionFactory")
    public SqlSessionFactory sqlSessionFactoryBean() {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setTypeAliasesPackage("org.cent.springBootDemo.entity");
        org.apache.ibatis.session.Configuration configuration=new org.apache.ibatis.session.Configuration();
        configuration.setLogImpl(Log4j2Impl.class);
        bean.setConfiguration(configuration);

        //配置mybatis 分頁插件
        PageHelper pageHelper=new PageHelper();
        Properties properties = new Properties();
        properties.setProperty("dialect","mysql");
        properties.setProperty("params","pageNum=start;pageSize=limit;pageSizeZero=zero;reasonable=heli;count=contsql");
        pageHelper.setProperties(properties);

        try {
            bean.setPlugins(new Interceptor[]{pageHelper});
            return bean.getObject();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    /**
     * 數據庫會話模板bean
     * @param sqlSessionFactory
     * @return
     */
    @Bean
    public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

    /**
     * 事務管理器配置
     * @return
     */
    @Bean
    @Override
    public PlatformTransactionManager annotationDrivenTransactionManager() {
        return new DataSourceTransactionManager(dataSource);
    }

}
  1. 新建MapperScannerConfiguierConfig.class 文件,用於配置Mybatis的Mapper掃描器。
package org.cent.springBootDemo.configs;

import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;

/**
 * Mybatis Mapper掃描配置
 * Created by cent on 2016/9/20.
 */
@Configuration
@AutoConfigureAfter(MybatisConfig.class)
public class MapperScannerConfiguierConfig {

    /**
     * Mybatis mapper掃描器
     * @return
     */
    @Bean
    public MapperScannerConfigurer mapperScannerConfigurer() {
        MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
        mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
        mapperScannerConfigurer.setBasePackage("org.cent.springBootDemo.mapper");
        return mapperScannerConfigurer;
    }
}

>>Spring Boot啓動入口

建立Spring Boot啓動入口Application類,這裏只有啓動的main方法,因此的配置都在其餘的config類配置。

package org.cent.springBootDemo.entrance;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

/**
 * Spring Boot啓動入口
 * Created by cent on 2016/9/2.
 */
@EnableWebMvc
@Configuration
@SpringBootApplication(scanBasePackages = {"org.cent.springBootDemo"})
public class Application extends WebMvcConfigurerAdapter {

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

>>MyBatis generator插件配置

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">


<generatorConfiguration>
    <!--數據庫驅動jar -->
    <classPathEntry location="C:\Users\user\.m2\repository\mysql\mysql-connector-java\5.1.38\mysql-connector-java-5.1.38.jar" />

    <context id="DB2Tables" targetRuntime="MyBatis3">
        <!--去除註釋  -->
        <commentGenerator>
            <property name="suppressAllComments" value="true" />
        </commentGenerator>

        <!--數據庫鏈接 -->
        <jdbcConnection driverClass="com.mysql.jdbc.Driver"
                        connectionURL="jdbc:mysql://localhost:3306/spring_boot_demo"
                        userId="root"
                        password="123456">
        </jdbcConnection>
        <!--默認false
           Java type resolver will always use java.math.BigDecimal if the database column is of type DECIMAL or NUMERIC.
         -->
        <javaTypeResolver >
            <property name="forceBigDecimals" value="false" />
        </javaTypeResolver>

        <!--生成實體類 指定包名 以及生成的地址 (能夠自定義地址,可是路徑不存在不會自動建立  使用Maven生成在target目錄下,會自動建立) -->
        <javaModelGenerator targetPackage="org.cent.springBootDemo.entity" targetProject="src\main\java">
            <property name="enableSubPackages" value="false" />
            <property name="trimStrings" value="true" />
        </javaModelGenerator>
        <!--生成SQLMAP文件 -->
        <sqlMapGenerator targetPackage="mapper"  targetProject="src\main\resources">
            <property name="enableSubPackages" value="false" />
        </sqlMapGenerator>

        <!--生成Dao文件 能夠配置 type="XMLMAPPER"生成xml的dao實現  context id="DB2Tables" 修改targetRuntime="MyBatis3"  -->
        <javaClientGenerator type="ANNOTATEDMAPPER" targetPackage="org.cent.springBootDemo.mapper"  targetProject="src\main\java">
            <property name="enableSubPackages" value="false" />
        </javaClientGenerator>

        <!--對應數據庫表 mysql能夠加入主鍵自增 字段命名 忽略某字段等-->
        <table tableName="sys_user" domainObjectName="User" >
        </table>

    </context>
</generatorConfiguration>

>>生成實體類及Mapper接口

我用的是IDEA IntelliJ,使用Mybatis generator插件的方式以下圖,其餘開發工具相似。

image

>>開發Service
  1. 定義UserService接口

UserService.class

package org.cent.springBootDemo.service;

import com.github.pagehelper.PageInfo;
import org.cent.springBootDemo.entity.User;

/**
 * User服務接口
 * Created by cent on 2016/9/20.
 */
public interface UserService {
    /**
     * 根據ID查找
     * @return
     * @throws Exception
     */
    public User queryById(Integer id) throws Exception;

    /**
     * 獲取分頁數據
     * @param start
     * @param limit
     * @return
     * @throws Exception
     */
    public PageInfo<User> selectPage(int start,int limit) throws Exception;
}
  1. UserService實現類

UserServiceImpl.class

package org.cent.springBootDemo.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.cent.springBootDemo.entity.User;
import org.cent.springBootDemo.entity.UserExample;
import org.cent.springBootDemo.mapper.UserMapper;
import org.cent.springBootDemo.service.UserService;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.Map;

/**
 * User服務接口實現類
 * Created by cent on 2016/9/20.
 */
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private SqlSessionTemplate sqlSessionTemplate;

    @Override
    public User queryById(Integer id) throws Exception {
        UserMapper userMapper = sqlSessionTemplate.getMapper(UserMapper.class);
        return userMapper.selectByPrimaryKey(id);
    }

    public PageInfo<User> selectPage(int start,int limit) throws Exception {
        UserMapper userMapper = sqlSessionTemplate.getMapper(UserMapper.class);
        PageHelper.startPage(start,limit);
        UserExample ue = new UserExample();
        PageInfo<User> users = new PageInfo<User>(userMapper.selectByExample(ue));
        return users;
    }
}

>>開發Controller

定義UserController類。

UserController.class

package org.cent.springBootDemo.controller;


import com.github.pagehelper.PageInfo;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.cent.springBootDemo.constants.PageConstants;
import org.cent.springBootDemo.entity.User;
import org.cent.springBootDemo.properties.DataSourceProperties;
import org.cent.springBootDemo.service.UserService;
import org.cent.springBootDemo.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

/**
 * User Demo Controller
 * Created by cent on 2016/9/2.
 */
@RestController
@RequestMapping(value="/user")
public class UserController extends BaseController {

    Logger logger = LogManager.getLogger(getClass());

    @Autowired
    private UserService userService;

    /**
     * 根據用戶ID獲取用戶信息
     * @param id
     * @return
     */
    @RequestMapping(value = "/{id}", method = RequestMethod.GET, produces = "application/json;charset=utf-8")
    @ResponseBody
    public User user(@PathVariable("id") Integer id) {
        try {
            User user = userService.queryById(id);
            return user;
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return new User();
        }
    }

    /**
     * 獲取用戶列表(分頁)
     * 請求參數:start-頁數、limit-每頁記錄數
     * @param request
     * @return
     */
    @RequestMapping(value = "", method = RequestMethod.GET, produces = "application/json;charset=utf-8")
    @ResponseBody
    public PageInfo<User> user(HttpServletRequest request) {
        try {
            Map<String, String> params = getRequestParams(request);
            Integer start = StringUtil.isBlank(params.get("start")) ? PageConstants.DEFAULT_START_PAGE : Integer.valueOf(params.get("start"));
            Integer limit = StringUtil.isBlank(params.get("limit")) ? PageConstants.DEFAULT_PAGE_LIMIT : Integer.valueOf(params.get("limit"));

            PageInfo<User> users = userService.selectPage(start, limit);
            return users;
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return new PageInfo<User>();
        }

    }
}

>>Log4j2配置(使用Spring Boot默認日誌模塊可忽略)

  1. 新建log4j2.properties文件,配置appender和logger,如下配置增長單獨輸出Mybatis Mapper的Debug日誌,因爲查看Mybatis的語句執行記錄。

log4j2.properties

appender.console.type = Console
appender.console.name = STDOUT
appender.console.target = SYSTEM_OUT
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = %-d{yyyy-MM-dd HH:mm:ss} [ %p ] [ %c ] %m%n

appender.rollingFileAppender.type = RollingFile
appender.rollingFileAppender.name = rollingFile
appender.rollingFileAppender.fileName = /spider/logs/all.log
appender.rollingFileAppender.filePattern = /spider/logs/info_%d{yyyy-MM-dd}_%i.log
appender.rollingFileAppender.layout.type = PatternLayout
appender.rollingFileAppender.layout.pattern = %-d{yyyy-MM-dd HH:mm:ss} [ %p ] [ %c ] %m%n
appender.rollingFileAppender.policies.type = Policies
appender.rollingFileAppender.policies.time.type = TimeBasedTriggeringPolicy
appender.rollingFileAppender.policies.time.interval = 1
appender.rollingFileAppender.policies.time.modulate = true
appender.rollingFileAppender.policies.size.type = SizeBasedTriggeringPolicy
appender.rollingFileAppender.policies.size.size=20M
appender.rollingFileAppender.strategy.type = DefaultRolloverStrategy
appender.rollingFileAppender.strategy.max = 100

appenders =console,rollingFileAppender

#主logger
rootLogger.level = info
#rootLogger.appenderRefs = console,I,E
rootLogger.appenderRefs =${appenders}
rootLogger.appenderRef.console.ref = STDOUT
rootLogger.appenderRef.rollingFileAppender.ref = rollingFile

#輸出mybatis的SQL語句執行日誌
logger.sql.name=org.cent.springBootDemo.mapper
logger.sql.level = debug
logger.sql.additivity=false
logger.sql.appenderRefs = console
logger.sql.appenderRef.console.ref = STDOUT
  1. 更改Spring Boot的日誌配置路徑,建立application.properties文件,在裏面更改日誌配置。

application.properties

#使用log4j2的配置
logging.config=classpath:log4j2.properties

>>總體項目結構

image

>>啓動&測試

  1. 運行入口main方法,啓動Spring Boot。

image

  1. http訪問測試

image


附錄

  • 示例數據庫初始化腳本
CREATE DATABASE `spring_boot_demo` /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci */;

CREATE TABLE `sys_user` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `USER_CODE` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
  `USER_NAME` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL,
  `REMARK` varchar(256) COLLATE utf8_unicode_ci DEFAULT NULL,
  `CREATE_TIME` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  `UPDATE_TIME` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

示例源碼

示例項目源碼地址:https://code.aliyun.com/cent/spring-boot-demo.git

相關文章
相關標籤/搜索