MyBatis-plus从入门到会用

前言

此篇博客是本人近数日的学习成果,希望对正在学习MyBatis-plus的各位有所帮助。


Mybatis-Puls

1. Mybatis-Plus简介及特性

Mybatis-plus的简介:MP(Mybatis-Plus)是一个MyBatis的增强工具,只做增强不做修改

Mybatis-plus的特性: (mybatis-plus 官方文档摘抄)

  • 无入侵(只做增强),损耗小(注入即用),强大的CRUD操作
  • 支持Lambda形式调用
  • 支持主键自动生成支持ActiveRecord模式
  • 支持自定义全局通用操作,支持关键字自动转换
  • 内置代码生成器,内置分页插件,内置性能分析插件
  • 内置全局拦截插件,内置Sql注入剥离器

2. 使用mybatis-plus需要引入的依赖(官方最新版本)

<dependency>
	<groupId>com.baomidou</groupId>
	<artifactId>mybatis-plus-boot-starter</artifactId>
	<version>3.1.1</version>
</dependency>

3. Mybatis-plus入门的简单例子 (使用mybatis-plus的通用mapper完成简单的CRUD,在SpringBoot测试类中完成)

1. 准备工作:创建数据库,创建表,创建SpringBoot项目,引入依赖(mysql,mybatis-plus,lombok),编写SpringBoot配置文件(application.properties)

2. 我的项目结构
Project目录结构

3.编写代码:
在domain包下创建一个与数据库表对应的Java实体类(User),在实体类User中有用到以下Mybatis-plus的注解(更多注解请参照mybatis-plus官方文档)

  • @TableName(“对应该Java实体类的表名”)
  • @TableId(value=“对应表中的字段名”,type=IdType.主键的一些自动设置)

3.1 User实体类

/**
 * @Author Jimmy
 * @Date 2019/10/8 3:12 PM
 * @Desc 用户类
 */

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("b_user")
public class User {
    // MyBatis-Plus 声明主键
    // 如果表中的主键使用了自增 需要在次注解中声明 type = IdType.AUTO(自增)[本人亲测]
    @TableId(value = "uid",type = IdType.AUTO)
    private Integer uid;
    private String username;
    private Integer age;
    private String email;
}

3.2 在DAO层, 创建UserMapper接口,继承BaseMapper接口; 接口的泛型为User
特别说明:在使用mybatis的通用mapper的时候可以在接口上添加@Mapper(org.apache.ibatis.annotations.Mapper),SpringBoot启动类启动时会将接口添加到Spring容器中,但是在mybatis-plus中在接口上添加@Mapper注解是不好使的需要在SpringBoot启动类中使用@MapperScan注解配置接口所在包的位置。这样才能被加入到Spring容器中

public interface UserMapper extends BaseMapper<User> {
	// do something...
}

3.2 SpringBoot启动类

@SpringBootApplication
@MapperScan("com.czxy.dao")
public class MybatisPlusApplication {
    public static void main(String[] args) {
        SpringApplication.run(MybatisPlusApplication.class, args);
    }
}

3.4 CRUD JUnit测试

@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserMapperTests {
	@Autowired
	private UserMapper mapper;

	/**
	 * 查询:selectList()方法,因为是简单的查询这里查询条件为null
	 * 查询所有(该方法常配合条件构造器进行复杂查询)
	 */
	@Test
    public void query() {
        //查询所有
        List<User> users = mapper.selectList(null);
        Assert.assertEquals(5,users.size());
        users.forEach(System.out::println);
        log.info("---------");
        //条件查询 根据指定主键查询记录
        User user = mapper.selectById(1);        log.info("User :{}", user);
    }

	/**
     * 添加:insert()
     */
    @Test
    public void addUser() {
        User user = new User(null,"Jack",25,"Jack123@163.com");
        // 返回影响条数
        int result = mapper.insert(user);
        // 使用断言判断
        Assert.assertEquals(1, result);
    }
    
	/**
     * 修改:updateById(T entity) 根据记录的注解对记录进行修改
     */
    @Test
    public void updateUser() {
        User user = new User(1,"Jimmy",19,"Jimmy123@163.com");
        //根据主键对记录进行更改 返回影响条数
        int number = mapper.updateById(user);
        Assert.assertEquals(1, number);
    }

	/**
	 * 删除:deleteById(Serializable id) 根据主键删除记录
	 */
	@Test
    public void deleteUser() {
        //删除记录返回影响调试
        int number = mapper.deleteById(5);
        Assert.assertEquals(1, number);
    }
}		

