SpringBoot基础教程(二)——与Mybatis的结合

MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。每个MyBatis应用程序主要都是使用SqlSessionFactory实例的,一个SqlSessionFactory实例可以通过SqlSessionFactoryBuilder获得。SqlSessionFactoryBuilder可以从一个xml配置文件或者一个预定义的配置类的实例获得。今天我们看一下,他如何同spring boot结合再一起。

首先我们知道,spring boot 他可以支持xml形式配置Bean,但是它更为推崇的方式是通过代码的方式,也就是配置类实现配置,因为这样,我们可以更好的保持代码的统一性,这样也会帮助我们更好的查看源码,所以我们接下来的课程中的所以实例都采用配置类的形式替代xml的配置。

首先还是看下我们的pom文件中引入的jar

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

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

        <!-- 有数据库链接需求时打开-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
        </dependency>

上面两个我们不做赘述了,上一讲已经提到了,下面我们剩下的。spring-boot-starter-jdbc 主要是spring boot 帮我们封装好关于事务方面需要引入的jar。mybatis 是 mybatis框架所需要的核心包,mybatis-spring是mybatis与spring 结合需要的bridge包。我们实例中演示中的数据库使用mysql,所以需要mysql-connector-java包,代表了数据库的驱动。lombok是一个可以通过简单的注解的形式来帮助我们简化消除一些必须有但显得很臃肿的 Java 代码的工具。druid是阿里巴巴开源的一款数据库连接池的jar,很轻松的引入连接池的功能,相同功能的还有c3p0与dbcp。

剩下的我们讲一下我们最重要的配置文件

/**
 * pajk.com Inc.
 * Copyright (c) 2014-2015 All Rights Reserved.
 */
package com.shuqi;

import com.alibaba.druid.filter.Filter;
import com.alibaba.druid.filter.stat.StatFilter;
import com.alibaba.druid.pool.DruidDataSource;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.support.TransactionTemplate;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;


@Configuration
@MapperScan(basePackages = "com.shuqi.dal",sqlSessionFactoryRef = "sqlSessionFactory")
@EnableTransactionManagement
public class DalConfig {


    @Value(value = "classpath:mybatis/sqlmap/*.xml")
    private Resource[] mapperLocations;

    @Value(value = "classpath:mybatis/mybatis-config.xml")
    private Resource configLocation;


    @Bean
    public SqlSessionFactoryBean sqlSessionFactory(DruidDataSource dataSource) {
        SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();
        ssfb.setMapperLocations(mapperLocations);
        ssfb.setConfigLocation(configLocation);
        ssfb.setTypeAliasesPackage("com.shuqi.dal.model");
        ssfb.setDataSource(dataSource);
        return ssfb;
    }

    @Bean(initMethod = "init", destroyMethod = "close")
    public DruidDataSource dataSource(@Value("${ds.jdbc.url}") String url,
                                      @Value("${ds.jdbc.username}") String username,
                                      @Value("${ds.jdbc.password}") String password) throws SQLException {
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setUrl(url);
        druidDataSource.setUsername(username);
        druidDataSource.setPassword(password);
        druidDataSource.setMaxActive(60);
        druidDataSource.setInitialSize(1);
        druidDataSource.setMaxWait(60000);//60s
        druidDataSource.setMinIdle(1);
        druidDataSource.setTimeBetweenEvictionRunsMillis(3000);
        druidDataSource.setMinEvictableIdleTimeMillis(300000);
        druidDataSource.setValidationQuery("select 1");
        druidDataSource.setTestWhileIdle(true);
        druidDataSource.setTestOnBorrow(false);
        druidDataSource.setTestOnReturn(false);
        druidDataSource.setPoolPreparedStatements(true);
        druidDataSource.setMaxPoolPreparedStatementPerConnectionSize(20);
        druidDataSource.setFilters("config");
        Properties properties = new Properties();
        properties.put("config.decrypt", "false");
        druidDataSource.setConnectProperties(properties);

        StatFilter statFilter = new StatFilter();
        statFilter.setSlowSqlMillis(10000);//10s。。慢
        statFilter.setMergeSql(true);
        statFilter.setLogSlowSql(true);

        List<Filter> filterList = new ArrayList<Filter>();
        filterList.add(statFilter);
        druidDataSource.setProxyFilters(filterList);

        return druidDataSource;
    }

