【框架篇】MyBatis-Plus的使用入门

前言:

  众所周知,Mybatis在持久层框架中还是比较火的,一般的项目都是基于ssm。虽然Mybatis可以直接在xml中通过编写SQL语句来操作数据,非常的灵活,但是也带来了很多麻烦,所有的操作都要通过SQL语句进行,这就意味着要写大量的文件,很不方便。这时候MyBatis-Plus就很好的解决了这个问题。

一、MyBatis-Plus简介
MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。(这段话是官网的原话,了解更多可以参考官网mybatis-plus官网)那么它是如何增强的呢?其实就是它已经封装好了一些CRUD方法,我们不需要再写xml了,仅仅通过少量配置即可实现单表大部分的CRUD操作。直接调用这些方法就可以了。
看到这里,各位看官们是不是觉得,哇,终于可以少撸一些xml代码了,内心美滋滋,我们接着往下看~

二、MyBatis-Plus特性
1.无侵入:只是在Mybatis的基础上做增强而不做改变,引入它不会对我们现有的工程产生影响
2.损耗小:启动项目即会自动注入基本CURD,性能基本无损耗,直接面向对象操作
3.强大的CRUD操作:内置通用Mapper、通用Service,只需要通过少量配置即可实现单表大部分CRUD操作,还有强大的条件构造器,满足各类使用需求
4.支持主键自动生成:支持4种主键策略(内含分布式唯一ID生成器 - Sequence),可自由配置,完美解决主键问题
5.支持ActiveRecord模式:支持ActiveRecord形式调用,实体类只需要继承Model类就可以进行CRUD操作
6.内置分页插件:基于Mybatis的物理分页,开发者无需关心具体操作,配置好插件以后,写分页就相当于普通List查询
这里只展示了部分特性,更多特性可以到官网仔细了解~

三、spring整合MyBatis-Plus
正如官方所说,MyBatis-Plus在Mybatis的基础上只做增强不做改变,所以与spring的整合也是很简单的。只需要把Mybatis的依赖替换成MyBatis-Plus的依赖,再把sqlSessionFactory换成MyBatis-Plus的就可以了,接下来看具体的操作:
1.pom.xml:
核心依赖如下:

    <!-- spring -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.3.14.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>4.3.14.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>4.3.14.RELEASE</version>
            <scope>test</scope>
        </dependency>
        <!-- MyBatis-Plus 依赖 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus</artifactId>
            <version>2.3</version>
        </dependency>

注意:集成MyBatis-Plus要把Mybatis、Mybatis-spring去掉,避免冲突

2.mybatis-config.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
</configuration>

注意:因为是与spring整合,所有MyBatis-Plus的大部分都写在spring的配置文件中,这里定义一个空的mybatis-config.xml即可。

3.spring-dao.xml:

<?xml version="1.0" encoding="UTF-8"?>    
<beans xmlns="http://www.springframework.org/schema/beans"    
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
    xmlns:p="http://www.springframework.org/schema/p"  
    xmlns:aop="http://www.springframework.org/schema/aop"   
    xmlns:context="http://www.springframework.org/schema/context"  
    xmlns:jee="http://www.springframework.org/schema/jee"  
    xmlns:tx="http://www.springframework.org/schema/tx"  
    xsi:schemaLocation="    
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd  
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd  
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd  
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.0.xsd  
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">    
        
    <!-- 配置整合mybatis-plus过程 -->
    <!-- 1、配置数据库相关参数properties的属性:${
    
    url} -->
    <context:property-placeholder location="classpath:jdbc.properties" />
    <!-- 2、配置数据库连接池 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driver}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
    <!-- mybatis的sqlsessionFactorybean:org.mybatis.spring.SqlSessionFactoryBean-->
    <!-- 3、配置mybatis-plus的sqlSessionFactory -->
    <bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <property name="typeAliasesPackage" value="com.zhu.mybatisplus.entity"/>
    </bean>
    <!-- 4、DAO接口所在包名,Spring会自动查找其下的类 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.zhu.mybatisplus.dao" />
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    </bean> 
</beans>