阅读到这恭喜你入门了,Welcome to use MyBatis-plus

接下来, 更深入的了解Mybatis-plus

通过简单的例子概述了mybatis-plus简单的CRUD功能,让我们再深入的来了解mybatis-plus的强大之处

主要介绍:

排除非表字段的三种方式:

  1. 第一种使用 在非表字段属性中transient
  2. 第二种方式 在非表字段属性中 加入static (在JavaBean中要自己生成get & set方法)
  3. 第三种方式 使用Mybatis-plus 提供的注解 TableField(exits = false)

条件构造器查询(案例的形式说明,数据库表对应的实体类即是上面的User类,结构比较简单在此不提供)

  • select不列出全部字段
/**
 * 查询所有姓为J的用户,只显示用户名和email
 */
 //创建条件构造器
 QueryWrapper<User> queryWrapper01 = new QueryWrapper<>();
 queryWrapper01.likeRight("username", "J").select("username", "email");
 mapper.selectList(queryWrapper01).forEach(System.out::println);

/**
 * 查询所有大于19岁的用户,除了年龄不显示其他都显示
 */
 QueryWrapper<User> queryWrapper = new QueryWrapper<>();
 //如果有多个不显示的字段 在后面加 && !info.getColumn().equals("")
 queryWrapper.gt("age", 19)
 	.select(User.class, info -> !info.getColumn().equals("age"));
 mapper.selectList(queryWrapper).forEach(System.out::println);
  • 条件构造器中condition的作用
/**
 * 说明:在测试类中调用方法传入两个参数("username","email")
 * 被在调用的方法中判断username和email是否为空,如果不为空模糊查询username like username  email like email
 * 采用like方法中的condition 和 不采用like方法中的condition演示
 * like(boolean condition, R column, Object val)
 */

 @Test
 public void conditionTest() {
 	String username = "J";
 	String email = "163";
 	demoCondition(username,email);
 }
		
 //定义方法
 private  void demoCondition (String username,String email) {
	//创建条件构造器
	QueryWrapper<User> queryWrapper = new QueryWrapper<>();

	/* 没有使用like方法中的condition */
	//        if (StringUtils.isNullOrEmpty(username)) {
	//            queryWrapper.like("username",username);
	//        }
	//        if (StringUtils.isNullOrEmpty(email)) {
	//            queryWrapper.like("email",email);
	//        }

	/* 使用了like方法中的condition */
	queryWrapper.like(StringUtils.isNullOrEmpty(username),"username",username)
        .like(StringUtils.isNullOrEmpty(email),"email",email);
	mapper.selectList(queryWrapper).forEach(System.out::println);
}
  • 创建条件构造器时传入实体对象
/**
 * 如果条件构造器中传入了对象,也有其他条件,他们是互不影响的
 * 注意:如果传入的对象的属性于其他设立的条件等值了,可以在JavaBean中声明
 * @TableField(condition = SqlCondition.LIKE)
 */
 //创建user对象
 User user = new User();
 user.setUsername("Jimmy");
 user.setAge(19);

 //创建条件构造器
 QueryWrapper<User> queryWrapper = new QueryWrapper<>(user);
 queryWrapper.like("username","J").isNotNull("email");
 mapper.selectList(queryWrapper).forEach(System.out::println);
  • 条件构造器中 allEq 的用法
//创建条件构造器
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
//创建一个map集合(该集合即为查询的条件)
Map<String,Object> condition = new HashMap<>();
condition.put("username","Jimmy");
condition.put("age",null);
//调用条件构造器中allEq方法
//该方法有一参数,两个参数的形式,一个参数则是根据map集合中的条件对数据进行过滤
//两个参数的也是根据map集合中的条件对数据进行过滤,但是另一个参数为boolean值,为true是不忽略条件中为null的字段
//为false是忽略map集合中为null的字段
//queryWrapper.allEq(condition,false);
//还有一种方式 他是一个过滤函数,传入多参数时允许对参数进行过滤
//下面这种写法是不将username这个字段加入条件中
queryWrapper.allEq((k,v) -> !k.equals("username"),condition );
List<User> users = mapper.selectList(queryWrapper);
users.forEach(System.out::println);
  • 其他以条件构造器查询的方法
    • selectMaps -> 根据条件构造器中的条件将查询的结果封装到map集合中
    • selectObjs -> 根据条件构造器查询每条记录的第一列
    • selectOne -> 根据条件构造器中的条件查询一条记录,如果查询结果出现多条记录会报错
