【Mybatis Plus】

引入依赖
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.3.1</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.13</version>
        </dependency>
    </dependencies>
配置application.yml
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    url: jdbc:mysql://192.168.60.100/mybatisplus?characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mysql 5.0以上版本驱动需要配置为 com.mysql.cj.jdbc.Driver
mysql 5.7以上url配置:jdbc:m ysql://192.168.60.100/mydb?characterEncoding=UTF-8&useSSL=false
mysql 8.0 url需要配置时区:jdbc:m ysql://192.168.60.100/mydb?characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl为mybatisplus自带的日志,可以在控制台输出sql和执行结果
1 BaseMapper
public interface BaseMapper<T> extends Mapper<T> {
    int insert(T entity);
    int deleteById(Serializable id);
    int deleteByMap(@Param("cm") Map<String, Object> columnMap);
    int delete(@Param("ew") Wrapper<T> wrapper);
    int deleteBatchIds(@Param("coll") Collection<? extends Serializable> idList);
    int updateById(@Param("et") T entity);
    int update(@Param("et") T entity, @Param("ew") Wrapper<T> updateWrapper);
    T selectById(Serializable id);
    List<T> selectBatchIds(@Param("coll") Collection<? extends Serializable> idList);
    List<T> selectByMap(@Param("cm") Map<String, Object> columnMap);
    T selectOne(@Param("ew") Wrapper<T> queryWrapper);
    Integer selectCount(@Param("ew") Wrapper<T> queryWrapper);
    List<T> selectList(@Param("ew") Wrapper<T> queryWrapper);
    List<Map<String, Object>> selectMaps(@Param("ew") Wrapper<T> queryWrapper);
    List<Object> selectObjs(@Param("ew") Wrapper<T> queryWrapper);
    <E extends IPage<T>> E selectPage(E page, @Param("ew") Wrapper<T> queryWrapper);
    <E extends IPage<Map<String, Object>>> E selectMapsPage(E page, @Param("ew") Wrapper<T> queryWrapper);
}
1.1 创建继承BaseMapper的实现类
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
1.2 在启动类添加@MapperScan扫描mapper
@SpringBootApplication
@MapperScan
public class MybatisplusApplication {
    public static void main(String[] args) {
        SpringApplication.run(MybatisplusApplication.class, args);
    }
}
1.3 创建实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("t_user")
public class User {
    private Long id;
    private String name;
    private String email;
    private Integer age;
}
如果不使用t_user则对应表名为类名首字母小写 即user
1.4 测试
@SpringBootTest
class MybatisplusApplicationTests {
    @Autowired
    UserMapper userMapper;
    @Test
    void contextLoads() {
        List<User> users = userMapper.selectList(null);
        users.forEach(System.out::println);
    }
}
1.5 新增 insert
        User user = new User();
        user.setName("ryuu");
        user.setAge(25);
        user.setEmail("123456789@qq.com");
        userMapper.insert(user);
        log.info("id" + user.getId());
JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@5a82ebf8] will be managed by Spring
==>  Preparing: INSERT INTO t_user ( id, name, email, age ) VALUES ( ?, ?, ?, ? )
==> Parameters: 1582699157263532033(Long), ryuu(String), 123456789@qq.com(String), 25(Integer)
<==    Updates: 1
Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@f096f37]
2022-10-19 19:44:18.924  INFO 20208 --- [           main] com.hikaru.MybatisplusApplicationTests   : id1582699157263532033
mybatisplus的新增是能够获取到自增长的主键的:: id 15826991572635
这个值是由雪花算法生成的
这里还测试出了个有意思的地方,在测试类上开启声明式事务@Transactional测试结束之后会自动回滚。。想了半天数据库为啥没有新增,然后看到控制台打印如下:
Rolled back transaction for test: [DefaultTestContext@550dbc7a testClass = MybatisplusApplicationTests, testInstance = com.hikaru.MybatisplusApplicationTests@4f80542f, testMethod = contextLoads@MybatisplusApplicationTests, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@21282ed8 testClass = MybatisplusApplicationTests, locations = '{}', classes = '{class com.hikaru.MybatisplusApplication}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@6ac13091, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@75329a49, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@1534f01b, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@2473d930, org.springframework.boot.test.context.SpringBootTestArgs@1, org.springframework.boot.test.context.SpringBootTestWebEnvironment@7382f612], contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map[[empty]]]
1.6 删除
① deleteById
userMapper.deleteById(1582701639167422466L);
② deleteByMap
        Map<String, Object> map = new HashMap<>();
        map.put("name", "zhangsan");
        map.put("age", 23);
        userMapper.deleteByMap(map);
deleteByMap会按照map进行删除,其中map存放的是删除的条件的键值对,条件之间为且的关系
==>  Preparing: DELETE FROM t_user WHERE name = ? AND age = ?
==> Parameters: zhangsan(String), 23(Integer)
<==    Updates: 0
③ deleteBatchIds 批量删除
    @Test
    void contextLoads() {
        List<Long> idList = Arrays.asList(1L, 2L, 3L);
        userMapper.deleteBatchIds(idList);
    }
deleteBatchIds采用的是in的批量删除
==>  Preparing: DELETE FROM t_user WHERE id IN ( ? , ? , ? )
==> Parameters: 1(Long), 2(Long), 3(Long)
<==    Updates: 0
1.7 修改
updateById(Entity)
    @Test
    void contextLoads() {
        User user = new User();
        //user.setId(1L);
        user.setEmail("5462316489@qq.com");
        user.setName("zhangsan");
        userMapper.updateById(user);
    }
updateById会根据参数实体的id去按照条件修改
==>  Preparing: UPDATE t_user SET name=?, email=? WHERE id=?
==> Parameters: zhangsan(String), 5462316489@qq.com(String), null
<==    Updates: 0
可以看到这里没有设置age字段就不会出现在sql语句的条件里面,
没有设置id则id为null
1.8 查询
① selectById
② selectBatchIds
③ selectByMaps
④ selectList()
条件查询,如果选择器为null则查询所有数据
1.9 自定义查询
① 在application.yml配置mapper.xml文件位置
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    url: jdbc:mysql://192.168.60.100/mybatisplus?characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  mapper-locations: classpath*:/mapper/**/*.xml
这里mapper-locations的值即为默认值
② 创建UserMapper.xml
<?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.hikaru.mapper.UserMapper">
    <select id="selectMapById" resultType="map">
        select *
        from t_user
        where id = #{id}
    </select>
</mapper>
③ 创建UserMapper接口的方法
@Mapper
public interface UserMapper extends BaseMapper<User> {
    public Map<String, Object> selectMapById(@Param("id") long id);
}
这里可能出现@MapKey is required 的错误警告,无视就好,mybatisplus会自动将字段名和值对应key-value
2 IService
2.1 创建service
public interface UserService extends IService<User> {
}
2.2 创建ServiceImpl
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}
注意泛型对应
2.3 查询总记录数 count
    @Autowired
    UserService userService;
    @Test
    void contextLoads() {
        userService.count();
    }
2.6 批量添加
    @Test
    void contextLoads() {
        List<User> list = new ArrayList<>();
        for(int i = 0; i < 10; i++) {
            User user = new User();
            user.setName("ryuu" + i);
            user.setAge(20 + i);
            user.setEmail("123123213@qq.com");
            list.add(user);
        }
        boolean b = userService.saveBatch(list);
        log.info(Boolean.toString(b));
    }