4.entity:

@Data
@TableName(value = "DB_STUDENT")//指定表名
public class Student {
    
    
    //value与数据库主键列名一致,若实体类属性名与表主键列名一致可省略value
    @TableId(value = "id",type = IdType.AUTO)//指定自增策略
    private Integer id;
    //若没有开启驼峰命名,或者表中列名不符合驼峰规则,可通过该注解指定数据库表中的列名,exist标明数据表中有没有对应列
    @TableField(value = "last_name",exist = true)
    private String lastName;
    private String email;
    private Integer gender;
    private Integer age;
}

5.mapper:

public interface studentDao extends BaseMapper<Student> {
    
    
}

}

这样就完成了MyBatis-Plus与spring的整合。首先是把mybatis和mybatis-spring依赖换成MyBatis-Plus的依赖,然后把sqlsessionfactory换成MyBatis-Plus的,然后实体类中添加@TableName、@TableId等注解,最后mapper继承BaseMapper即可。

四、MyBatis-Plus的通用CRUD
需求:
存在一张 db_student表,且已有对应的实体类 Student,实现db_student表的 CRUD 操作我们需要做什么呢?
基于 Mybatis:
需要编写 StudentMapper 接口,并在 StudentMapper.xml 映射文件中手动编写 CRUD 方法对应的sql语句。
基于 MyBatis-Plus:
只需要创建 StudentMapper 接口, 并继承 BaseMapper 接口。
我们已经有了Student、db_student了,并且StudentDao也继承了BaseMapper了,接下来就使用CRUD方法。
1、insert操作:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({
    
    "classpath:spring/spring-dao.xml"})
public class test {
    
    
    @Autowired
    private StudentDao studentDao;
    @Test
    public void testInsert(){
    
    
        Student student= new Student ();
        student.setLastName("咸鱼");
        student.setEmail("[email protected]");
        student.setGender(1);
        student.setAge(20);
        studentDao.insert(student);
        //MyBatis-Plus会自动把当前插入对象在数据库中的id写回到该实体中
        System.out.println(employee.getId());
    }
}

执行添加操作,直接调用insert方法传入实体即可。

2、update操作:

@Test
public void testUpdate(){
    
    
        Student student = new Student();
        student.setId(1);
        student.setLastName("更新测试");
        //studentDao.updateById(student);//根据id进行更新,没有传值的属性就不会更新
        studentDao.updateAllColumnById(student);//根据id进行更新,没传值的属性就更新为null
}

注意:注意这两个update操作的区别,updateById方法,没有传值的字段不会进行更新,比如只传入了lastName,那么age、gender等属性就会保留原来的值;updateAllColumnById方法,顾名思义,会更新所有的列,没有传值的列会更新为null。

3、select操作:
(1)、根据id查询:

Student student = studentDao.selectById(1);

(2)、根据条件查询一条数据:

Student student = new Student ();
student.setId(1);
student.setLastName("更新测试");
//若是数据库中符合传入的条件的记录有多条,那就不能用这个方法,会报错
Student student = studentDao.selectOne(student);

注意:这个方法的sql语句就是where id = 1 and last_name = 更新测试,若是符合这个条件的记录不止一条,那么就会报错。

(3)、根据查询条件返回多条数据:
当符合指定条件的记录数有多条时,上面那个方法就会报错,就应该用这个方法。

Map<String,Object> columnMap = new HashMap<>();
columnMap.put("last_name","东方不败");//写表中的列名
columnMap.put("gender","1");
List<Student> student= studentDao.selectByMap(columnMap);
System.out.println(student.size());

注意:查询条件用map集合封装,columnMap,写的是数据表中的列名,而非实体类的属性名。比如属性名为lastName,数据表中字段为last_name,这里应该写的是last_name。selectByMap方法返回值用list集合接收。
(4)、通过id批量查询:

