引入依赖

    <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】的更多相关文章

  1. 【MyBatis笔记】mapper文件的配置以及说明

    <!doctype html>[MyBatis笔记]mapper文件的配置以及说明 figure:last-child { margin-bottom: 0.5rem; } #write ...

  2. 【mybatis笔记】 resultType与resultMap的区别

    序言: 昨天做一个项目,看到很多刚开始用mybatis的同事对于resultType和resultMap的理解与使用含糊不清,这里我试图用最好理解的说法写一写,欢迎大家勘误. 两者异同: 相同点:re ...

  3. 【Mybatis架构】Mapper映射文件中的#{}与${}

    前言 还记得当初从北京回来的时候,跟着倪文杰师姐做JavaITOO的一卡通模块,我亲姐贾梦洁带着我一块做,期间,我遇到了一个特别奇葩的问题,就死我要实现Mybatis的模糊查询,根据当时亲姐教给我方法 ...

  4. 【Mybatis架构】 延迟加载

    在上一篇博客中,我们提到过有关于Mybatis输出映射中resultMap能够实现延迟加载的事,然而真的是所有的resultMap都能实现延迟加载还是咋地啊?现在我们就来对那一句话做一下阐述和实例说明 ...

  5. 【Mybatis框架】查询缓存(二级缓存)

    继上一篇博客,我们讲述了mybatis的一级缓存,接下来,我们来学习一下mybatis的二级缓存 博客链接地址: http://blog.csdn.NET/liweizhong193516/artic ...

  6. 【Mybatis架构】输入、输出映射

    前言综述:   其实在我们分析Mybatis的查询缓存或者是一些简介的时候,我们就不难看到有关于Mybatis输入输出映射的东西,比如说: 但是一直没有想起来系统的来总结一下这方面的相关知识,偶然看到 ...

  7. 【Mybatis框架】查询缓存(一级缓存)

    做Java的各位程序员们,估计SSH和SSM是我们的基础必备框架.也就是说我们都已经至少接触过了这两套常见的集成框架.当我们用SSH的时候,相信很多人都接触过hibernate的两级缓存,同样,相对应 ...

  8. 【mybatis基础】mybatis开发dao两种方法

    mybatis是一个支持普通SQL查询,存储过程和高级映射的优秀的持久层的框架,是apache下的顶级项目.mybatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装.mybat ...

  9. 【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 ...

  10. 【mybatis xml】数据层框架应用--Mybatis 基于XML映射文件实现数据的CRUD

    使用MyBatis框架进行持久层开发 MyBatis是支持普通SQL查询,存储过程和高级映射的优秀持久层框架. MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索. MyBa ...

随机推荐

  1. 12.1linux学习第十二 天

    8.2 Iptables 在早期的Linux系统中,默认使用的是iptables防火墙管理服务来配置防火墙.尽管新型的firewalld防火墙管理服务已经被投入使用多年,但是大量的企业在生产环境中依然 ...

  2. api进阶Day2(低级流)文件流的输出流、读取流。向文件中写入文本数据、读取文件中的字符串、用lambda表达式创建文件过滤器。

    文件流:输出流: package io; import java.io.FileNotFoundException; import java.io.FileOutputStream; import j ...

  3. python 安装fbprophet模块的艰辛历程

    fbprophet这个模块是我目前见过最难装的一个模块,我安装这个包安装了3天,气死我了,需求的依赖包太多,而且对依赖包的版本有极高的要求,所以建议在装这个模块的时候在一个空的虚拟环境下安装,这样依赖 ...

  4. linux 获取文件名

    https://blog.csdn.net/liuyuedechuchu/article/details/123778605

  5. IDEA Maven 项目报错 java: 程序包org.springframework.beans.factory.annotation不存在

    idea 刚把项目导进去的时候,点击运行,import的好多包都报红,所有的文件的Maven依赖包都没导入进去. 但只是第一个报错是: java: 程序包org.springframework.bea ...

  6. LoadRunner性能测试-app压力测试

    步骤分为三步: 一,录制脚本 录制脚本原理:启动LR代理服务器监听设置好的端口号是否有请求发送给服务器,有请求时,代理服务器接收请求,并转发给对应的系统服务器,LR从而获取到请求的信息与数据,生成脚本 ...

  7. VScode好用插件

    1.Anaconda Extension Pack 可以自动补全anaconda包中的属性名称 2.Code Spell Checker 单词拼写检查,非常推荐,有时候会拼错单词,这个不仅可以指出错误 ...

  8. 1.HTML中的标签

    1.HTML的基础标签 <!--        -->  表示注释 1)  html语言是解释型语言,不是编译型 浏览器是容错的2)  html页面中由一对标签组成:<html> ...

  9. 第二章 excel的快捷键操作

    本章介绍excel中部分常用的快捷键 1.文件类 工作簿操作:Ctrl + N 新建:Ctrl + w 关闭当前:Ctrl + S 保存 F12 当前另存为 Ctrl + p 打印当前 2.通用类 C ...

  10. ls和mkdir

    ls  查看当前目录的内容 1) ls -l 显示详细列表 2) Ls -lh 吧文件大小以人性化的方式展开 3) ls -a 显示所有的文件,包括隐藏文件,隐藏文件是已.开头的文件 4) ll 等于 ...