因为mapper的insert只有单个添加,这是因为批量添加会导致sql语句过长,这也是有service层的原因,而上面service的本质也是多次调用了mapper:
==>  Preparing: INSERT INTO t_user ( id, name, email, age ) VALUES ( ?, ?, ?, ? )
==> Parameters: 1582722877105381377(Long), ryuu0(String), 123123213@qq.com(String), 20(Integer)
==> Parameters: 1582722877289930754(Long), ryuu1(String), 123123213@qq.com(String), 21(Integer)
==> Parameters: 1582722877289930755(Long), ryuu2(String), 123123213@qq.com(String), 22(Integer)
==> Parameters: 1582722877289930756(Long), ryuu3(String), 123123213@qq.com(String), 23(Integer)
==> Parameters: 1582722877289930757(Long), ryuu4(String), 123123213@qq.com(String), 24(Integer)
==> Parameters: 1582722877348651010(Long), ryuu5(String), 123123213@qq.com(String), 25(Integer)
==> Parameters: 1582722877348651011(Long), ryuu6(String), 123123213@qq.com(String), 26(Integer)
==> Parameters: 1582722877348651012(Long), ryuu7(String), 123123213@qq.com(String), 27(Integer)
==> Parameters: 1582722877348651013(Long), ryuu8(String), 123123213@qq.com(String), 28(Integer)
==> Parameters: 1582722877348651014(Long), ryuu9(String), 123123213@qq.com(String), 29(Integer)
3 MybatisPlus常用注解
3.1 @TableName
在实体类上添加用于指定实体类对应的数据库表名,不添加则默认为首字母小写的类名
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("t_user")
public class User {
    private Long id;
    private String name;
    private String email;
    private Integer age;
}
3.2 @TableId
在实体类属性上添加@TableId将属性对应的字段指定为主键,如果不添加则默认主键为id并且会使用雪花算法进行生成。即当表的主键不是id则需要使用该注解。
属性对应的字段作为主键,是因为mp的框架结构需要先扫描实体类,然后抽取属性对字段进行操作的
而注解的value属性则适用于实体类属性名和字段名不同的情况,不写则与属性相同。
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("t_user")
public class User {
    @TableId("uid")
    private Long id;
    private String name;
    private String email;
    private Integer age;
}
TableId的type属性
type属性用于指定主键的生成策略,默认为雪花算法,即使数据库使用了自动递增也是雪花算法。 而如果想要使用自动递增,还需要设置type:
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("t_user")
public class User {
    @TableId(value = "uid", type = IdType.AUTO)
    private Long id;
    private String name;
    private String email;
    private Integer age;
}
其中IdType为一个枚举类,常用的主键生成策略主要有两种:
AUTO(0):自动递增
ASSIGN_ID(3):雪花算法(id为空的时候默认的策略)
public enum IdType {
    AUTO(0),
    NONE(1),
    INPUT(2),
    ASSIGN_ID(3),
    ASSIGN_UUID(4),
    /** @deprecated */
    @Deprecated
    ID_WORKER(3),
    /** @deprecated */
    @Deprecated
    ID_WORKER_STR(3),
    /** @deprecated */
    @Deprecated
    UUID(4);
    private final int key;
    private IdType(int key) {
        this.key = key;
    }
    public int getKey() {
        return this.key;
    }
}
通过全局配置主键生成策略和表前缀
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    db-config:
      id-type: auto
      table-prefix: t_
4 雪花算法
数据库扩展的方式主要包括:
业务分库:
主从复制:即在保证数据一致的前提下,主服务器和从服务器实现表的读写分离。
数据库分表:分为水平和垂直分表。
雪花算法是Twitter公布的一种分布式主键生成算法,它能够保证不同表的主键的不重复性和相同表的主键的有序性。
5 MBP常用注解
5.1 @TableFiled 设置属性对应普通字段名
MBP默认的规则是下划线字段名对应实体的驼峰写法,除此之外不一致的情况需要使用@TableFiled:
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("t_user")
public class User {
    @TableId(value = "uid")
    private Long id;
    @TableField("user_name")
    private String name;
    private String email;
    private Integer age;
}
@TableField(exist = false)
注解表明该属性不是数据库表的字段
5.2 @TableLogic 逻辑删除
- 物理删除:真实删除,将数据从数据库表中删除,之后查询不到此条被删除的数据 
- 逻辑删除:假删除,只是将数据库中该数据设置为删除状态,之后仍然能从数据库中看到 
- 使用场景:数据恢复 
① 首先在逻辑删除属性上添加注解
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("t_user")
public class User {
    @TableId(value = "uid")
    private Long id;
    @TableField("user_name")
    private String name;
    private String email;
    private Integer age;
    @TableLogic
    private Integer isDelete;
}
② 进行删除操作
    @Autowired
    UserService userService;
    @Test
    void contextLoads() {
        userService.removeById(1);
    }
