目录
1、Mapper接口继承BaseMapper,T对应的是mapper对应的实体类
2、Service接口继承Iservice,T对应的是service对应的实体类
一、常用方法
1、Mapper接口继承BaseMapper<T>,T对应的是mapper对应的实体类
例:
UserMapper extends BaseMapper<User>{
}
insert(实体类) *新增功能
deleteById(id) *通过Id来删除数据
deleteByMap(删除条件) *根据map集合中所设置的条件删除,将删除条件放到Map集合中
deleteBatchIds(list集合) *根据id批量删除,将要批量删除的ID放到list集合中
updateById(实体类) *修改信息,将要修改的信息放到一个对应实体类中
selectById(id) *通过id查询信息
selectBatchIds(list集合) *根据多个id查询,将要查询的ID放到list集合中
selectByMap(map集合) *根据map集合中的条件查询用户信息
selectList(条件) *通过条件构造器查询一个list集合,若没有条件,则可以设置null为参数
2、Service接口继承Iservice<T>,T对应的是service对应的实体类
例:
public interface UserService extends IService<User>{
}
ServiceImpl实现类继承ServiceImpl<Mapper,T>实现自己的Service接口,泛型是<对应的Mapper接口,对应的实体类>
例:
public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements UserService{
}
count() *查询总记录数
saveBatch(list集合) *批量添加,list集合里放一个个实体【List<T> list=new ArrayList<>() (T表示对应的实体类)】
二、常用注解
@TableName(数据库表名) *设置实体类所对应的表名,添加在在实体类上面
Mybatis-plus全局配置
mybatis-plus:
#设置mybatis-plus的全局配置
global-config:
db-config:
#设置实体类所对应的表的统一前缀,如t_XXX
table-prefix:t_
@TableId *放在属性上面,表示将当前属性所对应的字段指定为主键 value属性:用于指定主键的字段(数据库中定为主键的字段名),只有value属性时,可以省略value
type属性:用于设置主键生成策略,默认是雪花算法
mybatis-plus:
#设置mybatis-plus的全局配置
global-config:
db-config:
#设置实体类所对应的表的统一前缀,如t_XXX
table-prefix: t_
#设置统一的主键生成策略
id-type: auto
@TableField *指定属性所对应的字段名
@TableLogic *逻辑删除,可以进行数据恢复,放在属性上面,加上之后删除自动改为修改。
三、条件构造器和常用接口
1、wrapper介绍
Wrapper:条件构造抽象类,最顶端父类
AbstractWrapper:用于查询条件封装,生成sql的where条件
QueryWrapper:查询条件封装
UpdateWrapper:Update条件封装
AbstractLambdaWrapper:使用Lambda语法
LambdaQueryWrapper:用于Lambda语法使用的查询Wrapper
LambdaUpdateWrapper:Lambda更新封装Wrapper
2、queryWrapper
//查询用户名包含a,年龄在20到30之间,邮箱信息不为null的用户信息
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.like("user_name","a")
.between("age",20,30)
.isNotNull("email");
List<User> list = userMapper.selectList(queryWrapper);
//查询用户信息,按照年龄的降序排序,若年龄相同,则按照id升序排序
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByDesc("age")
.orderByAsc("uid")
List<User> list = userMapper.selectList(querywrapper);
//删除邮箱地址为null的用户信息
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.isNull("email");
int result = userMapper.delete(queryWrapper);
条件的优先级:(Lambda表达式中的条件优先执行)
//将(年龄大于20并且用户名中包含有a)或邮箱为null的用户信息修改
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.gt("age",20)
.like("user_name","a")
.or()
.iaNull("email");
User user = new User();
user.setName("小明");
usser.setEmail("[email protected]");
int result = userMapper.update(user,queryWrapper);
//将用户名中包含有a并且(年龄大于20或邮箱为null)的用户信息修改
//Lambda中的条件优先执行
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.like("user_name","a")
.and(i->i.gt("age",20).or().isNull("email"));
User user = new User();
user.setName("小红");
usser.setEmail("[email protected]");
int result = userMapper.update(user,queryWrapper);
//查询用户的用户名、年龄、邮箱信息
QuerryWrapper<User> queryWrapper = new QuerryWrapper<>();
queryWrapper.select("user_name","age","email");
List<Map<String,Object>> maps = userMapper.selectMaps(queryWrapper);
子查询:
//查询id小于等于100的用户信息
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.inSql("uid","select uid from t_user where uid<=100");
List<User> list = userMapper.selectList(queryWrapper);
3、updateWrapper
//将用户名中包含有a并且(年龄大于20或邮箱为null)的用户信息修改
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
uodateWrapper.like("user_name","a")
.and(i->i.gt("age",20).or().isNull("email"));
updateWrapper.set("user_name","小黑").set("email","[email protected]");
int result = userMapper.update(null,updateWrapper);
4、模拟开发中组装条件的情况
String username = "";
Integer ageBegin = 20;
Integer ageEnd = 30;
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
if(StringUtils.isNotBlabk(username)){
//isNotBlank判断某个字符串是否不为空字符串,不为null,不为空白符
queryWrapper.like("user_name",username);
}
if(ageBegin != null){
queryWrapper.ge("age",ageBegin);
}
if(ageEnd != null){
queryWrapper.le("age",ageEnd);
}
List<User> list = userMapper.selectList(queryWrapper);
5、使用condition组装条件
String username = "a";
Integer ageBegin = null;
Integer ageEnd = 30;
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.like(StringUtils.isNotBlank(username),"user_name",username)
.ge(ageBegin != null,"age",ageBegin)
.le(ageEnd != null,"age",ageEnd);
List<User> list = userMapper.selectList(queryWrapper);
6、LambdaQueryWrapper
String username = "a";
Integer ageBegin = null;
Integer ageEnd = 30;
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.like(StringUtils.isNotBlank(username),User::getName,username)
.ge(ageBegin != null,User::getAge,ageBegin)
.le(ageEnd != null,User::getAge,ageEnd);
List<User> list = userMapper.selectList(queryWrapper);
7、LambdaUpdateWrapper
//将用户名中包含有a并且(年龄大于20或邮箱为null)的用户信息修改
LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
uodateWrapper.like(User::getName,"a")
.and(i->i.gt(User::getAge,20).or().isNull(User::getEmail));
updateWrapper.set(User::getName,"小黑").set(User::getEmail,"[email protected]");
int result = userMapper.update(null,updateWrapper);
四、插件
1、分页插件
1.1、配置类
@Configuration
@MapperScan("com.example.mybatisPlus.mapper")
public class MybatisPlusConfig{
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor interceeptor = new MybatisPlusInterceptor();
//添加分页插件
interceptor.addInnerInterceptor(new PageinationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
1.2、分页查询
Page<User> page = new Page<>(1,3);
userMapper.selectPage(page,null);
2、乐观锁插件
加乐观锁之前:
//小李取数据
Product p1 = productMapper.selectById(1L);
//小王取数据
Product p2 = productMapper.selectById(1L);
//小李修改 +50
p1.setPrice(p1.getPrice() + 50);
int result1 = productMapper.updateById(p1);
sout("小李修改结果:" + p1.getPrice);
//小王修改 -30
p2.setPrice(p2.getPrice() - 30);
int result2 = productMapper.updateById(p2);
sout("小王修改结果:" + p2.getPrice);
//老板看价格
Product p3 = productMapper.selectById(1L);
sout("老板看价格:" + p3.getPrice);
运行结果:
小李修改结果:150
小王修改结果:70
老板看价格:70
@Configuration
@MapperScan("com.example.mybatisPlus.mapper")
public class MybatisPlusConfig{
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor interceeptor = new MybatisPlusInterceptor();
//添加分页插件
interceptor.addInnerInterceptor(new PageinationInnerInterceptor(DbType.MYSQL));
//添加乐观锁插件
interceptor.addInnerInterceptor(new OptimistickLockerInnerInterceptor());
return interceptor;
}
}
在实体类中添加属性version并加上@Version
加乐观锁之后:
//小李取数据
Product p1 = productMapper.selectById(1L);
//小王取数据
Product p2 = productMapper.selectById(1L);
//小李修改 +50
p1.setPrice(p1.getPrice() + 50);
int result1 = productMapper.updateById(p1);
sout("小李修改结果:" + p1.getPrice);
//小王修改 -30
p2.setPrice(p2.getPrice() - 30);
int result2 = productMapper.updateById(p2);
if(result2 == 0){
//失败重试,重新获取Version并更新
p2 = productMapper.selectById(1L);
p2.setPrice(p2.getPrice() - 30);
result2 = productMapper.updateById(p2);
}
sout("小王修改结果:" + p2.getPrice);
//老板看价格
Product p3 = productMapper.selectById(1L);
sout("老板看价格:" + p3.getPrice);
运行结果:
小李修改结果:150
小王修改结果:120
老板看价格:120
五、通用枚举
例如性别:
@Getter
public enum SexEnum{
MALE(1,"男");
FEMALE(2,"女");
@EnumValue //将注解所标识的属性的值存储到数据库中
private Integer sex;
private String sexName;
SexEnum(Integer sex, String sexName){
this.sex = sex;
this.sexName = sexName;
}
}
mybatis-plus:
#设置mybatis-plus的全局配置
global-config:
db-config:
#设置实体类所对应的表的统一前缀,如t_XXX
table-prefix: t_
#设置统一的主键生成策略
id-type: auto
#扫描通用枚举的包
type-enums-package: com.example.mybatisplus.enums
User user = new User();
user.setName("admin");
user.setAge(33);
user.setSex(SexEnum.MALE);
int result = userMapper.insert(user);
六、代码生成器
1、引入依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>最新版本</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>最新版本</version>
</dependency>
2、快速生成
FastAutoGenerator.create("url", "username", "password")
.globalConfig(builder -> {
builder.author("baomidou") // 设置作者
.enableSwagger() // 开启 swagger 模式
.fileOverride() // 覆盖已生成文件
.outputDir("D://"); // 指定输出目录
})
.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();
七、多数据源
适用于多种场景:纯粹多库、读写分离、一主多从、混合模式等
1、引入依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.5.0</version>
</dependency>
2、配置多数据源
datasource:
dynamic:
#设置默认的数据源或者数据源组,默认值即为master
primary: master
#严格匹配数据源,默认false,true未匹配到指定数据源时抛异常,false使用默认数据源
strict: false
datasource:
master:
url: jdbc:mysql://localhost:3306/mybatis_plus?characterEncoding=utf-8&useSSL=false
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: ******
slave_1:
url: jdbc:mysql://localhost:3306/mybatis_plus_1?characterEncoding=utf-8&useSSL=false
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: ******
在Service实现类上面添加注解,指定操作的数据源【@DS也可以加到方法上,读写分离】
@DS("master") //指定所操作的数据源
public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements UserService{
}