引入依赖

    <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

乐观锁与悲观锁

剩下的内容等以后再看吧。。

原文地址:http://www.cnblogs.com/tod4/p/16818411.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性