1,mybatis-plus的使用
1,创建数据库
create table users(
id int primary key auto_increment,
name varchar(30),
age int,
sex char(1),
birthday date
);
2,创建boot项目引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
3,实现逆向工程
1,用插件MyBatisCodeHelperPro实现逆向工程
2, 不用插件实现逆向工程
1,引入依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.31</version>
</dependency>
2,测试类执行程序
@SpringBootTest
public class MpDemoTest {
@Test
void test(){
FastAutoGenerator.create("jdbc:mysql://localhost:3306/db_mp?serverTimezone=UTC", "root", "root")
.globalConfig(builder -> {
//设置作者 -- 可选的
builder.author("powernode")
//用到swagger模式则开启
//.enableSwagger()
//覆盖已生成文件
.fileOverride()
//指定存放生成的Mapper接口、Service、Controller、实体类的磁盘目录
.outputDir("D://mmy-mybatis-plus");
})
.packageConfig(builder -> {
//指定基包
builder.parent("com").moduleName("pn")
//指定存放生成的sql映射文件的磁盘目录
.pathInfo(Collections.singletonMap(OutputFile.mapperXml,"D://mmy-mybatis-plus"));
})
.strategyConfig(builder -> {
//指定逆向工程的表名
builder.addInclude("users")
//如果表有前缀,用于过滤表的前缀
.addTablePrefix("t_", "tab_");
})
//使用Freemarker引擎模板
.templateEngine(new FreemarkerTemplateEngine())
.execute();
}
}
3,逆向工程内容拷贝到项目
3,逆向工程产生的各类
4, 实体类
//当表名和实体类类名不一致时,需加上@TableName指定表名,一致则可忽略
//@TableName(value = "users")
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Users implements Serializable {
private static final long serialVersionUID = 1L;
//@TableId用于标注主键列映射的属性,value="id"指定主键列名,type=IdType.AUTO表示主键自增
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
//当列名和属性名不一致时,需加上@TableField指定列名,一致则可忽略
//@TableField(value = "name")
private String name;
private Integer age;
private String sex;
private LocalDate birthday;
//当实体类定义的属性在表中没有对应的列时,必须标注@TableField(exist=false)
//@TableField(exist = false)
//private String hello;
}
5,mapper接口
//继承了mybatis-plus提供的BaseMapper<T>接口
public interface UsersMapper extends BaseMapper<Users> {
}
6,service接口
//继承了mybatis-plus提供的IService<T>接口
public interface IUsersService extends IService<Users> {
}
7,serviceimpl实现类
//继承了mybatis-plus为IService<T>接口提供的实现类ServiceImpl<M extends BaseMapper<T>, T>
@Service
public class UsersServiceImpl extends ServiceImpl<UsersMapper, Users>
implements IUsersService {
}
8,mapper映射文件
<?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.mmy.mapper.UsersMapper">
</mapper>
4,搭建mybatis-plus环境
1,配置文件
#------------------------mp的配置-----------------------
#数据源的配置
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/db_mp?serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=root
#指定sql映射文件的位置
mybatis-plus.mapper-locations=classpath:mapper/*.xml
#开启日志功能
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
#开启驼峰命名规则
mybatis-plus.configuration.map-underscore-to-camel-case=true
#指定实体类所在包,为所有实体类起别名
mybatis-plus.type-aliases-package=com.pn.entity
2,主程序类
//给扫描器指定Mapper接口所在的包
@MapperScan(basePackages = "com.mmy.mapper")
@SpringBootApplication
public class SbmpDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SbmpDemoApplication.class, args);
}
}
5,基础CRUD操作
提前注入StudentService
1,添加单条数据
//添加学生 -- 添加单条记录
@Test
void addTest2(){
Student student = new Student(null, "李四", null,22, new Date());
studentService.save(student);
}
2,批量添加数据
//批量添加
@Test
void addTest3(){
List<Student> studentList = new ArrayList<>();
studentList.add(new Student(null, "王五", null,23, new Date()));
studentList.add(new Student(null, "赵六", null,24, new Date()));
studentList.add(new Student(null, "孙七", null,25, new Date()));
studentService.saveBatch(studentList);
}
3,根据主键删除单条数据
//根据主键删除单条记录
@Test
void deleTest1(){
studentService.removeById(5);
}
4,根据主键批量删除数据
//根据主键批量删除
@Test
void deleteTest2(){
List<Integer> idList = new ArrayList<>();
idList.add(3);
idList.add(4);
studentService.removeByIds(idList);
}
5,根据主键修改数据
//根据主键修改
@Test
void updateTest(){
Student student = new Student();
student.setId(2);
student.setName("王五");
student.setAge(23);
studentService.updateById(student);
}
6,根据主键查询单条数据
//根据主键查询单条记录
@Test
void queryTest1(){
Student student = studentService.getById(2);
System.out.println(student);
}
7,根据主键批量查询数据
//根据主键批量查询
@Test
void queryTest2(){
List<Integer> idList = new ArrayList<>();
idList.add(1);
idList.add(2);
List<Student> studentList = studentService.listByIds(idList);
for (Student student : studentList) {
System.out.println(student);
}
}
8,查询全部数据
//全查
@Test
void queryTest3(){
List<Student> studentList = studentService.list();
for (Student student : studentList) {
System.out.println(student);
}
}
6,条件查询
Wrapper<T>对象 -- 条件对象 -- 用于封装底层执行的sql语句的条件的。
Wrapper<T>是个抽象类,常用子类:
1,QueryWrapper<T>
1,常用的条件方法 -- 不同的方法表示给条件对象添加不同的条件:
eq(String column,Object value) -- where 列=值 的条件 ne(String column,Object value) -- where 列!=值 的条件 gt(String column,Object value) -- where 列>值 的条件 ge(String column,Object value) -- where 列>=值 的条件 lt(String column,Object value) -- where 列<值 的条件 le(String column,Object value) -- where 列<=值 的条件 between(String column,Object value1,Object value2) -- where 列 between v1 and v2 notBetween(String column,Object value1,Object value2) -- where 列 not between v1 and v2 in(String column,Object...values) -- where 列 in(v1,v2,v3...) notIn(String column,Object...values) -- where 列 not in(v1,v2,v3...) like(String column,Object value) --- where 列 like xxx notLike(String column,Object value) --- where 列 not like xxx likeRight(String column,Object value) --- where 列 like 'value%' likeLeft(String column,Object value) --- where 列 like '%value' isNull(String column) --- where 列 is null isNotNull(String column) --- where 列 is not null orderByAsc(String...columns) -- order by 列1,列2... asc; orderByDesc(String...columns) -- order by 列1,列2... desc; groupBy(String...columns) -- group by 列1,列2...
2, 所有条件方法的重载的方法:
所有条件方法的重载的方法: eq(String column,Object value) -- 直接转成条件:where 列=值 eq(boolean condition, String column,Object value) -- 如果参数一布尔表达式为false,则不上条件:where 列=值;如果参数一布尔表达式为true,则上条件:where 列=值;
2,LambdaQueryWrapper<T>
1,常用的条件方法
LambdaQueryWrapper和QueryWrapper具有的条件方法一模一样,区别是QueryWrapper的条件方法的列名是 字符串形式,而LambdaQueryWrapper的条件方法的列名是Lambda表达式:实体类类名::列对应的属性的get方法名; 优点: 在给QueryWrapper的条件方法指定字符串的列名的时候,因为没有提示出错的几率比较大;而在给LambdaQueryWrapper 的条件方法指定Lambda表达式的列名的时候,ide是由提示并代码补全的,几乎不会出错且能提高编码效率。
3,LambdaQueryWrapper和QueryWrapper的选择:
大部分情况下都是使用LambdaQueryWrapper,当条件方法参数列名只能使用字符串形式的时候就使用QueryWrapper。 例如,查询年薪大于50000的员工 select * from 员工表 where (月薪+奖金)*12>50000; 表达式(月薪+奖金)*12肯定不能使用Lambda表达式表示,只能使用字符串表示。
3,条件查询的使用
1.查询单行 T | getOne(Wrapper<T>) 2.查询多行 List<T> | list(Wrapper<T>)
1,查询年龄大于20且性别是女的学生
@Test
void test1(){
//创建条件对象
QueryWrapper<Student> wrapper = new QueryWrapper<>();
//添加条件
wrapper.gt("age", 20);
wrapper.eq("sex", "女");
-------------------------------
//执行查询方法
Student student = studentService.getOne(
new QueryWrapper<Student>()
.gt("age", 20)
.eq("sex", "女")
);
-------------------------------------------
Student student = studentService.getOne(
new LambdaQueryWrapper<Student>()
.gt(Student::getAge, 20)
.eq(Student::getSex, "女")
);
System.out.println(student);
}
2,查询性别是女且都姓王的学生
@Test
void test2(){
List<Student> studentList = studentService.list(
new QueryWrapper<Student>()
.eq("sex", "女")
.likeRight("name", "王")
);
--------------------------------------------------------
List<Student> studentList = studentService.list(
new LambdaQueryWrapper<Student>()
.eq(Student::getSex, "女")
.likeRight(Student::getName, "王")
);
for (Student student : studentList) {
System.out.println(student);
}
}
3,给定一个学生年龄,如果年龄大于22,则查询所有性别为男的学生,反之查询所有性别为女的学生
@Test
void test3(){
int age = 23;
List<Student> studentList = studentService.list(
new QueryWrapper<Student>()
.eq(age > 22, "sex", "男")
.eq(age <= 22, "sex", "女")
);
for (Student student : studentList) {
System.out.println(student);
}
}
7,分页查询
1,配置分页插件配置类
@Configuration
public class MpConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
//创建插件容器
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
//向插件容器添加分页插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
2,测试类
@SpringBootTest
public class MpPageTest {
//注入StudentService
@Autowired
private StudentService studentService;
/*
分页查询方法:
1.Page | page(Page)
参数是封装了查询页码和每页行数的Page对象,返回值是封装了所有分页信息的Page。
表示全查并分页。
2.Page | page(Page, Wrapper)
参数一是封装了查询页码和每页行数的Page对象,参数二是条件对象,返回值也是封装
了所有分页信息的Page。
表示条件查询并分页。
Page类中定义有所有分页信息的成员属性。
*/
@Test
void test1(){
/*
查询所有学生并分页,一页三行,查询第二页
*/
Page<Student> page = new Page<>(2, 3);
//SELECT id,name,sex,age,birthday FROM student LIMIT ?,?
page = studentService.page(page);
long total = page.getTotal();//总行数
long pages = page.getPages();//总页数
long current = page.getCurrent();//页码
long size = page.getSize();//每页行数
List<Student> studentList = page.getRecords();//当前页数据
for (Student student : studentList) {
System.out.println(student);
}
}
@Test
void test2(){
/*
查询所有男生并分页,每页2行,查询第二页
*/
Page<Student> page = new Page<>(2, 2);
//SELECT id,name,sex,age,birthday FROM student WHERE (sex = ?) LIMIT ?,?
page = studentService.page(page,
new LambdaQueryWrapper<Student>()
.eq(Student::getSex, "男")
);
long total = page.getTotal();//总行数
long pages = page.getPages();//总页数
long current = page.getCurrent();//页码
long size = page.getSize();//每页行数
List<Student> studentList = page.getRecords();//当前页数据
for (Student student : studentList) {
System.out.println(student);
}
}
}