MyBaitsPlus快速入门
Posted 大忽悠爱忽悠
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MyBaitsPlus快速入门相关的知识,希望对你有一定的参考价值。
MyBaitsPlus
导入依赖
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--mybaits-plus第三方提供的启动器-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3.1</version>
</dependency>
导入上面这个增强版依赖之后,下面两个依赖无需再次导入:
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
主配置文件中的数据源相关配置
spring:
datasource: #是否使用安全连接
#mysal 8驱动不同com.mysql.cj.jdbc.Driver,还需要增加时区的配置 serverTimezone=GMT%2B8
url: jdbc:mysql://localhost:3306/tx?userSSL=false&useUnicode=true&characterEncoding=utf-8
username: root
password: 126433
driver-class-name: com.mysql.jdbc.Driver
UserMapper接口
//继承BaseMapper基本类,接口里面已经写了很多的crud方法
@Mapper
public interface UserMapper extends BaseMapper<User>
{}
测试
@SpringBootTest
class SpringBootDaoApplicationTests
{
//继承了BaseMapper,所有的方法都来自于父类,我们页可以编写自己的扩展方法
@Autowired
UserMapper userMapper;
@Test
void contextLoads()
{
//参数是一个Wrapper,条件构造器,这里我们先不使用 null
//查询全部用户
List<User> users = userMapper.selectList(null);
users.forEach(System.out::println);
}
}
@Mapper注解和@MapperScan注解
1、@Mapper注解:
作用:在接口类上添加了@Mapper,在编译之后会生成相应的接口实现类
添加位置:接口类上面
@Mapper
public interface UserDAO {
//代码
}
如果想要每个接口都要变成实现类,那么需要在每个接口类上加上@Mapper注解,比较麻烦,解决这个问题用@MapperScan
2、@MapperScan
作用:指定要变成实现类的接口所在的包,然后包下面的所有接口在编译之后都会生成相应的实现类
添加位置:是在Springboot启动类上面添加,
@SpringBootApplication
@MapperScan("com.winter.dao")
public class SpringbootMybatisDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootMybatisDemoApplication.class, args);
}
}
添加@MapperScan(“com.winter.dao”)注解以后,com.winter.dao包下面的接口类,在编译之后都会生成相应的实现类
配置日志
#开启日志功能
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #控制台输出
@TableId注解
这个注解表示表的主键
@NoArgsConstructor
@AllArgsConstructor
@Data
public class User
{
String name;
Integer age;
@TableId(value="id",type = IdType.AUTO)
Integer id;
}
接受两个参数
value = 主键列名
type = 主键类型
可选类型:
使用@TableId注解时,类型为: type = IdType.AUTO 数据库也需要设置自增
否则会出 Cause: java.sql.SQLException: Field ‘id’ doesn’t have a default value
插入操作
//测试插入
@Test
public void testInsert(){
User user = new User();
user.setName("淮城一只猫");
user.setAge(5);
user.setEmail("2424496907@qq.com");
int result = userMapper.insert(user); //自动生成id
System.out.println(result); //受影响的行数
System.out.println(user); //发现id自动回填
}
主键生成策略
默认使用ID_WORKER,全局唯一id----雪花算法
雪花算法(默认使用):
snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0。可以保证几乎全球唯一!
主键自增
我们需要配置注解自增:
- 实体类字段上:@TableId(type = IdType.AUTUO)
- 数据库字段一定要自增
其余的策略解释
public enum IdType {
AUTO(0), //id自增
NONE(1), //未设置主键
INPUT(2), //手动输入,一旦手动输入后,就需要自己去写id,否则id为空
ID_WORKER(3), //默认值,全局唯一id
UUID(4), //全局唯一id,uuid
ID_WORKER_STR(5); //ID_WORKER的字符串表示法
}
更新操作
//测试更新
@Test
public void testUpdate(){
User user = new User();
user.setId(6L);
user.setName("我的博客叫:淮城一只猫");
user.setAge(6);
user.setEmail("2424496907@qq.com");
//注意:updateById参数是一个对象
int result = userMapper.updateById(user); //自动生成id
System.out.println(result); //受影响的行数
}
自动填充
创建时间、修改时间!这些操作一般自动化完成的,我们不希望手动更新!
阿里巴巴开发手册:所有的数据库表:gmt_create、gmt_modified几乎所有表都要配置上!而且需要自动化!
方式一:数据库级别(工作中不建议这么做)
1.在表中新增字段create_time、update_time
2. 再次测试插入方法,需要先把实体类同步!
private Date creteTime;
private Date updateTime;
mysql日期相关的知识点
mysql中的日期类型小结笔记
MySQL-datetime类型的列设置默认值为CURRENT_TIMESTAMP
MySQL中datetime字段的默认值CURRENT_TIMESTAMP
方式二:代码级别
1.删除数据库中的默认值、更新操作
2.在实体类字段属性上需要注释
//字段必须声明TableField注解,属性fill选择对应策略,该声明告知Mybatis-Plus需要预留注入SQL字段
// 注意!这里需要标记为填充字段
@TableField(fill = FieldFill.INSERT)
private Date creteTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
策略枚举如下:
public enum FieldFill {
/**
* 默认不处理
*/
DEFAULT,
/**
* 插入填充字段
*/
INSERT,
/**
* 更新填充字段
*/
UPDATE,
/**
* 插入和更新填充字段
*/
INSERT_UPDATE
}
3.自定义实现类 MyMetaObjectHandler(实现元对象处理器接口)
@Slf4j
@Component//填充处理器MyMetaObjectHandler在 Spring Boot 中需要声明@Component或@Bean注入
public class MyMetaObjectHandler implements MetaObjectHandler
{
//插入时填充策略
@Override
public void insertFill(MetaObject metaObject) {
log.info("start insert fill ....");
this.setFieldValByName("createTime",new Date(),metaObject);
this.setFieldValByName("updateTime",new Date(),metaObject);
}
//更新时填充策略
@Override
public void updateFill(MetaObject metaObject) {
log.info("start update fill ....");
this.setFieldValByName("updateTime",new Date(),metaObject);
}
}
4.测试
@SpringBootTest
class SpringBootDaoApplicationTests
{
//继承了BaseMapper,所有的方法都来自于父类,我们页可以编写自己的扩展方法
@Autowired
UserMapper userMapper;
@Test
void contextLoads()
{
User user=new User();
user.setAge(18);
user.setName("hhhh");
int ret = userMapper.insert(user);
System.out.println(user);
}
}
乐观锁
乐观锁:顾名思义乐观,它总是认为不会出现问题,无论干什么都不去上锁!如果出现问题,再次更新值测试
悲观锁:顾名思义悲观,它总是认为会出现问题,无论干什么都会加上锁!再去操作
乐观锁实现方式:
- 取出记录时,获取当前version
- 更新时,带上这个version
- 执行更新时, set version = newVersion where version = oldVersion
- 如果version不对,就更新失败
测试MP乐观锁插件
1.数据库中添加version字段,默认值为1
2.在实体类的字段上加上@Version注解
@Version //乐观锁注解
private Integer version;
说明:
- 支持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime
- 整数类型下 newVersion = oldVersion + 1
- newVersion 会回写到 entity 中
- 仅支持 updateById(id) 与 update(entity, wrapper) 方法
- 在 update(entity, wrapper) 方法下, wrapper 不能复用!!!
3.配置插件
@MapperScan("com.Mapper")
@EnableTransactionManagement //自动管理事务(默认也是开启的)
@Configuration //配置类
public class MybaitsPlusConfig {
//注册乐观锁插件
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return mybatisPlusInterceptor;
}
}
4.测试
@SpringBootTest
class SpringBootDaoApplicationTests
{
//继承了BaseMapper,所有的方法都来自于父类,我们页可以编写自己的扩展方法
@Autowired
UserMapper userMapper;
//测试乐观锁成功!
@Test
public void testOptimisticLocker1() {
//1.查询用户信息
User user = userMapper.selectById(276);
//2.修改用户信息
user.setName("aaa");
user.setAge(18);
//3.执行更新操作
userMapper.updateById(user);
}
//测试乐观锁失败!多线程下
@Test
public void testOptimisticLocker2() {
//线程1
User user1 = userMapper.selectById(276);
user1.setName("aaa");
//模拟另外一个线程执行插队操作
User user2 = userMapper.selectById(276);
user2.setName("bbb");
userMapper.updateById(user2);
//自旋锁多次操作尝试提交
userMapper.updateById(user1);
}
}
查询操作
@SpringBootTest
class SpringBootDaoApplicationTests
{
//继承了BaseMapper,所有的方法都来自于父类,我们页可以编写自己的扩展方法
@Autowired
UserMapper userMapper;
//测试查询
@Test
public void testSelectById() {
User user = userMapper.selectById(276);
System.out.println("===========================");
System.out.println(user);
}
//测试批量查询
@Test
public void testSelectByBatchId()
{
List<User> users = userMapper.selectBatchIds(Arrays.asList(270, 271, 272));
System.out.println("===========================");
users.forEach(System.out::println);
}
//条件查询之一 使用map操作
@Test
public void testSelectBatchIds() {
HashMap<String, Object> map = new HashMap<>();
//自定义查询,同时满足map集合中的所有条件
map.put("name","bbb");
map.put("age","18");
List<User> users = userMapper.selectByMap(map);
System.out.println("===========================");
users.forEach(System.out::println);
}
}
分页查询
分页在网站中使用非常多!
- 原始limit进行分页
- pageHelper第三方插件
- MP其实也内置了分页插件
1.配置分页插件
//Spring boot方式
@Configuration
@MapperScan("com.baomidou.cloud.service.*.mapper*")
public class MybatisPlusConfig {
// 旧版
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
// 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求 默认false
// paginationInterceptor.setOverflow(false);
// 设置最大单页限制数量,默认 500 条,-1 不受限制
// paginationInterceptor.setLimit(500);
// 开启 count 的 join 优化,只针对部分 left join
paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
return paginationInterceptor;
}
// 最新版
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
return interceptor;
}
}
- setMaxLimit: 设置最大分页数
- setOverflow:是否对超过最大分页时做溢出处理,默认false不处理,即直接丢弃溢出的数据,为true时,怎么把溢出数据放入到下一个分页中。
- setDbType:设置数据库类型以匹配不同方言
- setDialect: 设置分页方言
- setOptimizeJoin:优化Join分页语句,默认true
2.直接使用Page对象即可
//测试分页查询
@Test
public void testPage() {
//参数一:当前页
//参数二:页面大小
//使用了分页插件之后,所有的分页操作页变得简单了
Page<User> page = new Page<>(1,5);
//第二个参数是查询条件
userMapper.selectPage(page,null);
page.getRecords().forEach(System.out::println);
System.以上是关于MyBaitsPlus快速入门的主要内容,如果未能解决你的问题,请参考以下文章
SpringBoot+Maven+MyBaitsPlus+MySQL+Redis——配置开启Redis的基本使用
SpringBoot+Maven+MyBaitsPlus+MySQL+Redis——配置开启Redis的基本使用