IDEA 使用Spring Boot 超快速搭建 SSM (进阶版)

IDEA 使用Spring Boot 超快速搭建 SSM (进阶版)

author:Cris

零、序

不管你是编程做Coding,还是做编辑码字,你的每一行代码或者你文章的每句话,都应该像写诗一样。只有这样的程序员和编辑,才能最终成就自己

温馨提示:本篇笔记跟随上一篇 《IDEA 使用Spring Boot 超快速搭建 SSM (完整版)》 ,基础环境以及场景介绍都已经在上篇笔记中详细说明,此次进阶篇的目的还是为了提高开发效率,主要是集中在 Dao 层,我们使用了 Mybatis的通用插件 以及 PageHelper分页插件,笔者在搭建过程中遇到的问题以及细节详细记录如下,感兴趣的同学可以关注一下?以及参考一下

该项目完整代码请参考:https://github.com/zc-cris/SpringBoot_SSM

一、环境修改

首先,需要对上一篇笔记做出一点改正

上篇笔记中,笔者曾经在 Spring Boot 应用的启动类 DemoApplication 设置了 Mapper 接口扫描注解@MapperScan(basePackages = "com.cris.dao") 后,还在 Mapper 接口上 加入了 @Mapper 注解,虽然对最后的测试没有影响,但是本着 准确 以及 能少些绝不多写 的原则,在这里笔者还是修改如下:

IDEA 使用Spring Boot 超快速搭建 SSM (进阶版)

1.1、关于插件

因为项目使用 Mybatis 来实现数据访问层,为了提高开发的效率,上篇笔记给大家介绍了 IDEA 开发插件 MybatisCodeHelperPro,这一次主要是介绍单表操作的神级插件 Mybatis通用插件 以及分页插件 PageHelper

在平时的开发中,我们的大部分精力都是放在了业务层上,对于数据访问层的开发应该尽量简洁,高效。毕竟重复性的劳动就交给那些大牛们提供的插件就好?,除非是项目在后期遇到了瓶颈,需要优化,那个时候就可以从数据访问层入手,并且由于使用的是 Mybatis 这种半自动 ORM 框架,SQL 优化起来也是比较容易。

还是那句话,一切可以提高开发效率的工具我们都应该尽量熟悉乃至掌握,只有这样,才不会重复造*,才不会天天熬夜加班?

最后给出这两个插件的链接,感兴趣的同学建议看看,还是我们中国的开发者开发的?

通用mapper

PageHelper

1.2、数据库数据

这里简单起见,我们就新建两张最常见的 emps 表和 depts 表,值得一提的是,这两张表的创建和修改都是依托于 IDEADatabase 模块

depts

IDEA 使用Spring Boot 超快速搭建 SSM (进阶版)

emps

IDEA 使用Spring Boot 超快速搭建 SSM (进阶版)

这里并不建议在 emps 表插入 deptsid 作为约束。原因参见 总结

1.3、配置文件修改

先来看 pom.xml 文件,导入插件的启动器 starter

IDEA 使用Spring Boot 超快速搭建 SSM (进阶版)

再看看 application.yml 文件

IDEA 使用Spring Boot 超快速搭建 SSM (进阶版)

二、开始编码

2.1、entity

先来看看 Dept

IDEA 使用Spring Boot 超快速搭建 SSM (进阶版)

再来看看 Emp

/**
 * 员工表对应的实体
 *
 * @author zc-cris
 * @version 1.0
 **/
@Table(name = "emps")
@SuppressWarnings("unused")
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class Emp {
    @Id
    private Integer id;
    private String name;
    private Integer deptId;
    private String countryName;
}

关于实体类的属性,一定要设置成 引用数据类型!!!,否则获取出来的数据无法正确装配到实体类上,

根据阿里代码规约,实体类的属性需要统一使用引用数据类型,主要是为了防止基本数据类型的默认值造成干扰。

举个例子:一个同学因故没有参加考试,那么这趟考试是应该给他计 0 分还是设置为 null 呢?

简而言之:null 可以表示不存在,可以表示错误,但是 0 只能表示一个客观存在的数据

2.2、mapper

DeptMapper

IDEA 使用Spring Boot 超快速搭建 SSM (进阶版)

EmpMapper

IDEA 使用Spring Boot 超快速搭建 SSM (进阶版)

注意:以前版本的 通用mapper,直接写我们的业务 mapper 接口继承自插件的 Mapper 接口即可,但是新版本需要一个我们自己的本地 Mapper 接口

本地 Mapper 接口如下

IDEA 使用Spring Boot 超快速搭建 SSM (进阶版)

这个本地 Mapper 接口必须在 application.yml 文件中进行配置?,如 1.3节所示

2.3、配置类