//selectMaps -> 根据条件构造器中的条件将查询的结果封装到map集合中
//创建条件构造器
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.select("uid","username").eq("username","Jimmy").lt("age",23);
List<Map<String, Object>> maps = mapper.selectMaps(queryWrapper);
maps.forEach(System.out::println);

//selectObjs -> 根据条件构造器查询每条记录的第一列
//创建条件构造器
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
//我在这里定义了条件显示id 和 username 但是事实上他会去除其他多于的列queryWrapper.select("uid","username").eq("username","Jimmy");

List<Object> objs = mapper.selectObjs(queryWrapper);
objs.forEach(System.out::println);

//selectOne -> 根据条件构造器中的条件查询一条记录,如果查询结果出现多条记录会报错
//创建条件构造器
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("uid","10").eq("username","Jimmy");

User user = mapper.selectOne(queryWrapper);
System.out.println(user);

selectMaps案例

/**
 * 需求:根据直属上级ID分组,分别查询组中的最小年龄,最大年龄,平均年龄,并区年龄总小于40
 * SQL:
	SELECT 
		MIN(b_age) min_age,
		MAX(b_age) max_age,
		AVG(b_age) avg_age
	FROM department
	GROUP BY belong HAVING SUM(b_age) < 40
 */
 //创建条件构造器
 QueryWrapper<Department> queryWrapper = new QueryWrapper<>();
 queryWrapper.select("MIN(b_age) min_age","MAX(b_age) max_age","AVG(b_age) avg_age")
         .groupBy("belong")
         //SUM(b_age) < {0} 使用的是可变参数
         .having("SUM(b_age) < {0}",40);
 List<Map<String, Object>> maps = departmentMapper.selectMaps(queryWrapper);
 maps.forEach(System.out::println);
  • lambda条件构造器
    • lambda条件构造器的好处:使用lambda表达式的好处是 防误写
    • lambda条件构造器创建的三种方式
//1.使用new QueryWrapper<User>().lambda()
LambdaQueryWrapper<T> lambda = new QueryWrapper<T>().lambda();

//2.直接new
LambdaQueryWrapper<T> lambdaQueryWrapper = new LambdaQueryWrapper<>();

//3.使用wrappers工具类点lambda()
LambdaQueryWrapper<T> lambdaQuery = Wrappers.lambdaQuery();
  • 使用lambda条件构造器完成的两个小demo
//1.查询名字中包含 "k" 并且 年龄为为19的用户记录
//使用lambda表达式的好处是 防误写
lambdaQuery.like(User::getUsername,"J").eq(User::getAge,19);
List<User> users = mapper.selectList(lambdaQueryWrapper);
users.forEach(System.out::println);

//2.查询姓为"J",并且(年龄大于19或者邮箱不为空)的所有记录
//创建lambda条件构造器
LambdaQueryWrapper<User> queryWrapper = Wrappers.lambdaQuery();
queryWrapper.likeRight(User::getUsername,"J").and(lqw ->lqw.gt(User::getAge,"19").or().isNotNull(User::getEmail));
//遍历查看数据
mapper.selectList(queryWrapper).forEach(System.out::println);
  • lambda条件构造器传入实体类对应的mapper
LambdaQueryChainWrapper<User> chainWrapper = new LambdaQueryChainWrapper<>(mapper);
//可以直接通过 .list获得记录的对象集合
chainWrapper.like(User::getUsername,"r").list().forEach(System.out::println);
  • 使用条件构造器查询数据的小demo
/**
 * 查询用户名中包含m,并且年龄大于 23岁的 所有用户
 */
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.like("username", "m").ge("age", 23);
List<User> users = mapper.selectList(queryWrapper);
users.forEach(System.out::println);
/**
 * 查询用户名中包含m,并且年龄大于等于19小于等于23,并且email不为空的
 */
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.like("username", "m").between("age", 19, 23).isNotNull("email");
List<User> users = mapper.selectList(queryWrapper);
users.forEach(System.out::println);
/**
 * 查询姓名性李或者年龄大于23,按照年龄降序排序,年龄相同按照id升序排序
 */
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.likeRight("username", "李").or().gt("age", 23).orderByAsc("age","uid");
List<User> users = mapper.selectList(queryWrapper);
users.forEach(System.out::println);
/**
 * 查询创建日期为2019年10月9日并且直属上级姓名为王性
 */