    @Bean
    public TransactionTemplate transactionTemplate(PlatformTransactionManager transactionManager) {
        return new TransactionTemplate(transactionManager);
    }

    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource) throws SQLException {
        return new DataSourceTransactionManager(dataSource);
    }

}

@Configuration 注解表示是一个配置类,功能相当于传统的xml配置文件,spring 发现这个注解,就知道里面的内容是Bean,所以也是说被@Configuration注解修饰的类是Bean的容器。@EnableTransactionManagement表示开启了数据库的事务。@ MapperScan表示扫描Mapper接口basePackages表示从哪里扫描出的类作为我们的mapper接口,sqlSessionFactoryRef 指定SqlSessionFactoryBean。在这里我们插一句,对不了解mybatis的同学说,Mybatis的常用使用形式是定义Mapper接口,注意是接口,那么实现呢?一般情况下是使用配置文件,他们怎么关联起来,通过配置文件中的namespace属性,他里面的值是被实现接口的全限定名称。下面我们会再提到这里。我们再说dataSource就是使用druid来定义的。他可以支持很多特性,比如对慢SQL的一些监控等。有了数据源,我们就可以根据它来定义一个事务管理器transactionManager。如果你喜欢编程式事务也可以定义一个transactionTemplate,如果喜欢声明式事务,就可以直接加@Transactional注解了。当然最重要的还是我们的SqlSessionFactoryBean,他设置了数据源DataSource,Mapper文件的地址MapperLocations,也就是Mapper文件存放的地址。Mybatis的配置文件的地址ConfigLocation,也就是mybatis-config存放的地址。基本上都配置好了。下面我们再看看Mapper Interface的内容

package com.shuqi.dal.mapper;


import com.shuqi.dal.model.UserDO;

public interface UserMapper {

    void create(UserDO userDO);

    void modify(UserDO userDO);

    UserDO findByName(String name);
}

与 Mapper 文件的内容

<?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="com.shuqi.dal.mapper.UserMapper">

    <resultMap id="UserDOResultMap" type="com.shuqi.dal.model.UserDO">
        <id column="id" property="id"/>
        <result column="gmt_modified" property="gmtModified"/>
        <result column="gmt_created" property="gmtCreated"/>
        <result column="name" property="name"/>
        <result column="status" property="status"/>


    </resultMap>

    <sql id="Base_Column_List">
        gmt_created,id,gmt_modified,`name`,`status`
    </sql>

    <insert id="create" useGeneratedKeys="true" keyProperty="id">
        INSERT INTO `user`
        (
               gmt_modified ,
               gmt_created ,
               `name`,
               status
        )
        VALUES (
               now()  ,
               now()  ,
               #{name},
               #{status}
        );
    </insert>

    <update id="modify">
        UPDATE `user`
        <set>
            gmt_modified=now()

            <if test="gmtCreated !=null">
                ,gmt_created = #{gmtCreated}
            </if>
            <if test="name !=null">
                ,`name` = #{name}
            </if>
            <if test="status !=null">
                ,`status` = #{status}
            </if>
        </set>
        where
        id=#{id};
    </update>
    <select id="findByName" resultMap="UserDOResultMap">
        SELECT
        <include refid="Base_Column_List"/>
        from `user` where name=#{name}
    </select>


</mapper>

看下namespace的定义就知道他们是怎么关联的了。看一下每个代码块中的ID,就知道怎么和接口中的方法对应了。

下节将的内容是:SpringBoot基础教程(三)——多数据源结合

本节项目源码

参考文档

MyBatis

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342

推荐阅读更多精彩内容