【优雅写代码系统】springboot+mybatis+pagehelper+mybatisplus+druid教你如何优雅写代码

[TOC]

springboot 融合了很多插件。springboot相比spring来说有一下有点

  • 自动配置: 针对很多spring的应用程序,springboot提供了很多自动配置
  • 起步依赖: 告诉springboot你需要什么,他就会引入需要的库
  • 命令行界面:springboot的可选特性
  • Autuator: 监控springboot项目的运行情况

spring基本搭建

  • springboot的配置很简单。在pom中继承springboot的pom .然后依赖一下pom就可以继承所需的jar了

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


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

  • 出了jar外。我们pom中配置一个插件就行了

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

整合mybatis

【详见feature/0002/spring-mybatis 分支】

  • 之前我们梳理过mybatis的运行机制及注意点。javaweb的开发时离不开spring的。一个完整的框架是离不开spirng的。所以spring整合mybatis势在必行。我们下面实现如何在spring下融合mybatis及其优秀的一些插件搭建架构

pom配置

  • 我们在springboot项目的pom中继续添加我们mybatis的jar就完成了第一步。
  • 一个是mybatis与spring的整合jar 。 开启springboot加载mybatis项目
  • 一个是spring的aopjar包。主要是实现mybatis的事务问题
  • 一个是mysql的jar包。这里主要看你自己的需求。如果你的项目中使用oracle那么久加入oracle的坐标就行了
  • druid是管理数据的数据源

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.3.1</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.10</version>
</dependency>

mybatis配置

  • 上面的pom设置已经准备了mybatis开发阶段的基本jar。 有了上述的包就可以搭建mybatis . 正常我们在我们的springboot项目中配置一个bean配置的类 MybatisConfig

设置数据源


@Bean
@ConfigurationProperties("spring.datasource")
public DataSource primaryDataSource() {
    // 这里为了演示,暂时写死 。 实际上是可以通过autoConfigure装配参数的
    DruidDataSource dataSource = new DruidDataSource();
    dataSource.setUsername("root");
    dataSource.setPassword("123456");
    dataSource.setDriverClassName("com.mysql.jdbc.Driver");
    dataSource.setUrl("jdbc:mysql://192.168.44.130:3306/others?useUnicode=true&amp;characterEncoding=utf8");
    return dataSource;
}

  • 在springboot中我们只需要在方法上添加Bean注解,就相当于我们在spring的xml中配置的bean标签。在java代码中我们可以进行我们业务处理。个人理解感觉更加的可控。 因为我们使用的mysql。所以这里我们简单的使用druid的数据源

设置sqlsessionfactory