QueryWrapper<Department> queryWrapper = new QueryWrapper<>();

//TODO 注意:apply方法可以是一个参数页可以是两个参数
//apply为一个参数时和两个参数时查询的效果都是一样的
//但是有两个参数可以避免SQL注入
//b_time 对应的是数据库中表的字段名
queryWrapper.apply("(date_format(b_time,'%Y-%m-%d')={0})", "2019-10-09")
        .inSql("belong", "select emp_id from department where b_name like '王%'");
departmentMapper.selectList(queryWrapper).forEach(System.out::println);
/**
 * 查询为J姓,并且年龄大于23或者邮箱不为空
 */
 //创建条件构造器
 QueryWrapper<User> queryWrapper = new QueryWrapper<>();
 queryWrapper.likeRight("username", "J").and(wq -> wq.gt("age", 23).or().isNotNull("email"));
 mapper.selectList(queryWrapper).forEach(System.out::println);
/**
* 查询为J姓,或者年龄小于30岁大于19岁并且邮箱不为null
*/
//创建条件构造器
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.likeRight("username", "J").or(wq -> wq.lt("age", 30).gt("age", 19).isNotNull("email"));
mapper.selectList(queryWrapper).forEach(System.out::println);
		
/**
 * 查询:(年龄小于23并且邮箱不为空)并且姓J
 */
//创建条件构造器
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.lt("age", 23).isNotNull("email").and(wq -> wq.likeRight("username", "J"));
mapper.selectList(queryWrapper).forEach(System.out::println);
		        
/**
 * 查询年龄为19,20,21,22,23
 * age in(19,20,21,22,23)
 */

//创建条件构造器
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.in("age", Arrays.asList(19, 20, 21, 22, 23));
mapper.selectList(queryWrapper).forEach(System.out::println);
/**
 * 只返回满足条件的一条记录
 */
//创建条件构造器
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
//last 谨慎使用!! 只能调用一次,已最后一次为准,有SQL注入的风险
queryWrapper.in("age", Arrays.asList(19, 20, 21, 22)).last("limit 1");
mapper.selectList(queryWrapper).forEach(System.out::println);

分页功能

  • Mybatis-plus中提供的物理插件 分页查询 注意:分页查询需要添加分页插件(在配置类中添加,或者在SpringBoot启动类中添加)
@SpringBootApplication
@MapperScan("com.czxy.dao")
public class MybatisPlusApplication {

    public static void main(String[] args) {
        SpringApplication.run(MybatisPlusApplication.class, args);
    }

    /*
     * 分页插件
     */
    @Bean
    public PaginationInterceptor paginationInterceptor(){
        return new PaginationInterceptor();
    }
}
   
  • 分页查询的两个方法
  • 1.selectPage(IPage page, @Param(Constants.WRAPPER) Wrapper queryWrapper) 在方法中传入分页查询条件对象,和条件构造器,方法返回的是分页查询条件对象其泛型为实体对象
  • 2.selectMapsPage(IPage page, @Param(Constants.WRAPPER) Wrapper queryWrapper) 在方法中传入分页查询条件对象,和条件构造器其泛型为map集合
  • demo
//演示 selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper) 方法
//创建分页查询条件对象
Page<User> page = new Page<>(1,3);
//创建条件构造器
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.like("username","m").eq("age",19);
//mapper调用分页方法
IPage<User> userIPage = mapper.selectPage(page, queryWrapper);
//获取总页数
System.out.println("总页数:"+userIPage.getPages());
//获取总条数
System.out.println("总条数:" + userIPage.getTotal());

//获取分页查询结果 并打印
userIPage.getRecords().forEach(System.out::println);

System.out.println("------------------------------------------------------------");

//演示 selectMapsPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper) 方法

//创建分页条件对象,
Page<User> mapPage = new Page<>(1,3);
//创建条件构造器
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.like("username","m").eq("age",19);
//mapper调用selectMapsPage方法
IPage<Map<String, Object>> mapIPage = mapper.selectMapsPage(mapPage, wrapper);
//获取总页数
System.out.println("总页数:"+mapIPage.getPages());
//获取总条数
System.out.println("总条数:" + mapIPage.getTotal());

