Java:MybatisPlus--高级
一、分页
1、分页插件
分页的本质就是需要设置一个拦截器,通过拦截器拦截了 SQL,通过在 SQL 语句的结尾添加 limit 关键字,来实现分页的效果。
2、通过配置类来指定一个具体数据库的分页插件
@Configuration
public class MybatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return interceptor;}
}
3、分页查询的实现
@Test
void selectPage(){//1.创建 QueryWrapper 对象LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();//2.创建分页查询对象,指定当前页和每页显示条数IPage<User> page = new Page<>(1,2;//3.执行分页查询userMapper.selectPage(page, lambdaQueryWrapper);//4.查看分页查询的结果System.out.println("当前页码值:"+page.getCurrent());System.out.println("每页显示数:"+page.getSize());System.out.println("总页数:"+page.getPages());System.out.println("总条数:"+page.getTotal());System.out.println("当前页数据:"+page.getRecords());
}
二、自定义分页
1、在 UserMapper.xml 映射配置文件中提供查询语句
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.islunatic.mapper.UserMapper"><select id="selectByName" resultType="com.islunatic.pojo.User">select * from user where name = #{name}</select>
</mapper>
2、在 Mapper 接口中提供对应的方法,方法中将 IPage 对象作为参数传入
@Mapper
public interface UserMapper extends BaseMapper<User> {IPage<User> selectByName(IPage<User> page, String name);
}
三、ActiveRecord 模式
AR是一种领域模型模式,
特点:
是一个模型类对应关系型数据库中的一个表,而模型类的一个实例对应表中的一行记录。
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User extends Model<User> {private Long id;private String name;private Integer age;private String email;
}
Model 类中提供了一些增删改查方法,可以直接使用实体类对象调用这增删改查方法,简化了操作的语法,但是底层是需要UserMapper的,所以持久层接口不能省略。
具体使用方式
增
@Test
void activeRecordAdd(){User user = new User();user.setName("wang");user.setAge(35);user.setEmail("123456789@qq.com");user.insert();
}
删
@Test
void activeRecordDelete(){User user = new User();user.setId(8L);user.deleteById();
}
改
@Test
void activeRecordUpdate(){User user = new User();user.setId(6L);user.setAge(50);user.updateById();
}
查
@Test
void activeRecordSelect(){User user = new User();user.setId(1L);User user1= user.selectById();System.out.println(user1);
}
四、SimpleQuery
SimpleQuery可以对selectList查询后的结果用 Stream流进行了一些封装,可以返回一些指定果
1、list
@Test
void testList1(){List<Long> ids = SimpleQuery.list(newLambdaQueryWrapper<User>().eq(User::getName, "Mary"), User::getId);System.out.println(ids);
}
②对于封装后的字段进行 lambda 操作
@Test
void testList2(){List<String> names = SimpleQuery.list(newLambdaQueryWrapper<User>().eq(User::getName, "Mary"),User::getName,e ->Optional.of(e.getName()).map(String::toLowerCase).ifPresent(e::setName));System.out.println(names);
}
2、map
@Test
void testMap(){//将所有元素封装为 Map 形式Map<Long, User> Map1 = SimpleQuery.keyMap(new LambdaQueryWrapper<>(), User::getId);System.out.println(Map1 );
}
3、group
分组效果
@Test
void testGroup(){Map<String, List<User>> maps = SimpleQuery.group(newLambdaQueryWrapper<>(), User::getName);System.out.println(maps );
}
五、锁
常见的数据库锁类型有两种,悲观锁和乐观锁。
一次完成的修改操作是,先查询数据,然后修改数据。
1、悲观锁
悲观锁是在查询的时候就锁定数据,在这次请求未完成之前,不会释放锁。等到 这次请求完毕以后,再释放锁,释放了锁以后,其他请求才可以对于这条数据完成读写。
这样做的操作能够保证读取到的信息就是当前的信息,保证了信息的正确性,但是并发效率很低,在实际开发中使用悲观锁的场景很少,因为在并发时我们是要保证效率。
2、乐观锁
乐观锁是通过表字段完成设计的,他的核心思想是在读取的时候不加锁,其他请求依然可以读取到这个数据,在修改的时候判断一个数据是否有被修改过,如果有被修改过, 那本次请求的修改操作失效。
Update 表 set 字段 = 新值,version = version + 1 where version = 1
这样做的操作是不会对于数据读取产生影响,并发的效率较高。但是可能目前看到的数据并不是真实信息数据,是被修改之前的,但是在很多场景下是可以容忍的,并不是产生很大影响,例如很多时候我们看到的是有库存,或者都加入到购物车了,但是点进去以后库存没有了。
在实体类字段上,添加对应的属性,并使用@Version 标注为这是一个乐观锁字段信息。
通过配置拦截器,对每条修改语句完成语句的增强,让每条修改的sql语句在执行的时候,都加版本控制的功能。
@Configuration
public class MybatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor(){MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());return interceptor;
}
}
六、代码生成器
1、导入依赖
<!--代码生成器依赖-->
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId><version>3.5.3</version>
</dependency>
<!--freemarker 模板依赖-->
<dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.31</version>
</dependency>
2、编写代码生成器
@SpringBootTest
public class GeneratorApplicationTests {public static void main(String[] args) {FastAutoGenerator.create("jdbc:mysql://localhost:3306/mp?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false", "root", "root")
.globalConfig(builder -> {builder.author("phb") // 设置作者//.enableSwagger() // 开启 swagger 模式.fileOverride() // 覆盖已生成文件.outputDir("D://"); // 指定输出目录}).packageConfig(builder -> {builder.parent("com.islunatic") // 设置父包名.moduleName("mp") // 设置父包模块名//设置 mapperXml 生成路径.pathInfo(Collections.singletonMap(OutputFile.xml, "D://")); }).strategyConfig(builder -> {builder.addInclude("user") // 设置需要生成的表名.addTablePrefix(""); // 设置过滤表前缀}).templateEngine(new FreemarkerTemplateEngine()) // 使用 Freemarker 引擎模板,
默认的是 Velocity 引擎模板.execute();}
}
七、配置多数据源
1、导入依赖
<dependency><groupId>com.baomidou</groupId><artifactId>dynamic-datasource-spring-boot-starter</artifactId><version>3.1.0</version>
</dependency>
2、编写数据源信息
spring:datasource:dynamic:primary: masterstrict: falsedatasource:master:username: rootpassword: rooturl:jdbc:mysql://localhost:3306/mp?serverTimezone=UTCdriver-class-name: com.mysql.cj.jdbc.Driverslave_1:username: rootpassword: rooturl:jdbc:mysql://localhost:3306/mp2?serverTimezone=UTCdriver-class-name: com.mysql.cj.jdbc.Driver