所有基本的crud都在BaseMapper接口中定义,用户只需要继承该接口即可实现基本的crud操作
@Repository
//需要指定泛型为哪一个实体类
public interface UserMapper extends BaseMapper<User> {
}
@Test
public void testUserMapper(){
QueryWrapper<User> userWrapper = new QueryWrapper<>();
userWrapper.between("id",1,3);
List<User> users = userMapper.selectList(userWrapper);
users.forEach(System.out::println);
}
public void testUserDeleteById(){
userMapper.deleteById(5);//根据id删除
}
public void testUserDeleteByMap(){
Map<String, Object> map = new HashMap<>();
map.put("name","lisi");
map.put("age",14);
//DELETE FROM user WHERE name = ? AND age = ?
//根据map中的条件匹配删除
userMapper.deleteByMap(map);
}
public void testDeleteBatchIds(){
List<Integer> list = new ArrayList<>();
list.add(14);
list.add(34);
//根据id批量删除
userMapper.deleteBatchIds(list);
}
public void updateById(){
//根据id修改
userMapper.updateById(new User(1,"zhangsan",14,"[email protected]"));
}
public void selectById(){
//根据id查询
User user = userMapper.selectById(1);
System.out.println(user);
}
public void selectBatchIds(){
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
//根据id批量查询
List<User> users = userMapper.selectBatchIds(list);
users.forEach(System.out::println);
}
public void selectByMap(){
Map<String,Object> map = new HashMap<>();
map.put("name","lisi");
List<User> users = userMapper.selectByMap(map);
users.forEach(System.out::println);
}
/**
* * UserService继承IService模板提供的基础功能
*/
public interface UserService extends IService<User> {
}
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}
如果接口中的方法不够用则需要自己定义
我们在实现crud的时候,我们只是在BaseMapper中指定了泛型类User,没有指定在数据库中的表,便可以查询User表中的数据,因为Mybatis-plus默认是表名和实体类一致,如果不一致的话,则会报异常,所以需要@TableName指定实体类对应的表明
或者通过全局配置前缀
mybatis-plus:
configuration:
# 配置MyBatis日志
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
# 配置MyBatis-Plus操作表的默认前缀
table-prefix: t_
# 配置MyBatis-Plus的主键策略
id-type: auto
MyBatis-Plus在实现CRUD时,会默认将id作为主键列,并在插入数据时,默认 基于雪花算法的策略生成id
如果实体类中的主键不是id,而是其他名称,如uid,Mybatis-plus识别不了,则会出现异常
这时候需要在uid上加上@TableId,表示将字段设置为主键
@TableId(value = "id",type= IdType.AUTO)
private Integer id;
设置表中主键的名称
指定主键的策略
mybatis-plus:
configuration:
# 配置MyBatis日志
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
# 配置MyBatis-Plus的主键策略
id-type: auto
Mybatis-plus在执行的时候,需要保证实体类的属性名和数据库表中的字段名一致
可以使用@TableField标识实体类中的属性名并指定对应的字段名
@TableField("name")
private String name;
如果没有使用注解标注的话,Mybatis-plus默认属性名为对应的字段名
用于封装各种条件
@Test
public void test(){
QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
//lambda表达式先执行
userQueryWrapper
.like("name","J")
.and(i->{
i.eq("id","5")
.or()
.eq("id","6");
});
//SELECT id,name,age,email,is_deleted FROM user WHERE is_deleted=0 AND (name LIKE ? AND (id = ? OR id = ?))
List<User> users = userMapper.selectList(userQueryWrapper);
users.forEach(System.out::println);
}
@Test
public void test02(){
QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
//查询用户的name和age字段
//SELECT name,age FROM user WHERE is_deleted=0
userQueryWrapper.select("name","age");
//select搭配selectMaps使用避免User对象中出现属性值为空的现象
List<Map<String, Object>> list = userMapper.selectMaps(userQueryWrapper);
list.forEach(System.out::println);
}
@Test
public void test03(){
QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
//嵌套查询/子查询
//SELECT id,name,age,email,is_deleted FROM user WHERE is_deleted=0 AND (id IN (select id from user where `name` like '%J%'))
userQueryWrapper.inSql("id","select id from user where `name` like '%J%'");
List<User> users = userMapper.selectList(userQueryWrapper);
users.forEach(System.out::println);
}
实现修改功能有以下两种
@Test
public void test04(){
QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
userQueryWrapper.eq("name","jack");
User user = new User();
user.setAge(10);
// UPDATE user SET age=? WHERE is_deleted=0 AND (name = ?)
// 10(Integer), jack(String)
int update = userMapper.update(user, userQueryWrapper);
System.out.println(update);
}
@Test
public void test05(){
UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
userUpdateWrapper.eq("name","jack");
userUpdateWrapper.set("age",15);
// UPDATE user SET age=? WHERE is_deleted=0 AND (name = ?)
// 15(Integer), jack(String)
int update = userMapper.update(null,userUpdateWrapper);
System.out.println(update);
}
@Test
public void test06(){
String name = "j";
Integer ageBegin = 20;
Integer ageEnd = 50;
QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
userQueryWrapper.like(StringUtils.isNotBlank(name),"name",name)
.gt(ageBegin != null,"age",ageBegin)
.lt(ageEnd != null,"age",ageEnd);
//SELECT id,name,age,email,is_deleted FROM user WHERE is_deleted=0 AND (name LIKE ? AND age > ? AND age < ?)
//%j%(String), 30(Integer), 50(Integer)
List<User> users = userMapper.selectList(userQueryWrapper);
users.forEach(System.out::println);
}
防止写错数据库中的字段名,所以封装了支持Lambda表达式的条件查询类
@Test
public void test07(){
Integer ageBegin = 10;
LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
//使用Lambda表达式构造查询条件
userLambdaQueryWrapper.gt(ageBegin != null,User::getAge,ageBegin);
List<User> users = userMapper.selectList(userLambdaQueryWrapper);
users.forEach(System.out::println);
}
使用方法与LambdaQueryWrapper相似
在配置类中添加拦截器组件MybatisPlusInterceptor,并在这个拦截器中添加一个内部拦截器PaginationInnerInterceptor,指定数据库类型为MySql
@Configuration
@MapperScan("com.lin.mapper")
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return mybatisPlusInterceptor;
}
}
@Test
public void testPage(){
//指定当前页码和每页数据量
Page<User> userPage = new Page<>(2,3);
userMapper.selectPage(userPage,null);
//页中的数据
System.out.println("getRecords:"+userPage.getRecords());
//获取页码总数
System.out.println("getPages:"+userPage.getPages());
//获取当前页码数
System.out.println("getCurrent:"+userPage.getCurrent());
//获取总数据量
System.out.println("getTotal:"+userPage.getTotal());
//获取每页的数据量
System.out.println("getSize:"+userPage.getSize());
//是否存在上一页
System.out.println(userPage.hasPrevious());
//是否存在下一页
System.out.println(userPage.hasNext());
...
}
方法的第一个参数和返回值必须为Page类
@Mapper
public interface UserMapper extends BaseMapper<User> {
Page<User> queryAgePage(@Param("page") Page<User> page, @Param("age") Integer age);
}
<select id="queryAgePage" resultType="user">
select `id`,`name`,`age`,email from user where age>#{age}
select>
@Test
public void testQueryAgePage(){
Page<User> userPage = new Page<>(2,3);
userMapper.queryAgePage(userPage,10);
System.out.println(userPage.getRecords());
}
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
//添加分页插件
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
//添加乐观锁插件
mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return mybatisPlusInterceptor;
}
@Data
@TableName("t_product")
public class Product {
@TableId
private Long id;
private String name;
private Integer price;
//每当执行一次修改操作时,版本号version自加一
@Version
private Integer version;
}
每当执行修改操作的时候,都会检查一下版本号是否一致,如果不一致则执行不成功
//测试数据冲突
@Test
public void test(){
Product productLi = productMapper.selectById(1);
Integer priceLi = productLi.getPrice();
System.out.println("小李查出的数据:"+priceLi);
Product productWang = productMapper.selectById(1);
Integer priceWang = productWang.getPrice();
System.out.println("小王查出的数据:"+priceWang);
//小李修改数据
productLi.setPrice(priceLi+50);
productMapper.updateById(productLi);
//小王修改数据
productWang.setPrice(priceWang-30);
int i = productMapper.updateById(productWang);
while (i == 0){
System.out.println("修改失败,重新修改");
Product productNew = productMapper.selectById(1);
productNew.setPrice(productNew.getPrice() - 30);
i = productMapper.updateById(productNew);
}
System.out.println("老板查看的价格:"+ productMapper.selectById(1).getPrice());
}
@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;
}
}
@Data
@AllArgsConstructor
@NoArgsConstructor
//指定在数据库中所映射的表名
@TableName("user")
public class User {
@TableId(value = "id",type= IdType.AUTO)
private Long id;
@TableField("name")
private String name;
//sex属性
private SexEnum sex;
private Integer age;
private String email;
//逻辑删除
@TableLogic
private Integer isDeleted;
}
mybatis-plus:
configuration:
# 配置MyBatis日志
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
#通过全局配置idtType为auto
id-type: auto
#设置别名
type-aliases-package: com.lin.bean
#配置扫描通用枚举
type-enums-package: com.lin.enums
@Test
public void test(){
User user = new User();
user.setName("zhaoliu");
user.setAge(18);
user.setSex(SexEnum.MALE);
user.setEmail("[email protected]");
int insert = userMapper.insert(user);
System.out.println(insert);
}
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-generatorartifactId>
<version>3.5.1version>
dependency>
<dependency>
<groupId>org.freemarkergroupId>
<artifactId>freemarkerartifactId>
<version>2.3.31version>
dependency>
执行此方法
public static void main(String[] args) {
FastAutoGenerator.create("jdbc:mysql://127.0.0.1:3306/mybatis_plus?characterEncoding = utf-8 & userSSL = false", "root", "0911")
.globalConfig(builder -> {
builder.author("lin") // 设置作者
// .enableSwagger() // 开启 swagger 模式
.fileOverride() // 覆盖已生成文件
.outputDir("D://mybatis_plus"); // 指定输出目录
})
.packageConfig(builder -> {
builder.parent("com.lin") // 设置父包名
.moduleName("mybatisplus") // 设置父包模块名
.pathInfo(Collections.singletonMap(OutputFile.mapperXml, "D://mybatis_plus"));// 设置mapperXml生成路径
})
.strategyConfig(builder -> {
builder.addInclude("user") // 设置需要生成的表名
.addTablePrefix("t_", "c_"); // 设置过滤表前缀
})
.templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker 引擎模板,默认的是Velocity引擎模板
.execute();
}
<dependency>
<groupId>com.baomidougroupId>
<artifactId>dynamic-datasource-spring-boot-starterartifactId>
<version>3.5.0version>
dependency>
spring:
datasource:
dynamic:
# 严格匹配数据源,默认为false。true表示未匹配到指定数据源时抛异常,false表示如果未匹配则使用默认数据源
strict: false
# 设置默认的数据源或者数据源组,默认值即为master
primary: master
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: 0911
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: 0911
在Service实现类上标注@DS,,指定数据源
@Service
@DS("master")//指定数据源为master
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService{
}
@Service
@DS("slave_1")
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements ProductService{
}
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 0911
自动在mapperxml文件中生成的insert语句
<insert id="insertSelective">
insert into user
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">id,if>
<if test="name != null">name,if>
<if test="sex != null">sex,if>
<if test="age != null">age,if>
<if test="email != null">email,if>
<if test="isDeleted != null">is_deleted,if>
trim>
values
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">#{id,jdbcType=BIGINT},if>
<if test="name != null">#{name,jdbcType=VARCHAR},if>
<if test="sex != null">#{sex,jdbcType=INTEGER},if>
<if test="age != null">#{age,jdbcType=INTEGER},if>
<if test="email != null">#{email,jdbcType=VARCHAR},if>
<if test="isDeleted != null">#{isDeleted,jdbcType=INTEGER},if>
trim>
insert>