//获取分页查询结果 并打印
mapIPage.getRecords().forEach(System.out::println);
  • 4.自定义SQL查询(注解以及xml形式)

    使用条件构造器自定义SQL(mp支持该种方式,但是版本必须大于3.0.7)

  • 使用注解: 在UserMapper接口中自定义一个查询的方法,并在方法上使用@Select注解编写SQL

//mp 提供的Constants接口有定义的常量 WRAPPER:表示类
@Select("select * from user ${ew.customSqlSegment}")
List<User> selectAllUser(@Param(Constants.WRAPPER) LambdaQueryWrapper<User> wrappers);

测试类中调用方法:

LambdaQueryWrapper<User> wrapper = Wrappers.lambdaQuery();
wrapper.like(User::getUsername,"Jimmy");
List<User> users = mapper.selectAllUser(wrapper);
users.forEach(System.out::println);
  • 使用XML自定义SQL

    我的项目结构

在这里插入图片描述

1.在application.properties中配xml文件所在包的位置

  mybatis-plus.mapper-locations=classpath:mapper/*Mapper.xml

2在resources目录下创建mapper包,在mapper包下创建xml文件xml文件内容如下

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org/DTD Mapper 3.0//EN" "mybatis-3-mapper.dtd">
<mapper namespace="com.czxy.dao.UserMapper">
   <select id="selectAllUser" resultType="com.czxy.domain.User">
       select * from user ${ew.customSqlSegment}
   </select>
</mapper>

将UserMapper接口中方法上的@Select注解注射

List<User> selectAllUser(@Param(Constants.WRAPPER) LambdaQueryWrapper<User> wrappers);

测试类

LambdaQueryWrapper<User> wrapper = Wrappers.lambdaQuery();
wrapper.like(User::getUsername,"Jimmy");
List<User> users = mapper.selectAllUser(wrapper);
users.forEach(System.out::println);
  • 5.通过更新条件构造器对记录进行修改

    • 创建更新条件构造器的两种方式
      • 方式一:创建更新条件构造器,没有在构造函数中传入实体对象
      • 方式二:创建更新条件构造器对象,在对象的构造函数中传入一个实体对象(注意:该实体对象会被自动的加入where条件中(是以对比的方式判断的))
    • 案例演示
//方式一:创建更新条件构造器,没有在构造函数中传入实体对象
//创建更新条件构造器
UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
//编写更新记录的条件
userUpdateWrapper.eq("username","Jack").eq("age",25);
//创建User对象,在对象中封装要被修改的数据
User user = new User();
user.setEmail("3073665207@qq.com");
//使用mapper调用方法 方法返回影响条数
int number = mapper.update(user, userUpdateWrapper);
//打印查看影响条数
System.out.println(number +" 条数据受到影响");
//方式二:创建更新条件构造器对象,在对象的构造函数中传入一个实体对象(注意:该实体对象会被自动的加入where条件中(是以对比的方式判断的))
//创建条件构造器
//创建User对象
User user = new User();
user.setUsername("Jack");
user.setAge(25);
//创建更新条件构造器
UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>(user);
//TODO 特别注意:如果传入的对象中的条件与该更新条件构造器的中的条件相同时,请去掉其中一个条件(不去掉:等值的实体类的属性上添加@TableField(condition = SqlCondition.LIKE) 改变条件的类型)
//userUpdateWrapper.eq("username","Jack").set("email","1122@163.com");

//创建User对象,将要改变的字段值封装到对象中
User updateUser = new User();
updateUser.setEmail("878787@163.com");
int number = mapper.update(updateUser, userUpdateWrapper);
System.out.println(number + " 条数据受到影响");

//如果修改个别字段的值,可以直接通过更新条件构造器对象中的set方法,如下所示
//userUpdateWrapper.eq("username","Jack").set("email","1122@163.com");
  • 创建lambda更新条件构造器的两种方式(使用的方式和普通的条件构造器几乎一样,但是这个形式有较好防误写功能)
  • 第一种:创建lambda更新条件构造器,不传入实体对象对应的mapper,另一种则是传入实体对象对应的mapper
  • 第二种:创建LambdaUpdateChainWrapper更新条件构造器,在构造函数中传入泛型实体类对应的mapper
  • 案例演示
//第一种:创建lambda更新条件构造器,不传入实体对象对应的mapper,另一种则是传入实体对象对应的mapper
//创建创建lambda更新条件构造器
LambdaUpdateWrapper<User> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
//编写更新条件
lambdaUpdateWrapper.eq(User::getUsername,"王五").eq(User::getAge,25);
//创建User对象,将需要被更新的数据传入对象中
User updateUser = new User();
updateUser.setEmail("1258@163.com");
//通过mapper调用update方法 方法返回影响条数
int number = mapper.update(updateUser, lambdaUpdateWrapper);
//打印查看影响条数
System.out.println(number+" 条数据受到影响");

System.out.println("---------------------LambdaUpdateWrapper更新条件构造器的第二种形式------------------------");

//创建LambdaUpdateChainWrapper更新条件构造器,在构造函数中传入泛型实体类对应的mapper
//编写更新条件
//.update 对数据进行更新 方法的返回值是一个boolean类型 true即更新成功 false即更新失败
LambdaUpdateChainWrapper<User> chainWrapper = new LambdaUpdateChainWrapper<>(mapper);
boolean update = chainWrapper.eq(User::getUsername, "李四").eq(User::getAge, 24).set(User::getEmail,"123123@163.com").update();
if (update) {
    System.out.println("修改成功");
} else {
    System.out.println("修改失败");
}
  • 6.其他非条件构造器删除,通过删除条件构走器对数据进行删除

    • 其他普通非条件构造器删除
      • 1.deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap) 传入的参数是一个Map集合,根据Map集合中的键值对,对数据进行删除
      • 2.deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList) 传入多个主键,对记录进行批量删除
    • 案例
//创建一个Mapper集合
//调用deleteByMap() 方法将Map集合传入方法的构造函数中,方法的返回值是删除条数
Map<String,Object> map = new HashMap<>();
map.put("username","张三");
map.put("age",23);
int number = mapper.deleteByMap(map);
System.out.println("删除了" + number + "条记录");

System.out.println("-----------------------------------");
//调用deleteBatchIds() 方法传入多个主键,对记录进行批量删除
int deleteBatchIds = mapper.deleteBatchIds(Arrays.asList(1, 2, 3));
System.out.println("删除了"+deleteBatchIds+"条数据");
  • 条件构造器删除
//创建lambda条件构造器
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
//编写条件
queryWrapper.eq(User::getUsername,"Jack").eq(User::getAge,25);
int delete = mapper.delete(queryWrapper);
System.out.println("删除了"+delete+"条数据");
  • ActiveRecord模式

ActiveRecord模式介绍:简单粗暴来说就是通过实体对象来对表中的记录进行CRUD

实现ActiveRecord模式的两个要求:

1.实体类继承抽象类Model

/**
 * @Author Jimmy
 * @Date 2019/10/8 3:12 PM
 * @Desc 用户类
 */

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User extends Model<User> {
    //MyBatis-Plus 声明主键
    //如果表中的主键使用了自增 需要在次注解中声明 type = IdType.AUTO(自增)
    @TableId(value = "uid",type = IdType.AUTO)
    private Integer uid;
    private String username;
    private Integer age;
    private String email;
}