接下来这一步非常简单,但是很关键,我们需要在应用的启动类上,将之前的 @MapperScan 注解由 Mybatis 官方提供的更换为 通用 Mapper 插件 提供的,否则会报错!

IDEA 使用Spring Boot 超快速搭建 SSM (进阶版)

三、开始测试把~

具体的测试代码如下:

@SpringBootTest
@RunWith(SpringRunner.class)
public class EmpMapperTest {

    @Autowired
    EmpMapper empMapper;


    /**
     * 根据主键查询单条数据
     */
    @Test
    public void testSelectOne() {
        Emp emp = empMapper.selectByPrimaryKey(1);
        System.out.println("emp = " + emp);
    }

    /**
     * 查询所有员工
     */
    @Test
    public void testSelectAll() {
        List<Emp> emps = empMapper.selectAll();
        emps.forEach(System.out::println);
    }

    /**
     * 分页查询(借助pageHelper 插件)
     */
    @Test
    public void testSelectAllPage() {
        // 查询第一页的两条数据
        PageHelper.startPage(1, 2);
        List<Emp> emps = empMapper.selectAll();
        emps.forEach(System.out::println);
    }

    /**
     * 测试保存一条数据(这里没有选择自增主键)
     */
    @Test
    public void testSave() {
        empMapper.insert(new Emp(5, "麻花腾", 1002, "日本"));
    }

    /**
     * 有选择性的保存数据(null值不保存到数据库,前提是数据库允许该列为空)
     */
    @Test
    public void testInsertSelective() {
        empMapper.insertSelective(new Emp(6, "麻生希", 1001, null));
    }

    /**
     * 有选择性的更新数据,根据id更新数据,如果为null的属性就不更新对应的列,效率更高
     */
    @Test
    public void testUpdateSelective() {
        empMapper.updateByPrimaryKeySelective(new Emp(6, null, null, "*"));
    }

    /**
     * 根据主键删除数据
     */
    @Test
    public void testDeleteById() {
        empMapper.deleteByPrimaryKey(5);
    }

    /**
     * 搭配使用mapper 文件来完成复杂的sql crud,当然也可以使用
     * 通用mapper 插件为我们提供的 QBC 查询,个人建议使用手写sql 语句的形式
     * 因为可以自己优化sql 语句的执行效率
     * 同时也可以发现通用mapper插件是支持调用接口继承方法和mapper文件的sql语句的
     */
    @Test
    public void testDynamicSql() {
        List<Emp> byCountryName = empMapper.getByCountryName(Arrays.asList("中国", "德国"));
        byCountryName.forEach(System.out::println);
    }
}

值得一提的是,在最后一个测试动态 sql的方法,我们使用了 mapper 文件映射的方式,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.cris.dao.EmpMapper">
    <select id="getByCountryName" resultType="com.cris.entity.Emp">
        select
        id,
        name,
        dept_id,
        country_name
        from sql_primary_study.emps
        <foreach collection="countryNames" item="countryName" open="where country_name in (" close=")" separator=",">
            #{countryName}
        </foreach>
    </select>
</mapper>

之所以使用 mapper映射文件 的方式,一来是证明 通用mapper 支持两种方式(注解和文件)来开发 Mapper,还有就是可以使用 Mapper 映射文件 的方式来代替 通用Mapper 提供的 QBC 复杂查询(书写更加容易,也更加容易优化 sql),最后再练习练习 MybatisDynamic sql 特性

四、总结

项目特点:

  1. 使用 通用 MapperPageHelper 插件大大提高数据访问层的开发效率
  2. 通用Mapper 插件使用两种方式来开发 Mapper 接口,其中映射文件的方式可以有效代替 QBC查询

注意点:

  1. 实体类属性一定要是引用数据类型
  2. 实体类和实体类之间尽量不要 耦合,即少写以前那种在一个实体类里面引用其他实体类的写法(例如:在 Emp 中持有 Dept 的引用),换种写法,将 Emp 中的 Dept 引用更换为 deptId (等同于 Deptid)会不会更好?尽量让类和类之间的引用关系简单明了,避免不必要的互相引用以及缕清类和类之间的联系是迈向高级码农的基本常识。包括从数据库的设计,表和表之间的关系能不用外键就别用,否则会给后期的维护和优化带来极大的麻烦(本例中:emps 表的 dept_id 并没有引用 deps 表的 id,将这种数据关联引入到业务中去,而不是让数据库来管理 )
  3. 新版本的 通用mapper 插件引入了一个本地 Mapper接口 需要自定义
  4. 启动类的 @MapperScan 注解需要更换为 通用mapper 插件提供的
  5. Mybatis 的动态 sql 特性非常有利于复杂 sql 的书写
  6. 通用mapper 的批量操作很简单,查看 MySqlMapper<T> 的源代码即可