MyBatis-Plus - 快速入门
1、数据库建表
# 创建用户表
CREATE TABLE user (id BIGINT(20) PRIMARY KEY NOT NULL COMMENT '主键',name VARCHAR(30) DEFAULT NULL COMMENT '姓名',age INT(11) DEFAULT NULL COMMENT '年龄',email VARCHAR(50) DEFAULT NULL COMMENT '邮箱',manager_id BIGINT(20) DEFAULT NULL COMMENT '直属上级id',create_time DATETIME DEFAULT NULL COMMENT '创建时间',CONSTRAINT manager_fk FOREIGN KEY (manager_id)REFERENCES user (id)
) ENGINE=INNODB CHARSET=UTF8;# 初始化数据:
INSERT INTO user (id, name, age, email, manager_id, create_time)
VALUES (1087982257332887553, '大boss', 40, 'boss@baomidou.com', NULL, '2019-01-11 14:20:20'),(1088248166370832385, '王天风', 25, 'wtf@baomidou.com', 1087982257332887553, '2019-02-05 11:12:22'),(1088250446457389058, '李艺伟', 28, 'lyw@baomidou.com', 1088248166370832385, '2019-02-14 08:31:16'),(1094590409767661570, '张雨琪', 31, 'zjq@baomidou.com', 1088248166370832385, '2019-01-14 09:15:15'),(1094592041087729666, '刘红雨', 32, 'lhm@baomidou.com', 1088248166370832385, '2019-01-14 09:48:16');
2、依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId>
</dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope>
</dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional>
</dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional>
</dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope>
</dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.1.2</version>
</dependency>
3、SpringBoot 配置文件
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverusername: rootpassword: rooturl: jdbc:mysql://localhost:3306/test?serverTimezone=CTT&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
logging:level:root: warnorg.ywb.demo.dao: tracepattern:console: '%p%m%n'
4、创建相关包,如图
5、在pojo包中新建和数据库user表映射的类
@Data
public class User {private Long id;private String name;private Integer age;private String email;private String managerId;private LocalDateTime createTime;
}
6、在dao包中创建mapper接口,并集成mybatisPlus的BaseMapper
public interface UserMapper extends BaseMapper<User> {}
7、在springboot启动类添加@MapperScan
扫描dao层接口
@MapperScan("org.ywb.demo.dao")
@SpringBootApplication
public class MybatisPlusDemoApplication {public static void main(String[] args) {SpringApplication.run(MybatisPlusDemoApplication.class, args);}}
8、编写测试类
@RunWith(SpringRunner.class)
@SpringBootTest
public class MybatisPlusDemoApplicationTests {@Resourceprivate UserMapper userMapper;@Testpublic void select(){List<User> users = userMapper.selectList(null);users.forEach(System.out::println);}}
9、运行结果
新增方法
UserMapper代码
package com.neo.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.neo.model.User;
import org.apache.ibatis.annotations.Mapper;//要使用mp,就要集成BaseMapper
@Mapper
public interface UserMapper extends BaseMapper<User> {}
在测试方法中调用userMapper中的insert方法
@Test
public void insert(){User user = new User();user.setName("黄小明");user.setAge(20);user.setManagerId(1088248166370832385L);user.setCreateTime(LocalDateTime.now());int rows = userMapper.insert(user);System.out.println("影响记录数:"+rows);}
测试结果
DEBUG==> Preparing: INSERT INTO user ( id, name, age, manager_id, create_time ) VALUES ( ?, ?, ?, ?, ? ) DEBUG==> Parameters: 1223961279246393345(Long), 黄小明(String), 20(Integer), 1088248166370832385(Long), 2020-02-02T21:28:03.621(LocalDateTime) DEBUG<== Updates: 1 影响记录数:1
常用注解
MyBatisPlus提供了一些注解供我们在实体类和表信息出现不对应的时候使用。通过使用注解完成逻辑上匹配。
注解名称 | 说明 |
---|---|
@TableName
|
实体类的类名和数据库表名不一致 |
@TableId
|
实体类的主键名称和表中主键名称不一致 |
@TableField
|
实体类中的成员名称和表中字段名称不一致 |
@TabName注解
当修改数据库表明却不想修改实体类型时,可以通过@TabName("数据库表名")来指定表名,否则会运行报错。
@Data
@TableName("mp_user")
public class User {//主键private Long id;//姓名private String name;//年龄private Integer age;//邮箱private String email;//直属上级private Long managerId;//创建时间private LocalDateTime createTime;
}
@TabId注解
当实例中主键与数据库中的主键名称不一致时(例如实例中为驼峰命名,数据库表中为下划线命名),可使用该注解。
@TableField注解
当实例中的字段与数据库中的字段不同时,就可以使用该注解映射,如下例
@TableField("name")
private String realName;
排除非表字段的三种方式
第一:在声明类属性时使用 transient 关键字声明。
第二:如上方法可能无法序列化该字段,故可以在声明类属性时:使用 static 关键字声明为静态变量(注意,用static 声明的静态变量lombok不会为其添加set和get方法)。
第三:使用@TableField(exist = false)注解注解 其中括号中的 exist = false 表示该字段不是数据库表中的字段,无需映射。
基本查询方法
通过id查询:selectById()方法
@Test
public void selectById() {User user = userMapper.selectById(1094590409767661570L);System.out.println(user);
}
批量查询:selectBatchIds()
@Test
public void selectByIds() {List<Long> idsList = Arrays.asList(1094592041087729666L, 1223961279246393345L, 1088250446457389058L);List<User> users = userMapper.selectBatchIds(idsList);users.forEach(System.out::println);
}
通过map查询
@Test
public void selectByMap() {Map<String,Object> columnMap = new HashMap<>();columnMap.put("name","王天风");columnMap.put("age",25);//通过此map会执行类似 where name="王天风" and age=25 的sqlList<User> userList = userMapper.selectByMap(columnMap);userList.forEach(System.out::println);
}
注意:此map中的键名为数据表中列名,并非实体类中的属性名
以条件构造器为参数的查询方法
/* 查询要求:1、名字中包含雨并且年龄小于40name like '%雨%' and age<40*/
@Test
public void selectByWrapper() {QueryWrapper<User> queryWrapper = new QueryWrapper<>();//等同于//QueryWrapper<User> query = Wrappers.<User>query();queryWrapper.like("name","雨").lt("age",40);//注意:此处的键名依旧为数据库中的列名List<User> userList = userMapper.selectList(queryWrapper);userList.forEach(System.out::println);
}/*2、名字中包含雨年并且龄大于等于20且小于等于40并且email不为空name like '%雨%' and age between 20 and 40 and email is not null*/
@Test
public void selectByWrapper2() {QueryWrapper<User> queryWrapper = new QueryWrapper<>();//等同于//QueryWrapper<User> query = Wrappers.<User>query();queryWrapper.like("name","雨").between("age",20,40).isNotNull("email");//注意:此处的键名依旧为数据库中的列名List<User> userList = userMapper.selectList(queryWrapper);userList.forEach(System.out::println);
}/*3、名字为王姓或者年龄大于等于25,按照年龄降序排列,年龄相同按照id升序排列name like '王%' or age>=25 order by age desc,id asc*/
@Test
public void selectByWrapper3() {QueryWrapper<User> queryWrapper = new QueryWrapper<>();//等同于//QueryWrapper<User> query = Wrappers.<User>query();queryWrapper.likeRight("name","王").or().ge("age",25).orderByDesc("age").orderByAsc("id");//注意:此处的键名依旧为数据库中的列名List<User> userList = userMapper.selectList(queryWrapper);userList.forEach(System.out::println);
}/*4、创建日期为2019年2月14日并且直属上级为名字为王姓date_format(create_time,'%Y-%m-%d')='2019-02-14' and manager_id in (select id from user where name like '王%')*/
@Test
public void selectByWrapper4() {QueryWrapper<User> queryWrapper = new QueryWrapper<>();//等同于//QueryWrapper<User> query = Wrappers.<User>query();queryWrapper.apply("date_format(create_time,'%Y-%m-%d')={0}","2019-02-14").inSql("manager_id","select id from user where name like '王%'");//注意:此处的键名依旧为数据库中的列名List<User> userList = userMapper.selectList(queryWrapper);userList.forEach(System.out::println);
}
// 注意:以上方法查询为推荐查询,不建议写如下方式查询:会导致sql注入风险
//queryWrapper.apply("date_format(create_time,'%Y-%m-%d')="2019-02-14")/*5、名字为王姓并且(年龄小于40或邮箱不为空)name like '王%' and (age<40 or email is not null)*/
@Test
public void selectByWrapper5() {QueryWrapper<User> queryWrapper = new QueryWrapper<>();//等同于//QueryWrapper<User> query = Wrappers.<User>query();queryWrapper.likeRight("name","王").and(wq->wq.lt("age",40).or().isNotNull("email"));//注意:此处的键名依旧为数据库中的列名List<User> userList = userMapper.selectList(queryWrapper);userList.forEach(System.out::println);
}/*6、名字为王姓或者(年龄小于40并且年龄大于20并且邮箱不为空)name like '王%' or (age<40 and age>20 and email is not null)*/
@Test
public void selectByWrapper6() {QueryWrapper<User> queryWrapper = new QueryWrapper<>();//等同于//QueryWrapper<User> query = Wrappers.<User>query();queryWrapper.likeRight("name","王").or(wq->wq.lt("age",40).gt("age",20).isNotNull("email"));//注意:此处的键名依旧为数据库中的列名List<User> userList = userMapper.selectList(queryWrapper);userList.forEach(System.out::println);
}/*7、(年龄小于40或邮箱不为空)并且名字为王姓(age<40 or email is not null) and name like '王%'*/
@Test
public void selectByWrapper7() {QueryWrapper<User> queryWrapper = new QueryWrapper<>();//等同于//QueryWrapper<User> query = Wrappers.<User>query();queryWrapper.nested(wq->wq.lt("age",40).or().isNotNull("email")).likeRight("name","王");//注意:此处的键名依旧为数据库中的列名List<User> userList = userMapper.selectList(queryWrapper);userList.forEach(System.out::println);
}/*8、年龄为30、31、34、35age in (30、31、34、35)*/
@Test
public void selectByWrapper8() {QueryWrapper<User> queryWrapper = new QueryWrapper<>();//等同于//QueryWrapper<User> query = Wrappers.<User>query();queryWrapper.in("age",Arrays.asList(30,31,34,35));//注意:此处的键名依旧为数据库中的列名List<User> userList = userMapper.selectList(queryWrapper);userList.forEach(System.out::println);
}
/*** 无视优化规则直接拼接到 sql 的最后(有sql注入的风险,请谨慎使用)* <p>例: last("limit 1")</p>* <p>注意只能调用一次,多次调用以最后一次为准</p>** @param condition 执行条件* @param lastSql sql语句* @return children*/
Children last(boolean condition, String lastSql);/*** 9. 只返回满足条件的一条语句即可* limit 1*/
@Test
public void selectWrapper7(){QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.in("age", Arrays.asList(30,31,34,35)).last("limit 1");List<User> userList = userMapper.selectList(queryWrapper);userList.forEach(System.out::println);
}
- last 有SQL注入的风险!!!
select中字段不全出现的处理方法
并非每次查询都要查询所有字段,测试可用如下方法查询
/*10、名字中包含雨并且年龄小于40(需求1加强版)第一种情况select id,namefrom userwhere name like '%雨%' and age<40
*/
@Test
public void selectByWrapperSuper() {QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.select("id","name").like("name","雨").lt("age",40);List<User> userList =userMapper.selectList(queryWrapper);userList.forEach(System.out::println);
}/*第二种情况select id,name,age,emailfrom userwhere name like '%雨%' and age<40
*/
@Test
public void selectByWrapperSuper2() {QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.like("name","雨").lt("age",40).select(User.class,info->!info.getColumn().equals("create_time")&&!info.getColumn().equals("manager_id"));List<User> userList =userMapper.selectList(queryWrapper);userList.forEach(System.out::println);
}
条件构造器中condition作用
@Test
public void testCondition() {String name="王";String email="";condition(name,email);
}public void condition(String name,String email){QueryWrapper<User> queryWrapper = new QueryWrapper<>();
// if(StringUtils.isNotEmpty(name)){
// queryWrapper.like("name",name);
// }
// if(StringUtils.isNotEmpty(email)){
// queryWrapper.like("email",email);
// }// 以上代码过于臃肿,可采用如下代码代替queryWrapper.like(StringUtils.isNotEmpty(name),"name",name).like(StringUtils.isNotEmpty(email),"email",email);List<User> userList =userMapper.selectList(queryWrapper);userList.forEach(System.out::println);
}
创建条件构造器时传入实体对象
如果想通过对象中某些属性进行模糊查询,我们可以在跟数据库表对应的实体类中相应的属性标注注解即可。
比如我们想通过姓名进行模糊查询用户列表。
@TableField(condition = SqlCondition.LIKE)
private String name;
@Test
public void selectWrapper10(){User user = new User();user.setName("红");user.setAge(32);QueryWrapper<User> queryWrapper = new QueryWrapper<>(user);List<User> userList = userMapper.selectList(queryWrapper);userList.forEach(System.out::println);
}
- 当然可以通过源码对照 SqlCondition 对应的作用
- 如果源码中没有找到想要的功能,还可以自定义,如图
条件构造器中allEq用法
/*** allEq*/
@Test
public void selectList_allEq() {QueryWrapper<User> query = new QueryWrapper<>();Map<String, Object> params = new HashMap<>();params.put("name", "刘明强");params.put("age", 31);params.put("email", null);
// query.allEq(params,false);//第二个参数表示如果列值为null是否按IS NULL查询,false则忽略null列的查询query.allEq((k, v) -> !k.equals("name"), params, false);//第一个参数是过滤器List<User> list = userMapper.selectList(query);list.forEach(System.out::println);
}
其他以条件构造器为参数的查询方法
/*** selectMaps的应用场景1:当表中的列特别多,但实际只需要几个列时,这时返回一个实体类有些不必要*/
@Test
public void selectMaps() {QueryWrapper<User> query = new QueryWrapper<>();query.like("name", "雨").lt("age", 40).select("name", "age");List<Map<String, Object>> maps = userMapper.selectMaps(query);maps.forEach(System.out::println);
}/*** selectMaps的应用场景2:查询统计结果* 按照直属上级分组,查询每组的平均年龄、最大年龄、最小年龄,并且只取年龄总和小于100的组* SELECT AVG(age) avg_age,MIN(age) min_age,MAX(age) max_age* FROM `user`* GROUP BY `manager_id`* HAVING SUM(age)<100;*/
@Test
public void selectMaps2() {QueryWrapper<User> query = new QueryWrapper<>();query.select("AVG(age) avg_age", "MIN(age) min_age", "MAX(age) max_age").groupBy("manager_id").having("SUM(age)<{0}", 100);List<Map<String, Object>> maps = userMapper.selectMaps(query);maps.forEach(System.out::println);
}/*** selectObjs只返回第一列,其它列被遗弃* 应用场景:只需返回一列的时候*/
@Test
public void selectObjs() {QueryWrapper<User> query = new QueryWrapper<>();query.like("name", "雨").lt("age", 40).select("name", "age");List<Object> list = userMapper.selectObjs(query);list.forEach(System.out::println);
}/*** 返回总记录数*/
@Test
public void selectCount() {QueryWrapper<User> query = new QueryWrapper<>();query.like("name", "雨").lt("age", 40);Integer count = userMapper.selectCount(query);System.out.println("总记录数:" + count);
}/*** selectOne:只能查询一条记录,查询到多条会报错*/
@Test
public void selectOne() {QueryWrapper<User> query = new QueryWrapper<>();query.like("name", "刘红雨").lt("age", 40);User user = userMapper.selectOne(query);System.out.println(user);
}
Lambda条件构造器
/*** lambda条件构造器*/
@Test
public void lambdaQueryWrapper1() {
// LambdaQueryWrapper<User> lambdaQ = new QueryWrapper<User>().lambda();
// LambdaQueryWrapper<User> lambdaQ = new LambdaQueryWrapper<>();LambdaQueryWrapper<User> lambdaQ = Wrappers.<User>lambdaQuery();lambdaQ.like(User::getName, "雨").lt(User::getAge, 40);List<User> list = userMapper.selectList(lambdaQ);list.forEach(System.out::println);
}/*** lambda条件构造器:防误写(例如列名"name"可能被误写)*/
@Test
public void lambdaQueryWrapper2() {LambdaQueryWrapper<User> query = new LambdaQueryWrapper<>();query.likeRight(User::getName, "王").and(q -> q.lt(User::getAge, 40).or().isNotNull(User::getEmail));List<User> list = userMapper.selectList(query);list.forEach(System.out::println);
}/*** 链式lambda条件构造器:更优雅的书写方式*/
@Test
public void lambdaQueryChainWrapper() {List<User> list = new LambdaQueryChainWrapper<User>(userMapper).likeRight(User::getName, "王").and(q -> q.lt(User::getAge, 40).or().isNotNull(User::getEmail)).list();list.forEach(System.out::println);
}
使用条件构造器的自定义SQL
(要求版本大于等于3.0.7)
在UserMapper中定于接口方法(采用注解的方式)
@Select("select * from user ${ew.customSqlSegment}")
List<User> selectAll(@Param(Constants.WRAPPER)Wrapper<User> wrapper);
在测试中使用自定义方法
@Test
public void selectMy() {
// LambdaQueryWrapper<User> lambda = new QueryWrapper<User>().lambda();
// LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();LambdaQueryWrapper<User> lambdaQuery = Wrappers.<User>lambdaQuery();lambdaQuery.like(User::getName,"雨").lt(User::getAge,40);//where name like '%雨%'List<User> userList = userMapper.selectAll(lambdaQuery);//此处使用自定义接口方法userList.forEach(System.out::println);}
如果不想把自定义sql写在接口中,例如写在xml中,还可以采用如下方法:
第一步:在yml配置文件中配置接口对应的xml路径
Mybatis-plus:mapper-locations: classpath:mp/mapper/*.xml
在配置路径下新建UserMapper.xml文件,同时去除接口中的注解sql
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.neo.mapper.UserMapper" ><select id="selectAll" resultType="com.neo.model.User">select * from user ${ew.customSqlSegment}</select>
</mapper>
mybatis中提供分页方法,但是该分页是逻辑分页,而非物理分页。
MP分页插件实现物理分页
新建配置包(com.neo.configuration)并新建配置分页类MybatisPlusConfig:
@Configuration
public class MybatisPlusConfig {@Beanpublic PaginationInterceptor paginationInterceptor() {return new PaginationInterceptor();}
}
测试(selectPage)
@Test
public void selectPage() {QueryWrapper<User> queryWrapper = new QueryWrapper<User>();queryWrapper.ge("age", 26);Page<User> page = new Page<>(1, 2);IPage<User> iPage = userMapper.selectPage(page, queryWrapper);System.out.println("总页数:" + iPage.getPages());System.out.println("总记录数:" + iPage.getTotal());List<User> userlist = iPage.getRecords();userlist.forEach(System.out::println);
}运行日志:DEBUG==> Preparing: SELECT COUNT(1) FROM user WHERE age >= ?
DEBUG==> Parameters: 26(Integer)
TRACE<== Columns: COUNT(1)
TRACE<== Row: 7
DEBUG==> Preparing: SELECT id,name,age,email,manager_id,create_time FROM user WHERE age >= ? LIMIT ?,?
DEBUG==> Parameters: 26(Integer), 0(Long), 2(Long)
TRACE<== Columns: id, name, age, email, manager_id, create_time
TRACE<== Row: 1087982257332887553, 大boss, 40, boss@baomidou.com, null, 2019-01-11 14:20:20
TRACE<== Row: 1088250446457389058, 李艺伟, 28, lyw@baomidou.com, 1088248166370832385, 2019-02-14 08:31:16
DEBUG<== Total: 2
总页数:4
总记录数:7
User(id=1087982257332887553, name=大boss, age=40, email=boss@baomidou.com, managerId=null, createTime=2019-01-11T14:20:20)
User(id=1088250446457389058, name=李艺伟, age=28, email=lyw@baomidou.com, managerId=1088248166370832385, createTime=2019-02-14T08:31:16)
测试(selectMapsPage)
@Test
public void selectPage() {QueryWrapper<User> queryWrapper = new QueryWrapper<User>();
// queryWrapper.ge("age",26);Page<User> page = new Page<>(1, 2);
// IPage<User> iPage = userMapper.selectPage(page, queryWrapper);
// System.out.println("总页数:"+ iPage.getPages());
// System.out.println("总记录数:"+ iPage.getTotal());
// List<User> userlist = iPage.getRecords();IPage<Map<String, Object>> iPage = userMapper.selectMapsPage(page, queryWrapper);System.out.println("总页数:"+ iPage.getPages());System.out.println("总记录数:"+ iPage.getTotal());List<Map<String, Object>> userlist = iPage.getRecords();userlist.forEach(System.out::println);
}DEBUG==> Preparing: SELECT COUNT(1) FROM user
DEBUG==> Parameters:
TRACE<== Columns: COUNT(1)
TRACE<== Row: 13
DEBUG==> Preparing: SELECT id,name,age,email,manager_id,create_time FROM user LIMIT ?,?
DEBUG==> Parameters: 0(Long), 2(Long)
TRACE<== Columns: id, name, age, email, manager_id, create_time
TRACE<== Row: 1087982257332887553, 大boss, 40, boss@baomidou.com, null, 2019-01-11 14:20:20
TRACE<== Row: 1088248166370832385, 王天风, 25, wtf@baomidou.com, 1087982257332887553, 2019-02-05 11:12:22
DEBUG<== Total: 2
总页数:7
总记录数:13
{createTime=2019-01-11 14:20:20.0, name=大boss, id=1087982257332887553, age=40, email=boss@baomidou.com}
{createTime=2019-02-05 11:12:22.0, name=王天风, id=1088248166370832385, managerId=1087982257332887553, age=25, email=wtf@baomidou.com}
从以上两个例子看以看出每个是执行了两条sql语句,如果只想要查询结果,不想要查询总数,只需要将page的第三个参数变为false,即可:
Page<User> page = new Page<>(1, 2,false);
- 当我们在做多表联查时,就不能使用如上方式查询了,此时可以在xml文件中自定义sql。
根据id更新
@Test
public void updateById(){User user= new User();user.setId(1088248166370832385L);user.setAge(26);user.setEmail("wtf2@baomidou.com");int rows = userMapper.updateById(user);System.out.println("影响记录数:"+ rows);
}运行日志:DEBUG==> Preparing: UPDATE user SET age=?, email=? WHERE id=?
DEBUG==> Parameters: 26(Integer), wtf2@baomidou.com(String), 1088248166370832385(Long)
DEBUG<== Updates: 1
影响记录数:1
以条件构造器作为参数的更新方法
@Test
public void updateByWrapper(){UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();updateWrapper.eq("name","李艺伟").eq("age",28);User user = new User();user.setEmail("lyw2020@baomidou.com");user.setAge(29);int rows = userMapper.update(user, updateWrapper);System.out.println("影响行数:"+rows);
}运行日志:
DEBUG==> Preparing: UPDATE user SET age=?, email=? WHERE name = ? AND age = ?
DEBUG==> Parameters: 29(Integer), lyw2020@baomidou.com(String), 李艺伟(String), 28(Integer)
DEBUG<== Updates: 1
影响行数:1
条件构造器中set方法使用
(只修改少量字段时)
@Test
public void updateByWrapper(){UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();//通过条件构造器的链式编程设置更新信息updateWrapper.eq("name","李艺伟").eq("age",29).set("email","liw888@qq.com");// User user = new User();int rows = userMapper.update(null, updateWrapper);System.out.println("影响行数:"+rows);
}
lambda条件构造器更新
@Test
public void updateByWrapperLambda(){LambdaUpdateWrapper<User> lambdaUpdate = Wrappers.<User>lambdaUpdate();lambdaUpdate.eq(User::getName,"李艺伟").eq(User::getAge,29).set(User::getAge,31);int rows = userMapper.update(null, lambdaUpdate);System.out.println("影响行数:"+rows);
}
根据id删除的方法
@Test
public void deleteById() {int rows= userMapper.deleteById(1223976086888599553L);System.out.println("影响行数:"+rows);
}
根据id批量删除
@Test
public void deleteBatchIds() {int rows = userMapper.deleteBatchIds(Arrays.asList(1223973741031141377L,1223972327026405378L,1223970002606067714L));System.out.println("影响行数:"+rows);
}
其他普通删除方法
@Test
public void deleteByMap() {Map<String,Object> columnMap= new HashMap<>();columnMap.put("name","向后");columnMap.put("age","31");int rows = userMapper.deleteByMap(columnMap);System.out.println("影响行数:"+rows);
}
以条件构造器为参数的删除方法
AR模式(Active Record)
直接通过实体类完成对数据的增删改查。
实体类继承Model类
@Data
@EqualsAndHashCode(callSuper = false)
public class User extends Model<User> {private Long id;@TableField(condition = SqlCondition.LIKE)private String name;private Integer age;private String email;private Long managerId;private LocalDateTime createTime;
}
Model类中封装了很多增删改查方法,不用使用UserMapper即可完成对数据的增删改查。
查询所有用户信息
@Test
public void test(){User user = new User();user.selectAll().forEach(System.out::println);
}
主键策略
MyBatisPlus的主键策略封装在IdType
枚举类中。
@Getter
public enum IdType {/*** 数据库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);private final int key;IdType(int key) {this.key = key;}
}
在实体类中对应数据库中的主键id属性上标注注解TableId(type='xxx')
即可完成主键配置。
@TableId(type = IdType.AUTO)
private Long id;
这种配置方式的主键策略只能在该表中生效,但是其他表还需要进行配置,为了避免冗余,麻烦,MybatisPlus提供了全局配置,在配置文件中配置主键策略即可实现。
mybatis-plus:mapper-locations: mapper/*.xmlglobal-config:db-config:id-type: auto
如果全局策略和局部策略全都设置,局部策略优先。
基本配置
mybatis-plus:mapper-locations: mapper/*.xmlglobal-config:db-config:# 主键策略id-type: auto# 表名前缀table-prefix: t# 表名是否使用下划线间隔,默认:是table-underline: true# 添加mybatis配置文件路径config-location: mybatis-config.xml# 配置实体类包地址type-aliases-package: org.ywb.demo.pojo# 驼峰转下划线configuration:map-underscore-to-camel-case: true
- config-location & configuration 不能同时出现,否则报错。
通用Service
定义接口继承IService
public interface UserService extends IService<User>{}
定义接口的实现类
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService{}
MyBatis-Plus - 快速入门相关推荐
- MyBatis之快速入门
MyBatis之快速入门 2017/9/30 首先我要明确告诉大家的是MyBatis是一个java持久层框架,以前我们都是用jdbc来将我们的java程序与数据库相连接,而MyBatis是对jdbc的 ...
- java day53【 Mybatis框架概述 、 Mybatis 框架快速入门、自定义 Mybatis 框架 】
第1章 框架概述 1.1 什么是框架 1.1.1 什么是框架 框架(Framework)是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法;另一种 定义认为,框架是可被应用开发者定 ...
- MyBatis框架快速入门
MyBatis框架快速入门 入门案例 创建一个关于Mybatis项目 首先创建一个空项目,然后新建一个moudle,选择quickstart,接下来把模块放到空项目之下.即可 实现mybatis查询数 ...
- MyBatis 01 快速入门
MyBatis 01 快速入门 文章目录 MyBatis 01 快速入门 一.学习目标 二.为什么需要框架技术 三.框架技术介绍 四.主流框架介绍 五.持久化与ORM 六.MyBatis简介 七.搭建 ...
- Mybatis(day1)快速入门
框架(Framework)是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法:另一种定义认为,框架是可被应用开发者定制的应用骨架.前者是从应用方面而后者是从目的方面给出的定义. 简 ...
- mybatis的快速入门
说明: 在这个部分,会写个简单的入门案例. 然后,会重新写一个,更加严格的程序案例. 一:案例一 1.最终的目录结构 2.新建一个普通的Java项目,并新建lib 在项目名上右键,不是src. 3.导 ...
- 第一:Java+MyBatis(快速入门)
MyBatis 简介 MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为 ...
- springboot 整合mybatis_SpringBoot整合MyBatis框架快速入门
MyBatis概述: mybatis是一个优秀的基于java的持久层框架,它内部封装了jdbc,使开发者只需要关注sql语句本身,而不需要花费精力去处理加载驱动.创建连接.创建statemenet等繁 ...
- MyBatis:快速入门代码实例(maven代码版)
文章目录 1. MyBatis实例 1.1 添加Mybatis依赖 1.2 创建MyBatis配置文件 1.3.创建po类 1.4.创建映射文件 #{}: 表示sql参数,一个占位符. 1.5.测试 ...
- MyBatis从入门到精通(一)—MyBatis基础知识和快速入门
Mybatis简介 原始jdbc操作(查询数据) Connection connection = null;PreparedStatement preparedStatement = null;Res ...
最新文章
- AS3.0(3)-函数;类;对象
- android自定义WaveView水波纹控件
- hdu_1233(最小生成树)
- POJ 1182 食物链,并查集的拓展
- 倒叙输出 php,php foreach正序倒序输出示例代码
- Java 抽象类、接口
- idea install 失败_idea maven install 卡住,无报错排查。
- windows安装ruby on rails
- (C语言)素数是指大于1,且只能被1和它自身整除的正整数。现给定一个范围,请输出在此范围中素数的个数。
- html5 svg编辑器,HTML5 之 SVG
- SQLserver基础语句大全
- php?what=chinese,推荐4-ChineseUtil v1.1.2 发布,PHP 中文工具包
- jieba / hanlp / ltp / standforCorenlp 分词器对比
- 计算机编程语言排行榜—TIOBE世界编程语言排行榜(2021年10月份最新版)
- 你的企业如何才能留住员工?
- 老板最“丧心病狂”的11个行为艺术
- vscode 连接ubuntu显示“试图写入的管道不存在”
- lightoj1219Mafia
- 发那科机器人请关闭电源_FANUC机器人常见错误恢复步骤,你真的都会吗?
- jar和war的区别
热门文章
- 中国木质家具行业营销模式与品牌竞争格局展望报告2022版
- 性能测试工具-ab介绍
- Elasticsearch关联关系
- 使用NPOI实现在Excel第一行插入文字
- autojump env: python: No such file or directory
- AntDesign 的 Table 组件的 expandedRowRender 属性失效的问题
- <学习笔记>从零开始自学Python-之-web应用框架Django( 十)通用模板
- Android APP性能监测工具
- “R语言机器学习与大数据可视化”暨“Python文本挖掘与自然语言处理”核心技术高级研修班的通知
- java注解定义常量_java自定义注解