使用第三方组件一般步骤
导入对应依赖
研究依赖如何配置
代码如何编写
提高技术扩展能力
对于MyBatis-Plus的学习我们也将按照上面4步进行学习
常见网站
MVN仓库
MyBatisPlus官网
1.添加依赖
父工程的Spring Boot Starter
版本2.5+
添加依赖
spring-boot-starter
spring-boot-starter-test
这两个如果创建了springboot项目则大概率存在,注意检查是否已经存在
mybatis-plus-boot-starter
:mybatis plus
MySQL Connector/J
:数据库驱动
Project Lombok
:简化java代码,@Data
,@NoArgsConstructor
,@AllArgsConstructor
,生成常见方法
mybatis-plus-generator
:代码生成器,
Spring Boot Starter JDBC
2.安装插件lombok
这是为了让IDEA正确处理Lombok注解
3.配置
首先我们需要了解到,在Springboot项目中,使用.properties
和.yml
配置是等效的,均可以正常识别并使用.
在这里我们使用.properties
配置
spring.datasource.username=root
spring.datasource.password=232156
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
mybatis_plus ?
:对应使用的数据库的名称
serverTimezone=Asia/Shanghai
:配置时区
useUnicode=true&characterEncoding=utf-8
:字符编码解码格式
MySql5之前的
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
4.编写代码
pojo-mapper-service-controller
主要设计两个包的代码编写
pojo:存放实体类,
//注解就是利用lombok来自动生成一些方法 @Data @NoArgsConstructor @AllArgsConstructor public class User { private Integer id; private String name; private Integer age; private String email; }
mapper:存放对应使用的接口,在这一步,所有的CURD就已经全部实现完了
//必须继承BaseMapper类
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
在主程序入口添加@MapperScan
,来快速扫描mapper
//括号中填写具体的mapper文件夹路径
@MapperScan("com.baomidou.mybatisplus.samples.quickstart.mapper")
测试
@SpringBootTest
class MyBatisPlusApplicationTests {
//所有方法都来自父类
//也可以编写自己的文件
@Autowired
private UserMapper userMapper;
@Test
void contextLoads() {
//参数是wapper
List<User> users=userMapper.selectList(null);
System.out.println(users);
}
}
问题思考
- 谁帮我们编写的SQL:MyBatisPlus
- 方法哪里来?MyBatis_Plus写好了
我们所有sql是不可见的,我们希望知道他是怎么执行的,所以必须要看日志
#配置日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
主键生成策略
自增id:实体类配置(对应数据库中的也需要对应的设置)
@TabledId(type=IdType.AUTO)
NONE:未设置主键
INPUT:手动输入,需要我们手动输入
ID_WORKER:默认全局唯一ID
UUID:全局唯一id uuid
ID_WORKER_STR:ID_WORKER字符串表示法
UUID
Redis生成ID
雪花算法
雪花算法(多用于分布式):snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。
其核心思想是使用41bit作为毫秒数,10bit作为机器ID(5bit数据中心,5bit机器ID),12bit作为毫秒的流水号(每个节点每毫秒产生4096个id),最后一个符号位永远为0.可以保证全球唯一
@Test
public void testUpdate(){
User user=new User();
user.setId(1);
user.setName("曹操");
//参数实际是一个对象
int i=userMapper.updateById(user);
System.out.println(i);
}
代码级别
不设置默认值
实体类字段上增加注解
@TableField(fill = FieldFill.INSERT)//插入执行,更新不执行
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)//插入更新都执行
private Date updateTime;
编写处理器处理该注解(放在hadler包中)
@Slf4j//日志
@Component//丢到springboot里 一定不要忘记把处理器加到Ioc容器中!
public class MyMetaObjectHandler extends MetaObjectHandler {//extends??
@Override//插入时的填充策略
public void insertFill(MetaObject metaObject) {
log.info("==start insert ······==");
//setFieldValByName(java.lang.String fieldName, java.lang.Object fieldVal, org.apache.ibatis.reflection.MetaObject metaObject)
this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
}
@Override//更新时的填充策略
public void updateFill(MetaObject metaObject) {
log.info("==start update ······==");
this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
}
}
测试即可
乐观锁的实现
- 取出记录时,获取当前version
- 更新时,带上这个version
- 执行更新,
set version=newVersion where version=oldVersion
- 如果version不对则更新失败
给数据库增加version字段
实体类增加对应字段即注解
@Version//乐观锁version注解
private Integer version;
注册组件:新建文件config.MyBatisPlusConfig
文件
@MapperScan("com.upupstudy.mybatis_plus.mapper")//在主程序入口就可以删除对应的扫描了
@EnableTransactionManagement//事务管理
@Configuration//代表这是配置类
public class MyBatisPlusConfig {
//注册乐观锁插件
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {//拦截器
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());//乐观锁插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));//分页插件
return interceptor;
}
}
测试
新增一个deleted
字段
实体类添加对应属性
@TableLogic//逻辑删除注解
private Integer deleted;
配置
#配置逻辑删除 没删除的为0 删除的为1
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0
测试
userMapper.deleteById(1)//看似删除,其实执行的时更新操作
单个查询
@Test//通过id查询单个用户
public void testSelectById(){
User user = userMapper.selectById(1);
System.out.println(user);
}
批量查询
@Test//通过id查询多个用户
public void testSelectBatchIds(){
List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
users.forEach(System.out::println);
//System.out.println(users);
}
条件查询
@Test//通过条件查询之一 map
public void testMap(){
HashMap<String, Object> map = new HashMap<>();
//自定义要查询的条件
map.put("name","张飞");
map.put("age",18);
List<User> users = userMapper.selectByMap(map);
users.forEach(System.out::println);
}
常见的分页方法
设置拦截器组件
@MapperScan("com.upupstudy.mybatis_plus.mapper")
@EnableTransactionManagement//事务管理
@Configuration//代表这是配置类
public class MyBatisPlusConfig {
//注册乐观锁插件
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {//拦截器
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());//乐观锁插件
//************新增分页插件***************
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));//分页插件
return interceptor;
}
}
直接使用page对象分页查询
/*
*与前端连用,只需要从前端向后传输一个current参数即可
*
*/
@Test//测试分页查询
public void testPage(){
//参数一current:当前页 参数二size:页面大小
//使用了分页插件之后,所有的分页操作都变得简单了
Page<User> page = new Page<>(2,5);
userMapper.selectPage(page,null);
page.getRecords().forEach(System.out::println);
System.out.println("总页数==>"+page.getTotal());
}
@Test
public void testWrapper1() {
//参数是一个wrapper ,条件构造器,和刚才的map对比学习!
//查询name不为空,email不为空,age大于18的用户
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper
.isNotNull("name")
.isNotNull("email")
.ge("age",18);//年龄大于18
List<User> userList = userMapper.selectList(wrapper);
userList.forEach(System.out::println);
可以快速生成Entity,Mapper,Mapper XML,Service,Controller等各个模块的代码,极大的提高了开发效率
1.导入依赖
mybatis-plus-generator
Freemarker
2.代码编写:建议放在测试文件夹中
交互生成
FastAutoGenerator.create(DATA_SOURCE_CONFIG)
// 全局配置
.globalConfig((scanner, builder) -> builder.author(scanner.apply("请输入作者名称?")).fileOverride())
// 包配置
.packageConfig((scanner, builder) -> builder.parent(scanner.apply("请输入包名?")))
// 策略配置
.strategyConfig((scanner, builder) -> builder.addInclude(getTables(scanner.apply("请输入表名,多个英文逗号分隔?所有输入 all")))
.controllerBuilder().enableRestStyle().enableHyphenStyle()
.entityBuilder().enableLombok().addTableFills(
new Column("create_time", FieldFill.INSERT)
).build())
/*
模板引擎配置,默认 Velocity 可选模板引擎 Beetl 或 Freemarker
.templateEngine(new BeetlTemplateEngine())
.templateEngine(new FreemarkerTemplateEngine())
*/
.execute();
// 处理 all 情况
protected static List<String> getTables(String tables) {
return "all".equals(tables) ? Collections.emptyList() : Arrays.asList(tables.split(","));
}
快速生成
FastAutoGenerator.create("url", "username", "password")//对应到.properites中的sql配置
.globalConfig(builder -> {
builder.author("baomidou") // 设置作者
//建议注释
.enableSwagger() // 开启 swagger 模式,0
//建议注释
.fileOverride() // 覆盖已生成文件,建议注释
.outputDir("D://"); // java一级目录下,绝对路径
})
.dataSourceConfig(builder -> builder.typeConvertHandler((globalConfig, typeRegistry, metaInfo) -> {
int typeCode = metaInfo.getJdbcType().TYPE_CODE;
if (typeCode == Types.SMALLINT) {
// 自定义类型转换
return DbColumnType.INTEGER;
}
return typeRegistry.getColumnType(metaInfo);
}))
.packageConfig(builder -> {
builder.parent("com.baomidou.mybatisplus.samples.generator") // 填写到与主程序同一级目录
.moduleName("system") // 设置父包模块名,为这个文件夹命名
.pathInfo(Collections.singletonMap(OutputFile.xml, "D://")); // 设置mapperXml生成路径
})
.strategyConfig(builder -> {
builder.addInclude("t_simple") // 设置需要生成的表名
.addTablePrefix("t_", "c_"); // 设置过滤表前缀
})
.templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
.execute();
配置方法
详细解释