③ 观察这时候的sql语句,删除被替换为了更新:
==>  Preparing: UPDATE t_user SET is_delete=1 WHERE uid=? AND is_delete=0
==> Parameters: 1(Integer)
<==    Updates: 0
如果进行数据恢复,只需要将isDelete恢复为0即可
6 条件构造器 wrapper

- Wrapper:条件构造器的抽象类,最顶端的父类 - AbstractWrapper:用于查询条件封装,生成sql的where条件 - QueryWrapper:查询条件封装 
- UpdateWrapper:Update条件封装 
- AbstractLambdaWrapper:使用Lambda语法 - LambdaQueryWrapper:Lambda查询封装 
- LambdaUpdateWrapper:Lambda update封装 
 
 
 
updateWrapper不但需要封装修改的条件还需要封装修改的字段,而删除是不需要提供字段只需要条件,因此查询和删除都使用QueryMapper做条件封装。
6.1 组装查询条件
    @Test
    void contextLoads() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("user_name", 2)
                .between("age", 20, 25)
                .isNotNull("email");
        System.out.println(userService.list(queryWrapper));
    }
对应的SQL
==>  Preparing: SELECT uid AS id,user_name AS name,email,age,is_delete FROM t_user WHERE is_delete=0 AND (user_name LIKE ? AND age BETWEEN ? AND ? AND email IS NOT NULL)
==> Parameters: %2%(String), 20(Integer), 25(Integer)
<==    Columns: id, name, email, age, is_delete
<==        Row: 3, ryuu2, 123123213@qq.com, 22, 0
<==        Row: 13, ryuu2, 123123213@qq.com, 22, 0
<==      Total: 2
6.2 组装排序条件
    @Test
    void contextLoads() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc("age").orderByAsc("uid");
        System.out.println(userService.list(queryWrapper));
    }
对应SQL
==>  Preparing: SEECT uid AS id,user_name AS name,email,age,is_delete
FROM t_user WHERE is_delete=0
ORDER BY age DESC,uid ASC
6.3 组装删除条件
    @Test
    void contextLoads() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.isNull("email");
        System.out.println(userMapper.delete(queryWrapper));
    }
对应sql
==>  Preparing: UPDATE t_user SET is_delete=1 WHERE is_delete=0 AND (email IS NULL)
==> Parameters:
<==    Updates: 1
6.4 组装修改功能
① 使用queryWrapper实现修改
    @Test
    void contextLoads() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("uid", 1)
                .between("age", 20, 25)
                .isNotNull("email");
        User user = new User();
        user.setName("小明");
        user.setEmail("xiaoming@163.com");
        userMapper.update(user, queryWrapper);
    }
对应SQL
==>  Preparing: UPDATE t_user SET user_name=?, email=?
WHERE is_delete=0 AND (uid LIKE ? AND age BETWEEN ? AND ? AND email IS NOT NULL)
==> Parameters: 小明(String), xiaoming@163.com(String), %1%(String), 20(Integer), 25(Integer)
② 使用UpdateWrapper实现修改
    @Test
    void contextLoads() {
        // 将用户名中含有a 并且 (年龄大于20 或者 邮箱为null)的用户信息进行修改
        UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
        updateWrapper.like("user_name", "a")
                .and(i -> i.gt("age", 20)
                        .or()
                        .isNotNull("email")
                );
        updateWrapper.set("user_name", "小黑");
        int update = userMapper.update(null, updateWrapper);
        log.info(String.valueOf(update));
    }