List<Integer> idList = new ArrayList<>();
idList.add(1);
idList.add(2);
idList.add(3);
List<Student> student = studentDao.selectBatchIds(idList);
System.out.println(student);

注意:把需要查询的id都add到list集合中,然后调用selectBatchIds方法,传入该list集合即可,该方法返回的是对应id的所有记录,所有返回值也是用list接收。
(5)、分页查询:

List<Student> student = studentDao.selectPage(new Page<>(1,2),null);
System.out.println(student);

注意:selectPage方法就是分页查询,在page中传入分页信息,后者为null的分页条件,这里先让其为null,讲了条件构造器再说其用法。这个分页其实并不是物理分页,而是内存分页。也就是说,查询的时候并没有limit语句。等配置了分页插件后才可以实现真正的分页。
4、delete操作:
(1)、根据id删除:

studentDao.deleteById(1);

(2)、根据条件删除:

Map<String,Object> columnMap = new HashMap<>();
columnMap.put("gender",0);
columnMap.put("age",18);
studentDao.deleteByMap(columnMap);

注意:该方法与selectByMap类似,将条件封装在columnMap中,然后调用deleteByMap方法,传入columnMap即可,返回值是Integer类型,表示影响的行数。
(3)、根据id批量删除:

 List<Integer> idList = new ArrayList<>();
 idList.add(1);
 idList.add(2);
 studentDao.deleteBatchIds(idList);

注意:该方法和selectBatchIds类似,把需要删除的记录的id装进idList,然后调用deleteBatchIds,传入idList即可。

五、ActiveRecord

Active Record(活动记录),是一种领域模型模式,特点是一个模型类对应关系型数据库中的一个表,而模型类的一个实例对应表中的一行记录。而MyBatis-Plus只需要让实体类继承Model类且实现主键指定方法,就可以使用Active Record。

1、entity:

@Data
public class User extends Model<User> {
    
    
    private Integer id;
    private String name;
    private Integer age;
    private Integer gender;
    //重写这个方法,return当前类的主键
    @Override
    protected Serializable pkVal() {
    
    
        return id;
    }
}

注意:实体类继承Model类,重写pkVal方法。

2、mapper:

public interface UserDao extends BaseMapper<User> {
    
    
}

注意:虽然AR模式用不到该接口,但是一定要定义,否则使用AR时会报空指针异常。

3、使用AR:
(1)、AR插入操作:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({
    
    "classpath:spring/spring-dao.xml"})
public class TestAR {
    
    
    @Test
    public void testArInsert(){
    
    
        User user = new User();
        user.setName("咸鱼");
        user.setAge(20);
        user.setGender(1);
        boolean result = user.insert();
        System.out.println(result);
    }
}

在这里插入图片描述

注意:可以看到我们并不需要注入mapper接口,不过正如刚才所说,不使用但还是要定义,否则会报错。AR操作是通过对象本身调用相关方法,比如要insert一个user,那就用这个user调用insert方法即可。返回值为布尔类型,由上图可看到返回了true,是操作成功的。
(2)、AR更新操作:

    @Test
    public void testArUpdate(){
    
    
        User user = new User();
        user.setId(1);
        user.setName("咸鱼");
        boolean result = user.updateById();
        System.out.println(result);
    }

注意:user调用updateById方法,将id为1的用户进行更新。

(3)、AR查询操作:

    @Test
    public void testArSelect(){
    
    
        User user = new User();
        //1、根据id查询
        //user = user.selectById(1);
        //或者这样用
        //user.setId(1);
        //user = user.selectById();

        //2、查询所有
        //List<User> users = user.selectAll();

        //3、根据条件查询
        //List<User> users = user.selectList(new EntityWrapper<User>().like("name","刘"));

        //4、查询符合条件的总数
        int result = user.selectCount(new EntityWrapper<User>().eq("gender",1));
        System.out.println(result);
    }