2.必须存在对应的原始mapper接口继承BaseMapper

public interface UserMapper extends BaseMapper<User> {

}

3.编写CRUD

添加数据

//向数据库中插入数据
User user = new User();
user.setUsername("朱茵");
user.setAge(23);
user.setEmail("ns@163.com");
//user对象点insert方法插入数据 方法返回的是boolean值 true插入成功 false 插入失败
boolean insert = user.insert();
System.out.println(insert);

查询数据

//查询数据 根据主键查询数据
User user = new User();
User byId = user.selectById(1);
System.out.println(byId);

System.out.println("--------------------");
//selectById() 不传参数查询 给user对象中的主键属性赋值(查询用的就是对象中的属性值)
User user1 = new User();
user1.setUid(1);
System.out.println(user1.selectById());

删除数据

//删除 根据主键删除记录
User user = new User();
//方法的返回值是一个boolean值
boolean byId = user.deleteById(1);
System.out.println(byId);
//删除方法也是可以采用和查询方法一样的操作 不传参删除

修改数据

//修改 根据ID删除记录 方法的返回值是boolean类型
User user = new User();
user.setUid(2);
user.setEmail("15113@163.com");
boolean byId = user.updateById();
System.out.println(byId);

insertOrUpdate方法

 //insertOrUpdate 方法 在方法执行的时候它会先去表中查询表中是否有这样的一条记录,如果没有它会将这条数据添加到表中(返回值为false),存在则会修改这条数据