对应SQL
==>  Preparing: UPDATE t_user SET user_name=?
WHERE is_delete=0
AND (user_name LIKE ? AND (age > ? OR email IS NOT NULL))
==> Parameters: 小黑(String), %a%(String), 20(Integer)
6.5 组装select语句 实现查询指定字段
    @Test
    void contextLoads() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("user_name", "age");
        List<Map<String, Object>> list = userMapper.selectMaps(queryWrapper);
        System.out.println(list);
    }
注意需要使用selectMaps接收
6.6 组装子查询
    @Test
    void contextLoads() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.inSql("uid", "select uid from t_user where age > 25");
        List<User> users = userMapper.selectList(queryWrapper);
        System.out.println(users);
    }
对应SQL
==>  Preparing: SELECT uid AS id,user_name AS name,email,age,is_delete
FROM t_user WHERE is_delete=0
AND (uid IN (select uid from t_user where age > 25))
==> Parameters:
<==    Columns: id, name, email, age, is_delete
6.7 模拟开发中的条件组装
    @Test
    void contextLoads() {
        UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
        String userName = "r";
        Integer ageBegin =20;
        Integer ageEnd =25;
        if(StringUtils.isBlank(userName)) {
            updateWrapper.like("user_name", "a");
        }
        if(ageBegin != null) {
            updateWrapper.gt("age", ageBegin);
        }
        if(ageEnd != null) {
            updateWrapper.lt("age", ageEnd);
        }
        updateWrapper.set("user_name", "小黑");
        int update = userMapper.update(null, updateWrapper);
        log.info(String.valueOf(update));
    }
StringUtils.isBlank 判断字符串
① 不为空串
② 不为null
③ 不为空白符
==>  Preparing: UPDATE t_user SET user_name=? WHERE is_delete=0 AND (age > ? AND age < ?)
==> Parameters: 小黑(String), 20(Integer), 25(Integer)
<==    Updates: 8
6.8 使用condition进行条件判断
上面的写法需要用户传入条件后对每个条件进行编写判断,变得十分复杂
7 Lambda表达式优先执行实现条件优先级
考虑下面两条sql的条件优先级:
// 将用户名包含r 并且 年龄大于20 或者 邮箱为null的用户信息进行修改
            // 将用户名包含r 并且 (年龄大于20 或者 邮箱为null)的用户信息进行修改
    @Test
    void contextLoads() {
        // 将用户名包含r 并且 年龄大于20 或者 邮箱为null的用户信息进行修改
        // 将用户名包含r 并且 (年龄大于20 或者 邮箱为null)的用户信息进行修改
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("user_name", "r")
                .and(i -> i.gt("age", 20)
                        .or()
                        .isNull("email")
                );
        User user = new User();
        user.setName("小Li");
        user.setEmail("xiaoLi@163.com");
        userMapper.update(user, queryWrapper);
    }
利用Lambda表达式优先执行实现条件的优先级
对应SQL
==>  Preparing: UPDATE t_user SET user_name=?, email=? WHERE is_delete=0
AND (user_name LIKE ? AND (age > ? OR email IS NULL))
==> Parameters: 小Li(String), xiaoLi@163.com(String), %r%(String), 20(Integer)
<==    Updates: 13
8 LambdaQueryWraper
上面的代码中充斥着大量的字段名魔法值,为了防止字段写错,使用Lambda表达式来获取属性对应的字段名
    @Test
    public void lambadaQueryMapperTest() {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        String userName = "8";
        queryWrapper.like(StringUtils.isNotBlank(userName), User::getName, userName)
                .ge(User::getAge, 20)
                .le(User::getAge, 21);
        List<User> users = userMapper.selectList(queryWrapper);
        System.out.println(users);
    }