注意:上面的代码涉及到了四个不同的查询操作,其实用法与MP的BaseMapper提供的方法的用法差不多,只不过这里是实体对象调用。

(4)、AR删除操作:

@Test
    public void testArDelete(){
    
    
        User user = new User();
        //删除数据库中不存在的数据也是返回true
        //1、根据id删除数据
        //boolean result = user.deleteById(1);
        //或者这样写
        //user.setId(1);
        //boolean result = user.deleteById();

        //2、根据条件删除
        boolean result = user.delete(new EntityWrapper<User>().like("name","玲"));
        System.out.println(result);
    }

注意:这里介绍了两个删除方法,代码中已有注释说明。需要注意的是,删除数据库中不存在的数据,结果也是true。

(5)、AR分页操作:

@Test
    public void testArPage(){
    
    
       User user = new User();
       Page<User> page =
               user.selectPage(new Page<>(1,4),
               new EntityWrapper<User>().like("name","咸鱼"));
       List<User> users = page.getRecords();
       System.out.println(users);
    }

注意:这个分页方法和BaseMapper提供的分页一样都是内存分页,并非物理分页,因为sql语句中没用limit,和BaseMapper的selectPage方法一样,配置了分页插件后就可以实现真正的物理分页。AR的分页方法与BaseMapper提供的分页方法不同的是,BaseMapper的selectPage方法返回值是查询到的记录的list集合,而AR的selectPage方法返回的是page对象,该page对象封装了查询到的信息,可以通过getRecords方法获取信息。

六、插件的配置

MP提供了很多好用的插件,而且配置简单,使用方便。接下来一起看看MP的插件如何使用。

1、分页插件:
之前就有说到,BaseMapper的selectPage方法和AR提供的selectPage方法都不是物理分页,需要配置分页插件后才是物理分页,那么现在就来看看如何配置这个插件。

<!-- 3、配置mybatisplus的sqlSessionFactory -->
    <bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <property name="typeAliasesPackage" value="com.zhu.mybatisplus.entity"/>
        <!-- 注入全局配置 -->
        <property name="globalConfig" ref="globalConfiguration"/>
        <!-- 配置插件 -->
        <property name="plugins">
            <list>
                <!-- 分页插件 -->
                <bean class="com.baomidou.mybatisplus.plugins.PaginationInterceptor"/>
            </list>
        </property>
    </bean>

注意:在sqlSessionFactory这个bean中,通过配置插件,接下来的所有插件都配置在这个list中。

@Test
    public void testPage() {
    
    
        //配置了分页插件后,还是和以前一样的使用selectpage方法,
        //但是现在就是真正的物理分页了,sql语句中有limit了
        Page<Employee> page = new Page<>(1, 2);
        List<Employee> employeeList =
                emplopyeeDao.selectPage(page, null);
        System.out.println(employeeList);
        System.out.println("================= 相关的分页信息 ==================");
        System.out.println("总条数:" + page.getTotal());
        System.out.println("当前页码:" + page.getCurrent());
        System.out.println("总页数:" + page.getPages());
        System.out.println("每页显示条数:" + page.getSize());
        System.out.println("是否有上一页:" + page.hasPrevious());
        System.out.println("是否有下一页:" + page.hasNext());
        //还可以将查询到的结果set进page对象中
        page.setRecords(employeeList);
    }

在这里插入图片描述
由图可知,sql语句中已经有了limit,是物理分页了。

在这里插入图片描述
也可以通过page调用相关方法获取到相关的分页信息,而且还可以把查询到的结果set回page对象中,方便前端使用。

MyBatis-Plus的功能包括但不限于以下知识点:
通用crud、全局策略配置、条件构造器、AR模式、插件配置、代码生成器、自定义全局操作、公共字段自动填充等功能。熟练使用之后,会让我们的开发效率更上一层楼~

猜你喜欢

转载自blog.csdn.net/weixin_42777004/article/details/108616144