初步体验
安装
注:引入mybatis-plus后就无需再次引入mybatis
<!-- mybatis-plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3.4</version>
</dependency>
创建数据
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` bigint(20) NOT NULL COMMENT '主键ID',
`name` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '姓名',
`age` int(11) NULL DEFAULT NULL COMMENT '年龄',
`email` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '邮箱',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, 'Jone', 18, 'test1@baomidou.com');
INSERT INTO `user` VALUES (2, 'Jack', 20, 'test2@baomidou.com');
INSERT INTO `user` VALUES (3, 'Tom', 28, 'test3@baomidou.com');
INSERT INTO `user` VALUES (4, 'Sandy', 21, 'test4@baomidou.com');
INSERT INTO `user` VALUES (5, 'Billie', 24, 'test5@baomidou.com');
SET FOREIGN_KEY_CHECKS = 1;
appliaction.properties配置
#数据库配置
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/mybatis-plus-demo?characterEncoding=utf8&autoReconnect=true&failOverReadOnly=false&maxReconnects=10&interactiveClient=true&allowMultiQueries=true
#日志配置控制台打印SQL
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
创建User类
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private long id;
private String name;
private long age;
private String email;
}
创建User类
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.wf.mybatisplusdemo.pojo.User;
import org.springframework.stereotype.Repository;
/**
1. 编写Mapper接口,此处将不在需要编写相应xml文件
*/
@Repository
public interface UserMapper extends BaseMapper<User> {
}
配置注解扫描
@SpringBootApplication
@MapperScan("com.wf.mybatisplusdemo.mapper")
public class MybatisPlusDemoApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisPlusDemoApplication.class, args);
}
}
运行
import com.wf.mybatisplusdemo.mapper.UserMapper;
import com.wf.mybatisplusdemo.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
class MybatisPlusDemoApplicationTests {
@Autowired
private UserMapper userMapper;
@Test
void contextLoads() {
//此处的参数为查询条件,当前表示无条件查询
List<User> users = userMapper.selectList(null);
users.forEach(System.out::println);
}
}
运行结果
实体类注解(以下叙述中属性并不完整)
@TableName ---标注表名
value (属性) 作用:表名
resultMap (属性) 作用:xml 中 resultMap 的 id
excludeProperty (属性) 作用:需要排除的属性名
@TableId---标注主键
value (属性) 作用:主键字段名称
type (属性) 作用:主键类型 (默认IdType.NONE,即没有主键)
type可选值:
IdType.AUTO 数据库ID自增
IdType.NONE 没有主键
IdType.INPUT 手动输入
IdType.ASSIGN_ID 使用雪花算法分配ID(主键类型为Number(Long和Integer)或String)
IdType.ASSIGN_UUID 分配一个不包含下划线32位的UUID,主键类型为String
@TableField---字段注解(非主键)
value(属性) 作用:数据库字段名
el (属性)作用:映射为原生 #{ … } 逻辑,相当于写在 xml 里的 #{ … } 部分
fill (属性) 作用:字段自动填充策略,比如自动生成创建时间(默认FieldFill.DEFAULT,即,不处理)
FieldFill可选值:
DEFAULT 默认不处理
INSERT 插入时填充字段
UPDATE 更新时填充字段
INSERT_UPDATE 插入和更新时填充字段
注:在添加fill (自动填充属性后,需要自定义生成策略,否则将会为null)
例:
实体类:
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("user")
public class User {
@TableField(value="create_time",fill = FieldFill.DEFAULT)
private Date createTime;
}
生成策略:
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
/**
* 新增时,自动填充规则
* @param metaObject
*/
@Override
public void insertFill(MetaObject metaObject) {
log.info("start insert fill ....");
//createTime 为需要生成策略的字段名称
//new Date() 填充的值
this.setFieldValByName("createTime",new Date(),metaObject);
}
/**
* 修改时,自动填充规则
* @param metaObject
*/
@Override
public void updateFill(MetaObject metaObject) {
}
}
@Version ---乐观锁注解,标注在version字段上
乐观锁的作用:当要更新一条记录的时候,希望这条记录没有被别人更新
乐观锁的实现方式:取出记录时,获取当前version值,在执行更新操作时,带上这个version值 set version = newVersion where version = oldVersion 如果version不对,说明这条记录已经被别人更新过了,本次更新就应该失败
例:
1.数据库表新增version(版本号)字段,默认值为1
2.实体类新增version属性
import com.baomidou.mybatisplus.annotation.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("user")
public class User {
@TableId(value = "id",type = IdType.ASSIGN_ID)
private String id;
private String name;
private long age;
private String email;
@TableField(value="create_time",fill = FieldFill.INSERT)
private Date createTime;
/**
* 标注为乐观锁
*/
@Version
private Integer version;
}
3.注册乐观锁组件
package com.wf.mybatisplusdemo.config;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@EnableTransactionManagement //自动管理事务
@Configuration
public class MybatisPlusConfig {
/**
* 注册乐观锁插件
* @return
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
}
4.测试结果
/**
* 测试乐观锁
*/
@Test
void testMybatisPlusInterceptor(){
/**
* 注:因为实体类中使用了version注解,所以此处无需为version字段赋值,mybatisPlus会自动跟新version
*/
//查询user,数据1
User user=userMapper.selectById(1);
user.setName("第一");
user.setAge(1);
//查询user,数据2
User user2=userMapper.selectById(1);
user2.setName("第二");
user2.setAge(2);
//此处模拟多线程情况下,user2先被更新,然后user1再被跟新
userMapper.updateById(user2);
//此处的修改,就会失败,因为version已经不同了
userMapper.updateById(user);
}
@TableLogic ---表字段逻辑处理注解(逻辑删除)
value (属性) 作用:逻辑未删除值
delval (属性) 作用:逻辑删除值
逻辑删除
逻辑删除:通过数据库中的字段状态值来控制数据的有效性,比如,表中含有start字段,当该字段的值为0时,表示该数据有效,当值为1时,表示该数据已经被删除
注:使用逻辑删除后,在查询和修改时,都会将该字段值作为where条件,所以查询时就不会查询出删除的数据,更新也不会更新删除的数据,在删除时执行的将会是修改操作
- 数据库新增逻辑删除字段
2.实体类标注注解
/**
* 逻辑删除字段
* 此处标注过value 和 delval 后,如果不存在全局逻辑删除字段,则无需步骤3中的内容
*/
@TableLogic(value = "0",delval ="1")
private Integer start;
3.全局逻辑删除配置(若不存在全局配置,而在@TableLogic注解中就已经标注了未删除值和,已删除值,这样也可以执行,就不需要以下配置了)
# 全局逻辑删除的实体字段名
mybatis-plus.global-config.db-config.logic-delete-field=flag
# 全局逻辑已删除值(默认为 1)
mybatis-plus.global-config.db-config.logic-delete-value=1
# 全局逻辑未删除值(默认为 0)
mybatis-plus.global-config.db-config.logic-not-delete-value=0
4.测试
/**
* 测试逻辑删除
*/
@Test
void testDelete() {
//根据ID删除
userMapper.deleteById("2");
}
---------------执行结果---------------------
==> Preparing: UPDATE user SET start=1 WHERE id=? AND start=0
==> Parameters: 2(String)
<== Updates: 1
条件查询
/**
* 测试条件查询
*/
@Test
void testSelect() {
/**
* 查询ID为1的用户
*/
User user = userMapper.selectById(1);
System.out.println(user);
/**
* 查询ID为0,或ID为1,或ID为3的用户
*/
List<User> users = userMapper.selectBatchIds(Arrays.asList(0, 1, 3));
users.forEach(System.out::println);
/**
* 使用map封装条件查询
*/
Map<String,Object> queryMap=new HashMap<>();
queryMap.put("name","第二");
List<User> byMap = userMapper.selectByMap(queryMap);
byMap.forEach(System.out::println);
}
条件构造器查询
1.条件查询
/**
* 通过条件构造器查询
*/
@Test
void testWrapper() {
QueryWrapper<User> queryWrapper=new QueryWrapper<>();
queryWrapper
.ge("age",18)
.isNotNull("name")
.isNull("email")
.likeLeft("name","1");
userMapper.selectList(queryWrapper);
}
------------------执行SQL------------------
SELECT
id,
NAME,
age,
email,
create_time,
version,
START
FROM
USER
WHERE
START = 0
AND ( age >= 18
AND NAME IS NOT NULL
AND email IS NULL
AND NAME LIKE '%1'
)
2.子查询
@Test
void testWrapper() {
QueryWrapper<User> queryWrapper=new QueryWrapper<>();
queryWrapper.inSql("id","select ID from user where age>3");
userMapper.selectList(queryWrapper);
}
---------------------执行SQL-----------------------
SELECT
id,
NAME,
age,
email,
create_time,
version,
START
FROM
USER
WHERE
START = 0
AND (
id IN ( SELECT ID FROM USER WHERE age > 3 ))
此处仅作实例,具体请参见官网
分页查询
1.注入分页拦截器
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@EnableTransactionManagement //自动管理事务
@Configuration
public class MybatisPlusConfig {
/**
* 注入插件
*
* @return
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
//注入乐观锁插件
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
//注入分页拦截器
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
return interceptor;
}
}
2.测试
/**
* 测试分页查询
*/
@Test
void testPage() {
//创建分页对象,当前页码数为 1 ,每页展示 5 条数据
Page<User> page=new Page<>(1,5);
//不查询count
page.setSearchCount(false);
//查询结果
userMapper.selectPage(page,null);
//获取返回结果
page.getRecords().forEach(System.out::println);
//可分页页数
System.out.println(page.getPages());
//当前页码数
System.out.println(page.getCurrent());
//总记录条数
System.out.println(page.getTotal());
}
自定义SQl分页查询
- 编写mapper
<select id="selectUserList" resultType="User">
SELECT
id,
NAME,
age,
email,
create_time,
version,
START
FROM
USER
where
<if test="params.age !=null">
AND age=#{params.age}
</if>
</select>
- Mapper接口
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cn.test_plus.bean.User;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
@Repository
public interface UserMapper {
/**
* 查询用户列表
* @param page
* @return
*/
IPage<User> selectUserList(@Param("page") Page<User> page, @Param("params") Map<String, Object> params);
}
- controller查询
@Autowired
private UserMapper userMapper;
@PostMapping(value = "/queryList")
public Page<User> queryUserList(@RequestBody Map<String, Object> pamram) {
Integer page =(Integer)pamram.get("pageIndex");
Integer size =(Integer)pamram.get("size");
if (page != null && size != null) {
//创建分页对象,当前页码数为 1 ,每页展示 10 条数据
Page<AnswerRecord> result = new Page<>(page, size);
//查询count
result.setSearchCount(true);
//查询用户列表
userMapper.selectUserList(result, pamram);
return result;
}
return null;
}
条件删除
/**
* 测试条件删除
*/
@Test
void testDelete() {
//根据ID删除
userMapper.deleteById("0");
//根据map条件删除
HashMap<String, Object> map = new HashMap<>();
map.put("name","zhangsna");
userMapper.deleteByMap(map);
//根据ID批量删除
userMapper.deleteBatchIds(Arrays.asList(1,2,3));
}
代码自动生成器
依赖:
<!--mybatisPlus代码自动生成器-->
<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.0</version>
</dependency>
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.po.TableFill;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import java.util.ArrayList;
import java.util.List;
/**
* 代码自动生成配置类
*/
public class CodeGenerator {
public static void main(String[] args) {
//创建代码生成器对象
AutoGenerator mpg=new AutoGenerator();
//1. 全局配置
GlobalConfig gc=new GlobalConfig();
//获取当前项目路径
String projectPath = System.getProperty("user.dir");
//设置文件生成路径
gc.setOutputDir(projectPath+"/src/main/java");
//设置作者
gc.setAuthor("wf");
//是否打开资源管理器,(就是打开文件夹)
gc.setOpen(false);
//是否覆盖当前文件
gc.setFileOverride(false);
//Service接口名称
gc.setServiceName("Service");
//设置表的主键生成策略为uuid
gc.setIdType(IdType.ASSIGN_UUID);
//设置日期类型
gc.setDateType(DateType.ONLY_DATE);
//是否配置swagger
gc.setSwagger2(true);
//注入全局配置
mpg.setGlobalConfig(gc);
//2.配置数据源
DataSourceConfig dsc=new DataSourceConfig();
dsc.setUrl("jdbc:mysql://127.0.0.1:3306/mybatis-plus-demo?characterEncoding=utf8&autoReconnect=true&failOverReadOnly=false&maxReconnects=10&interactiveClient=true&allowMultiQueries=true");
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("root");
//设置连接的数据库类型
dsc.setDbType(DbType.MYSQL);
//注入数据源
mpg.setDataSource(dsc);
//3.配置包
PackageConfig pc=new PackageConfig();
//设置模块包名称
pc.setModuleName("project");
//设置包名
pc.setParent("com.wf");
//设置实体类包名称
pc.setEntity("bean");
//设置mapper包名称
pc.setMapper("mapper");
//设置service包名称
pc.setService("service");
//设置controller包名称
pc.setController("controller");
//注入包的配置
mpg.setPackageInfo(pc);
// 4.策略配置
StrategyConfig strategy = new StrategyConfig();
//映射的表,即,即要生成那个表,支持多个参数
strategy.setInclude("user");
//包名使用下划线转驼峰命名
strategy.setNaming(NamingStrategy.underline_to_camel);
//列名使用下划线转驼峰命名
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
//是否使用lombock
strategy.setEntityLombokModel(true);
//设置逻辑删除字段名称
strategy.setLogicDeleteFieldName("start");
//字段配置自动填充策略
TableFill tb=new TableFill("create_time", FieldFill.INSERT);
List<TableFill> fillList=new ArrayList<>();
fillList.add(tb);
strategy.setTableFillList(fillList);
//设置乐观锁字段名称
strategy.setVersionFieldName("version");
//controller是否可以使用resultful风格
strategy.setRestControllerStyle(true);
//注入策略配置
mpg.setStrategy(strategy);
//执行
mpg.execute();
}
}
生成结果