对应SQL
==>  Preparing: SELECT uid AS id,user_name AS name,email,age,is_delete FROM t_user WHERE is_delete=0 AND (user_name LIKE ? AND age >= ? AND age <= ?)
==> Parameters: %8%(String), 20(Integer), 21(Integer)
<==      Total: 0
9 LambdaUpdateWraper
    @Test
    void contextLoads() {
        LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
        String userName = "r";
        Integer ageBegin =20;
        Integer ageEnd =25;
        updateWrapper.like(StringUtils.isNotBlank(userName), User::getName, userName)
                .gt(ageBegin!=null, User::getAge, ageBegin)
                .lt(ageEnd!=null, User::getAge, ageEnd);
        updateWrapper.set(User::getName, "小黑");
        int update = userMapper.update(null, updateWrapper);
        log.info(String.valueOf(update));
    }
对应SQL
==>  Preparing: UPDATE t_user SET user_name=? WHERE is_delete=0 AND (user_name LIKE ? AND age > ? AND age < ?)
==> Parameters: 小黑(String), %r%(String), 20(Integer), 25(Integer)
<==    Updates: 0
10 MybatisPlus插件
Mybatis自带分页插件,只需要简单的配置就可实现分页功能
配置插件
@Configuration
@MapperScan("com.hikaru.mapper.UserMapper")
public class MybatisConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}
插件使用
    @Test
    public void testPage() {
        Page<User> page = new Page<>(2, 3);
        userMapper.selectPage(page, null);
        System.out.println(page.getRecords());
    }
对应SQL:
Preparing: SELECT uid AS id,user_name AS name,email,age,is_delete FROM t_user WHERE is_delete=0 LIMIT ?,?
自定义分页功能
① 在mapper.xml中编写SQL
<mapper namespace="com.hikaru.mapper.UserMapper">
    <select id="selectMapById" resultType="map">
        select *
        from t_user
        where id = #{id}
    </select>
    <select id="selectUserVOPage" resultType="User">
        select * from t_user where age > #{age}
    </select>
</mapper>
这里能够直接在resultType中写User是因为使用了类型别名(为不区分大小写的类名),类型别名的包在配置文件中配置:
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    db-config:
      table-prefix: t_
      id-type: auto
  type-aliases-package: com.hikaru.entity
② 在Mapper接口中定义对应的方法
Page<User> selectUserVOPage(@Param("page") Page<User> page,
                            @Param("age") int age);
注意这里第一个参数必须为对应泛型型的page,返回值类型也必须为对应泛型型的Page
乐观锁与悲观锁
剩下的内容等以后再看吧。。
【Mybatis Plus】的更多相关文章
- 【MyBatis笔记】mapper文件的配置以及说明
		<!doctype html>[MyBatis笔记]mapper文件的配置以及说明 figure:last-child { margin-bottom: 0.5rem; } #write ... 
- 【mybatis笔记】 resultType与resultMap的区别
		序言: 昨天做一个项目,看到很多刚开始用mybatis的同事对于resultType和resultMap的理解与使用含糊不清,这里我试图用最好理解的说法写一写,欢迎大家勘误. 两者异同: 相同点:re ... 
- 【Mybatis架构】Mapper映射文件中的#{}与${}
		前言 还记得当初从北京回来的时候,跟着倪文杰师姐做JavaITOO的一卡通模块,我亲姐贾梦洁带着我一块做,期间,我遇到了一个特别奇葩的问题,就死我要实现Mybatis的模糊查询,根据当时亲姐教给我方法 ... 
- 【Mybatis架构】 延迟加载
		在上一篇博客中,我们提到过有关于Mybatis输出映射中resultMap能够实现延迟加载的事,然而真的是所有的resultMap都能实现延迟加载还是咋地啊?现在我们就来对那一句话做一下阐述和实例说明 ... 
