加入依赖
<!--MyBatis-Plus的stater-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.1</version>
</dependency>
<!-- Druid的stater-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
分页使用
分页拦截器
@Configuration
public class MPConfig {
/**
* mp的拦截器
* @return
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
//mp的分页拦截器
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
// new PaginationInnerInterceptor() mp的分页插件
// addInnerInterceptor 在mp的拦截器中 添加某个插件
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
//乐观锁拦截器
mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return mybatisPlusInterceptor;
}
}
代码实现
/**
* 分页查询
*/
@Test
void page() {
IPage<User> userIPage = new Page<>();
//当前页
userIPage.setCurrent(1);
//当前要显示多少行
userIPage.setSize(3);
IPage<User> selectPage = mapper.selectPage(userIPage, null);
//数据
for (User record : selectPage.getRecords()) {
log.info(record.toString());
}
log.info("当前分页总页数====>{}",selectPage.getPages());
log.info("当前分页总行数====>{}",selectPage.getTotal());
}
server:
port: 8080
# 数据库连接地址
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://localhost:3306/mybatisplus_db?serverTimezone=UTC
username: root
password: root123qwe
mybatis-plus:
global-config:
db-config:
# 数据库id生成策略
id-type: auto
# 表名前缀
table-prefix: tbl_
# 逻辑删除字段
logic-delete-field: deleted
# 表示已经删除
logic-delete-value: 1
# 表述未删除
logic-not-delete-value: 0
configuration:
# 日志输出
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 驼峰
map-underscore-to-camel-case: true
配置文件
条件查询
/**
* 查询
*/
@Test
void getList04() {
// 第二种条件查询方式
// QueryWrapper<User> queryWrapper = new QueryWrapper<>();
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
// 前端传递的条件
// 有可能不传
User user1 = new User();
// 如果不为空 进行查询
// 如果前端为null 就不需要拼接查询条件
if (!StringUtils.isBlank(user1.getName())) {
// 大于18 并且 小于 30
queryWrapper.gt(User::getName, user1.getName());
}
queryWrapper.gt(StringUtils.isNotBlank(user1.getName()), User::getName, user1.getName());
// select * from user where age > 18 and age < 30
List<User> users = this.userMapper.selectList(queryWrapper);
for (User user : users) {
log.info(user.toString());
}
}
查询表中制定存在的字段
/**
* 查询
*/
@Test
void getList06() {
// 只查询表中的某个字段
// QueryWrapper<User> queryWrapper = new QueryWrapper<>();
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
// select id,age,name from user
queryWrapper.select(User::getId, User::getAge, User::getName);
List<User> users = this.userMapper.selectList(queryWrapper);
for (User user : users) {
log.info(user.toString());
}
}
查询表中不存在的字段
/**
* 查询
*/
@Test
void getList07() {
// 返回实体中不存在的字段
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
// QueryWrapper里可以写MySQL中的一些函数
queryWrapper.select("count(*) as count");
// 返回实体中不存在的字段,直接返回map
List<Map<String, Object>> maps = this.userMapper.selectMaps(queryWrapper);
// 查询表中数据的数量
// Integer i = this.userMapper.selectCount(queryWrapper);
log.info("maps ===> {}", maps.toString());
}
or的使用
/**
* 查询
*/
@Test
void getList05() {
// 第二种条件查询方式
// QueryWrapper<User> queryWrapper = new QueryWrapper<>();
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
// 大于18 并且 小于 30
// SELECT id,name,password,age,tel FROM user WHERE (age = 10 OR age = 12 AND age = 13)
// SELECT id,name,password,age,tel FROM user WHERE ((age = 10 OR age = 12) AND age = 13)
// queryWrapper.
// eq(User::getAge, 18)
// .or()
// .eq(User::getAge, 22);
// queryWrapper.eq(User::getAge, 22);
queryWrapper.or(i -> i.eq(User::getAge, 18).eq(User::getAge, 22));
queryWrapper.eq(User::getAge, 22);
// queryWrapper.and(i -> i.like(User::getId, 1).eq(User::getId, 2));
// select * from user where age > 18 and age < 30
List<User> users = this.userMapper.selectList(queryWrapper);
for (User user : users) {
log.info(user.toString());
}
}
条件查询
/**
* 查询
*/
@Test
void getList08() {
// 查询条件学习
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
// gt 大于 lt 小于
// queryWrapper.gt(User::getAge,18);
// ge 大于等于 le 小于等于
// queryWrapper.ge(User::getAge,18);
// 介于..之间
// queryWrapper.between(User::getAge, 18, 30);
// 模糊匹配
// 命中不了索引
// queryWrapper.like(User::getName, "张");
// 百分号在左边
// queryWrapper.likeLeft()
// 百分号在右边
// queryWrapper.likeRight()
// in
// queryWrapper.in(User::getId, 1, 2, 3, 4);
// queryWrapper.in(User::getId, Arrays.asList(1, 2, 3, 4));
// 等于
// queryWrapper.eq(User::getId, 1);
// 分组
// select age from user group by age;
// queryWrapper.select(User::getAge);
// queryWrapper.groupBy(User::getAge);
// 升序
// queryWrapper.orderBy(true, true, User::getAge);
// 降序
queryWrapper.orderBy(true, false, User::getAge);
List<User> users = this.userMapper.selectList(queryWrapper);
for (User user : users) {
log.info(user.toString());
}
}
-
问题一:表字段与编码属性设计不同步
-
问题二:编码中添加了数据库中未定义的属性
-
问题三:采用默认查询开放了更多的字段查看权限
-
问题四:表名与编码开发设计不同步
@Data public class User { // null @TableId(type = IdType.AUTO) private Long id; private String name; @TableField(value = "pwd", select = false) private String password; private Integer age; private String tel; @TableField(exist = false) private Integer online; /** * 逻辑删除 */ @TableLogic private Integer deleted; /** * 乐观锁字段 */ @Version private Integer version; }
-
逻辑删除
-
mybatis-plus: global-config: db-config: table-prefix: tbl_ # 逻辑删除字段名 logic-delete-field: deleted # 逻辑删除字面值:未删除为0 logic-not-delete-value: 0 # 逻辑删除字面值:删除为1 logic-delete-value: 1
/** * 逻辑删除 */ @TableLogic private Integer deleted;
配置文件里写了默认删除字段就不用加注解啦
-
乐观锁
-
拦截器
-
// 乐观锁拦截器 OptimisticLockerInnerInterceptor mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
字段
-
/** * 乐观锁字段 */ @Version private Integer version;
/** * 测试乐观锁 */ @Test void testLock() { User user = new User(); user.setId(1L); user.setName("李四"); // 版本号有值 user.setVersion(0); // 更新数据 // 先查询数据库,获取这条数据,对比数据库中的数据和要更新的数据的版本号 User dbData = this.userMapper.selectById(1L); if (user.getVersion() == dbData.getVersion()) { // 数据没有被其他人修改过,可以更新 this.userMapper.updateById(user); } else { log.info("数据已经被其他人修改过,请刷新后重试"); return; } }
代码生成
<!--mp代码生成器--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-generator</artifactId> <version>3.4.1</version> </dependency> <!--模板引擎--> <dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity-engine-core</artifactId> <version>2.3</version> </dependency>
工具类
-
/** * MybatisPlus生成器 * * @author t3rik * @since 2021-06-18 16:55 */ public class GeneratorUtils { private final static String DB_URL = "jdbc:mysql://localhost:3306/mybatisplus_db?serverTimezone=UTC"; private final static String USER_NAME = "root"; private final static String PASSWORD = "root123qwe"; private final static String AUTHOR = "t3rik"; private final static String DRIVE = "com.mysql.cj.jdbc.Driver"; public static void main(String[] args) { // 代码生成器 AutoGenerator mpg = new AutoGenerator(); // 全局配置 GlobalConfig gc = new GlobalConfig(); // 取当前项目路径 String projectPath = System.getProperty("user.dir"); // 输出路径 gc.setOutputDir(projectPath + "/src/main/java/test"); // 类的作者 gc.setAuthor(AUTHOR); // 生成代码完成之后是否需要打开相应文件 gc.setOpen(false); // controller的名称 gc.setControllerName("%sController"); // service的名称 gc.setServiceName("I%sService"); // 实现类的名称 gc.setServiceImplName("%sServiceImpl"); // mapper的名词 gc.setMapperName("%sMapper"); // 加入配置 mpg.setGlobalConfig(gc); // 数据源配置 DataSourceConfig dsc = new DataSourceConfig(); // dsc.setSchemaName("public"); // 数据库连接地址 dsc.setUrl(DB_URL); // 驱动 dsc.setDriverName(DRIVE); // 用户名 dsc.setUsername(USER_NAME); // 密码 dsc.setPassword(PASSWORD); // 加入配置 mpg.setDataSource(dsc); // 包配置 PackageConfig pc = new PackageConfig(); // 父级 pc.setParent("com.itheima"); // entity pc.setEntity("entity"); // mapper pc.setMapper("mapper"); // controller pc.setController("controller"); // service pc.setService("service"); // 加入配置 mpg.setPackageInfo(pc); // 自定义配置 InjectionConfig cfg = new InjectionConfig() { @Override public void initMap() { // to do nothing } }; // 如果模板引擎是 velocity String templatePath = "/templates/mapper.xml.vm"; // 自定义输出配置 List<FileOutConfig> focList = new ArrayList<>(); // 自定义配置会被优先输出 focList.add(new FileOutConfig(templatePath) { @Override public String outputFile(TableInfo tableInfo) { // 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!! return projectPath + "/src/main/resources/mapper/" + pc.getModuleName() + "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML; } }); cfg.setFileOutConfigList(focList); mpg.setCfg(cfg); // 配置模板 TemplateConfig templateConfig = new TemplateConfig(); templateConfig.setXml(null); mpg.setTemplate(templateConfig); // 策略配置 StrategyConfig strategy = new StrategyConfig(); // 驼峰配置 数据库实体 strategy.setNaming(NamingStrategy.underline_to_camel); // 数据库表字段映射到实体的命名策略 驼峰 strategy.setColumnNaming(NamingStrategy.underline_to_camel); // 要生成的表 strategy.setInclude("tbl_user"); // 表的前缀 strategy.setTablePrefix("tbl_"); // 是否使用lombok strategy.setEntityLombokModel(true); // restfull风格 strategy.setRestControllerStyle(true); // 逻辑删除 strategy.setLogicDeleteFieldName("deleted"); // 乐观锁 strategy.setVersionFieldName("version"); // 驼峰转连字符 strategy.setControllerMappingHyphenStyle(true); // 设置配置 mpg.setStrategy(strategy); // 执行生成 mpg.execute(); } }
-
查看数据库表,表字段,的类型即,字段名