User user = new User();
user.setUid(98);
user.setUsername("Jimmy");
user.setAge(76);
boolean insertOrUpdate = user.insertOrUpdate();
System.out.println(insertOrUpdate);
  • mybatis-plus中的主键策略

    参考

/*
 * 数据库ID自增
 */
 AUTO(0),
/**
 * 该类型为未设置主键类型
 */
NONE(1),
/**
 * 用户输入ID
 * <p>该类型可以通过自己注册自动填充插件进行填充</p>
 */
INPUT(2),

/* 以下3种类型、只有当插入对象ID 为空,才自动填充。 */
/**
 * 全局唯一ID (idWorker)
 */
ID_WORKER(3),
/**
 * 全局唯一ID (UUID)
 */
UUID(4),
/**
 * 字符串全局唯一ID (idWorker 的字符串表示)
 */
ID_WORKER_STR(5);
  
  • 通用Service

    一般情况,我们写项目的分层有 domian,dao,service,contrller

    如果是一些简单的CRUD操作我们就没有必要去dao中的mapper中编写了,这时候我们可以通过通用Service

    如何定义通用Service

    我的项目结构

    UserService接口继承IService 泛型即是mappe对应的实体对象

    UserServiceImpl类继承ServiceImpl(<M extends BaseMapper, T) 该类有两个构造参数,前一个为实体类对应的mapper,后一个即是实体类

    UserService

public interface UserService extends IService<User> {
	
} 

UserServiceImpl

/**
 * @Author Jimmy
 * @Date 2019/10/16 9:40 PM
 * @Desc UserService接口的实现类
 */

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements UserService {

}

演示的方法:

1.getOne(Wrapper queryWrapper)方法,根据条件查询记录,只查询一条记录

2.批量插入方法saveBatch(Collection entityList)

3.saveOrUpdateBatch(Collection entityList) 批量修改插入

4.使用条件构造器查询

5.使用条件修改数据

6.使用条件构造器删除数据

演示

//getOne(Wrapper<T> queryWrapper)方法,根据条件查询记录,只查询一条记录
//我这里是查询了多条记录,所有使用getOne(Wrapper<T> queryWrapper) 方法传参为一个时运行时会保存
//但是,在方法中再传入一个false则它只会去查询到的记录的第一条
User user = service.getOne(new LambdaQueryWrapper<User>().eq(User::getAge, 19),false);
System.out.println(user);
//批量插入方法saveBatch(Collection<T> entityList)
//我在这里创建多个User对象封装到List集合中传入该方法中,该方法的返回值为boolean类型(注意:只要该方法运行时没有报错都会返回true)

User user1 = new User();
user1.setUsername("凌琳");
user1.setAge(18);
user1.setEmail("xl1456289@163.com");

User user2 = new User();
user2.setUsername("阿雨");
user2.setAge(20);
user2.setEmail("ay1872649@163.com");

List<User> users = Arrays.asList(user1, user2);
boolean b = service.saveBatch(users);
System.out.println(b);


System.out.println("------------------------------------------");
//saveOrUpdateBatch(Collection<T> entityList) 批量修改插入
//这个方法在执行的时候会先去查询数据库中的表,如果数据库中的表有对应的记录则修改这条记录,如果吗,没就会将这条记录插入到数据库表中


User user3 = new User();
user3.setUid(23);
user3.setUsername("凌琳");
user3.setAge(18);
user3.setEmail("1456289@163.com");

User user4 = new User();
user4.setUsername("蔡虚昆");
user4.setAge(24);
user4.setEmail("cxk1456289@163.com");

List<User> list = Arrays.asList(user3, user4);
boolean b1 = service.saveOrUpdateBatch(list);
System.out.println(b1);
//条件查询
service.lambdaQuery().eq(User::getUsername,"Jimmy").eq(User::getAge,19).list().forEach(System.out::println);
//根据条件修改数据
boolean update = service.lambdaUpdate().eq(User::getUsername, "Jimmy").set(User::getAge, 20).update();
System.out.println(update);
//根据条件删除数据
boolean remove = service.lambdaUpdate().eq(User::getAge, 20).remove();
System.out.println(remove);
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值