- 【Mybatis框架】查询缓存(二级缓存)
		继上一篇博客,我们讲述了mybatis的一级缓存,接下来,我们来学习一下mybatis的二级缓存 博客链接地址: http://blog.csdn.NET/liweizhong193516/artic ... 
- 【Mybatis架构】输入、输出映射
		前言综述: 其实在我们分析Mybatis的查询缓存或者是一些简介的时候,我们就不难看到有关于Mybatis输入输出映射的东西,比如说: 但是一直没有想起来系统的来总结一下这方面的相关知识,偶然看到 ... 
- 【Mybatis框架】查询缓存(一级缓存)
		做Java的各位程序员们,估计SSH和SSM是我们的基础必备框架.也就是说我们都已经至少接触过了这两套常见的集成框架.当我们用SSH的时候,相信很多人都接触过hibernate的两级缓存,同样,相对应 ... 
- 【mybatis基础】mybatis开发dao两种方法
		mybatis是一个支持普通SQL查询,存储过程和高级映射的优秀的持久层的框架,是apache下的顶级项目.mybatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装.mybat ... 
- 【Mybatis异常】 org.apache.ibatis.binding.BindingException: Parameter 'storeId' not found. Available parameters are [form, param1]
		一.异常信息 2019-05-31 16:06:25.272 [http-nio-10650-exec-3] WARN o.s.w.s.m.m.a.ExceptionHandlerExceptionR ... 
- 【mybatis xml】数据层框架应用--Mybatis 基于XML映射文件实现数据的CRUD
		使用MyBatis框架进行持久层开发 MyBatis是支持普通SQL查询,存储过程和高级映射的优秀持久层框架. MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索. MyBa ... 
随机推荐
- Java 方法详解 与数组
			基础阶段: 1.何谓方法 何谓方法?◆System.out.println(),那么它是什么呢?◆Java方法是语句的集合,它们在- -起执行一个功能. ◆方法是解决一类问题的步骤的有序组合 ... 
- 【第4次作业】CNN实战
			使用VGG模型进行猫狗大战 import numpy as np import matplotlib.pyplot as plt import os import torch import torch ... 
- 用bat文件,自动进入cmd虚拟环境
			L:cd L:\myenv\Scriptscmd /K activate.bat 这行,这样写,cmd窗口会继续保留,按任意键也不会关闭. 这个问题网上大部分说法是在批处理里面加上 cmd /k, ... 
-  NuGet国内镜像
			NuGet国内镜像 https://nuget.cdn.azure.cn/v3/index.json 
- 将 Sql Server 表信息 C# 对象化 小工具_ 张光荣 的 正能量
			注: a.此程序所得到的结果是根据本人个人习惯生成,所以,肯定不完全适合所有人使用,重在想法...然后个人根据个人需求作出更进...b.程序中可能会出现数据库连接的错误提示[原因概是在sql 连接过程 ... 
- raid随笔
			1.raid 0 准备两个磁盘 [root@localhost ~]# lsblkNAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTsda 8:0 0 40G 0 disk ... 
- 3.javaweb-servlet
			1. 设置编码 tomcat8之前,设置编码: 1)get请求方式: //get方式目前不需要设置编码(基于tomcat8) //如果是get请求发送的中文数据,转码稍微有点麻烦(tomcat8之前) ... 
- MYSQL DUAL(伪表)
			#DUAL是一个伪表,不存在的表. SELECT 8*9 FROM DUAL #输出72 
- linux 安装配置redis
			linux 安装配置redis 安装 官网下载地址:https://redis.io/download linux下载命令:wget http://download.redis.io/releases ... 
- MySql8错误记录.巨坑!File './binlog.index' not found
			mysql8存在大小写敏感,若要设置不敏感,需要在mysql初始化时设置:然后库中已有项目存在,mysql备份文件夹后无法重启,还原数据后存在权限问题,更改文件夹权限后,发现仍然不行,将SELinux ... 