@Bean
public SqlSessionFactory primarySqlSessionFactory() {
    SqlSessionFactory factory = null;
    try {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(primaryDataSource());
        sqlSessionFactoryBean.setConfigLocation(new DefaultResourceLoader().getResource("classpath:mybatis-primary.xml"));
        sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:/com/github/zxhtom.**./*.xml"));
        factory = sqlSessionFactoryBean.getObject();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return factory;
}

  • 在mybatis中sqlsesson是我们操作数据库最直接的java类。管理sqlsession就是上面的sqlsessionFactory 。 所以我们配置它也是必须的。因为和spring整合。Mybatis的SqlsessionFactory交由给spring的SqlsessionfactoryBean管理。所以我们先构建SqlSessionFactoryBean。然后配置必须的数据源、Configuration、mybatis的xml路径等等信息
  • SqlSessionFactoryBean 设置出了spring的FactoryBean属性意外。最重要的是可以设置Mybatis的sqlsessionfactory的属性。上面我们只是简单的设置了。后期可以根据架构的需求进行不断的完善。
  • 可以设置插件、缓存、别名、映射处理器、事务、环境等等所有mybatis的配置

设置扫描


@Bean
public MapperScannerConfigurer mapperScannerConfigurer() {
    MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
    mapperScannerConfigurer.setSqlSessionFactory(primarySqlSessionFactory());
    //每张表对应的*.java,interface类型的Java文件
    mapperScannerConfigurer.setBasePackage("com.github.zxhtom.**.mapper");
    return mapperScannerConfigurer;
}

  • springboot 中我们的mapper接口也是交由spring来扫描的。之前mybatis程序我们是一个一个手动加入的。spring的特性可以直接扫描指定路径的所有java类。这里我们就设置了一下mapper的路径。

设置开启事务

  • 优秀的架构没有事务是能使用的。我们配置事务也是很简单的。在springboot中我们推荐使用java代码来配置事务的。下面的配置我们为了容易阅读。配置在TransactionConfig类中

@Bean
public DataSourceTransactionManager primaryTransactionManager() {
    return new DataSourceTransactionManager(dataSource);
}

  • 首先是配置事务管理器。事务管理的是数据源。所以这里我们需要将MybatisConfig中的DataSource加载进来。这里不多说
  • 然后配置我们的通知点

@Bean
public TransactionInterceptor txAdvice() {
    DefaultTransactionAttribute txAttr_REQUIRED = new DefaultTransactionAttribute();
    txAttr_REQUIRED.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

    DefaultTransactionAttribute txAttr_REQUIRED_READONLY = new DefaultTransactionAttribute();
    txAttr_REQUIRED_READONLY.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
    txAttr_REQUIRED_READONLY.setReadOnly(true);

    NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();
    source.addTransactionalMethod("add*", txAttr_REQUIRED);
    source.addTransactionalMethod("save*", txAttr_REQUIRED);
    source.addTransactionalMethod("delete*", txAttr_REQUIRED);
    source.addTransactionalMethod("update*", txAttr_REQUIRED);
    source.addTransactionalMethod("exec*", txAttr_REQUIRED);
    source.addTransactionalMethod("set*", txAttr_REQUIRED);
    source.addTransactionalMethod("get*", txAttr_REQUIRED_READONLY);
    source.addTransactionalMethod("query*", txAttr_REQUIRED_READONLY);
    source.addTransactionalMethod("find*", txAttr_REQUIRED_READONLY);
    source.addTransactionalMethod("list*", txAttr_REQUIRED_READONLY);
    source.addTransactionalMethod("count*", txAttr_REQUIRED_READONLY);
    source.addTransactionalMethod("is*", txAttr_REQUIRED_READONLY);
    return new TransactionInterceptor(primaryTransactionManager(), source);
}

  • 最后我们配置一下我们的切面、切点

@Bean
public Advisor txAdviceAdvisor() {
    AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
    pointcut.setExpression(AOP_POINTCUT_EXPRESSION);
    return new DefaultPointcutAdvisor(pointcut, txAdvice());
}@Bean
public Advisor txAdviceAdvisor() {
    AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
    pointcut.setExpression(AOP_POINTCUT_EXPRESSION);
    return new DefaultPointcutAdvisor(pointcut, txAdvice());
}

  • 最后说明下。TransactionConfig这个类因为配置事务、拦截所以我们需要加入如下注解在雷伤

@Configuration
@Aspect
@EnableTransactionManagement

资源放行

  • 以上就是mybatis基本的一个配置了。但是这个时候还是不能使用的。因为我们的mapper对应的xml是放在java目录下的。正常src下都是java。xml文件在maven编译时不放行的。我们需要特殊处理下

  • 在pom的build下加入放行配置


<resources>
    <resource>
        <directory>src/main/java</directory>
        <includes>
            <include>**/*.xml</include>
            <include>**/*.properties</include>
            <include>**/*.yaml</include>
        </includes>
        <filtering>true</filtering>
    </resource>
    <resource>
        <directory>src/main/resources</directory>
        <includes>
            <include>**/*.*</include>
        </includes>
        <filtering>false</filtering>
    </resource>
</resources>

  • 加入如下配置后别忘记了clean一下在运行。防止缓存。clean之后看看target下文件
image

测试

  • 为了方便测试我们需要编写测试类。

@SpringBootTest(classes = Application.class)
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
public class TestDataSource {
  
    @Autowired
    private TestMapper testMapper;
    
    @Test
    public void test() {
        List<Map<String, Object>> test = testMapper.test();
        System.out.println(test);
    }
}

结果

image
  • 这里是我查询数据库中的一条数据。主要是测试springboot整合mybatis的流程。到这里mybatis就整合完了。

思考&&疑问

  • 上面的配置我们是接入mybatis了。但是在笔者其他架构上测试过。在MybatisConfig这个类中配置数据源的时候可以直接new出DruidDataSource就可以了。springboot会自动通过DataSourceProperties这个类获取到数据源信息的。但是笔者这里一直没有尝试成功。至于原理更是没有搞懂了。这里留下一个彩蛋希望知道的朋友能说说这事怎么回事

@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource primaryDataSource() {
    return new DruidDataSource();
}

  • 上述代码和本案例中相比就少了很多配置。虽然有的朋友说可以通过映射实体来做。但是直接new对象对我们而言更简单。疑问

使用通用mapper功能

【详见feature/0002/spring-mybatis-tk-page 分支】


<dependency>
    <groupId>tk.mybatis</groupId>
    <artifactId>mapper</artifactId>
    <version>3.3.9</version>
</dependency>

  • 这些插件其实就是改写我们之前学习的myabtis四大组件中的某一个组件而实现的。所以不管是通用mapper还是后面要说的myabtis-plus都是需要重新改写我们的myabtis配置类的。

  • 首先我们想接入通用mapper时,我们需要改用tk提供的扫包配置


@Bean
public MapperScannerConfigurer mapperScannerConfigurer() {
    tk.mybatis.spring.mapper.MapperScannerConfigurer mapperScannerConfigurer = new tk.mybatis.spring.mapper.MapperScannerConfigurer();
    //MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
    mapperScannerConfigurer.setSqlSessionFactory(primarySqlSessionFactory());
    //每张表对应的*.java,interface类型的Java文件
    mapperScannerConfigurer.setBasePackage("com.github.zxhtom.**.mapper");
    return mapperScannerConfigurer;
}

  • 然后添加通用mapper配置

@Bean()
public MapperHelper primaryMapperHelper() throws Exception {
    MapperHelper mapperHelper = new MapperHelper();

    Config config = mapperHelper.getConfig();
    //表名字段名使用驼峰转下划线大写形式
    config.setStyle(Style.camelhumpAndUppercase);

    mapperHelper.registerMapper(Mapper.class);
    mapperHelper.processConfiguration(primarySqlSessionFactory().getConfiguration());
    return mapperHelper;
}

  • 测试代码就很简单了。

User user = tkMapper.selectByPrimaryKey(1);

使用mybatis-plus

【详见feature/0002/spring-mybatisplus 分支】

  • mybatis-plus 实际上就是通用mapper 。这里可以理解就是不同的实现。接入mybatis-plus其实很简单。首先我们引入坐标


<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>2.2.0</version>
</dependency>

  • 然后我们创建实体

@Data
@TableName(value = "person_info_large")
public class User {
    @TableId(value = "id",type = IdType.AUTO)
    private Integer id;
    private String account;
    private String name;
    private String area;
    private String title;
    private String motto;
}

  • 然后就是编写我们的Mapper 。需要继承BaseMapper

public interface PlusMapper extends BaseMapper<User> {
}

  • 上述的编写之后基本就可以查询了。但是注意一下我们需要修改上面的myabtisCOnfog这个类。因为接入mybatisplus后需要我们用mybatisplus中的sqlsessionbean。

@Bean
public SqlSessionFactory primarySqlSessionFactory() {
    SqlSessionFactory factory = null;
    try {
        MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(primaryDataSource());
        sqlSessionFactoryBean.setConfigLocation(new DefaultResourceLoader().getResource("classpath:mybatis-primary.xml"));
        sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:com/github/zxhtom.**./*.xml"));
        sqlSessionFactoryBean.setTypeAliasesPackage("com.github.zxhtom.**.model");
        factory = sqlSessionFactoryBean.getObject();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return factory;
}

  • 和通用mapper一样。就这样我们就可以调用BaseMapper为我们提供的方法操作数据库了。

@Test
public void plusTest() {
    User user = plusMapper.selectById(1);
    System.out.println(user);
}

使用分页插件

mybatis-plus自带分页

【详见feature/0002/spring-mybatisplus 分支】

  • 首先我们使用mybatis plus自带的分页插件,将插件类注入到容器中

@Bean
public PaginationInterceptor paginationInterceptor() {
    return new PaginationInterceptor();
}

  • 然后我们查询的构造一个Page对象就行了。参数分别是第几页、展示条数

return plusMapper.selectPage(page, null);

  • 就是这么简单。使用简单原理才是我们学习的重点。喜欢myabtis插件原理的可以留言。抽空可以研究

github分页插件

【详见feature/0002/spring-mybatis-tk-page 分支】

  • 因为myatis-plus自带了分页插件。上面也展示了如何使用myabtis-plus插件。还有一个github上开元的分页插件。这里就和通用mapper进行组合使用

  • pagehelper官方更新还是挺勤奋的。提供了pagehelper 和springboot auto装配两种。 笔者这里测试了pagehelper-spring-boot-starter这个包不适合本案例中。因为本案例中扫描mapper路径是通过MapperScannerConfigurer注册的。如果使用pagehelper-spring-boot-starter的话就会导致分页拦截器失效。我们看看源码

image
  • 这是因为这版本提供了springboot自动装配。但是自动装配的代码中进行添加拦截器的时候sqlsessionfactory这个时候还没有进行扫描mapper.也就没有进行addMapper 。 所以这个时候添加的拦截器拦截不到我们的mapper . 如果非要使用这个版本的话。我们扫描mapper就不能通过MapperScannerConfigurer . 经过笔者测试。需要在MybatisConfig类上添加扫描注解@MapperScan(basePackages = {"com.github.zxhtom.**.mapper"}, sqlSessionFactoryRef = "primarySqlSessionFactory")

使用常规版本

  • 为了符合本版本宗旨 。 我们这里使用如下坐标

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>5.1.7</version>
</dependency>

  • 使用这个版本pagehelper。 没有了springboot的自动装配了。我们可以自己添加插件。添加插件有两种方式。想自动装配版本一样通过Configuration进行添加不过我们通过Condition条件选择添加的时机 。
  • 还有一个简单的方式就是通过SqlSessionFactoryBean设置sqlSessionFactoryBean.setPlugins(new Interceptor[]{new PageInterceptor()});
  • 因为通过sqlsessionFactoryBean添加的插件和在settings文件中添加是一样的。在通过XmlFactory.build Configuration对象是会自动将插件装在上。这个时候mapper也都扫描过了。

@Bean
public SqlSessionFactory primarySqlSessionFactory() {
    SqlSessionFactory factory = null;
    try {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(primaryDataSource());
        sqlSessionFactoryBean.setConfigLocation(new DefaultResourceLoader().getResource("classpath:mybatis-primary.xml"));
        sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:com/github/zxhtom.**./*.xml"));
        sqlSessionFactoryBean.setTypeAliasesPackage("com.github.zxhtom.**.model");
        sqlSessionFactoryBean.setPlugins(new Interceptor[]{new PageInterceptor()});
        factory = sqlSessionFactoryBean.getObject();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return factory;
}

总结

  • 这里简单阐述下为什么不适用注解扫描mapper、或者不在配置文件中配置扫包路径。因为通过MapperScannerConfigurer我们可以动态控制路径。这样显得比较有逼格。在实际开发中笔者推荐使用注解方式扫描。因为这样可以避免不必要的坑。

  • 到这里我们整理了【springboot整合mybaits】、【mybatis-plus】、【通用mapper】、【pagehelper插件整合】 这四个模块的整理中我们发现离不开myabtis的四大组件。springboot其实我们还未接触到深的内容。这篇文章主要偏向myabtis . 后续还会继续衍生探索 【myabtis+druid】监控数据信息 。

  • 喜欢研究源码和开元框架小试牛刀的欢迎关注我

代码仓库: https://gitee.com/zxhTom/spring/tree/feature/0002/spring-mybatisplus

加入战队

# <span id="addMe">加入战队</span>

微信公众号

微信公众号

主题

image

非xml配置springboot+mybatis事务管理

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