MyBaitsPlus_CRUD 以及条件构造器的使用
- 使用断点查看当前源代码中的sql语句 MyBatisPlus是如何为我们创建sql语句的
MyBatisPlus在启动时就会将当前继承了BaseMapper
接口的dao接口中的方法所需要用到的SQL全部创建好,便于我们在操作使用
保存在Configuration 中的MappedStatements (这个对象会存在多个,每一个对象对应一条sql语句)
条件构造器 Wrapper
简介
条件构造器(Wrapper)的作用:
MP提供的通用Mapper中,删改查(没有insert)的方法通常会需要我们传入一个条件构造器,用来生成最后执行的SQL语句。
比如List selectList( Wrapper wrapper)方法,当我们传入null时,默认生成的语句就是select * from xxx,这条语句没有查询条件,排序,子查询,模糊查询并且固定查询所有的字段,如果我们需要一些复杂的查询条件,就可以使用条件构造器来指定我们的SQL需要拼接那些查询条件。
Wrapper : 条件构造抽象类,最顶端父类
AbstractWrapper : 用于查询条件封装,生成 sql 的 where 条件
QueryWrapper : Entity 对象封装操作类,不是用lambda语法
UpdateWrapper : Update 条件封装,用于Entity对象更新操作
AbstractLambdaWrapper :
Lambda 语法使用 Wrapper统一处理解析 lambda 获取 column。
LambdaQueryWrapper :
看名称也能明白就是用于Lambda语法使用的查询Wrapper
LambdaUpdateWrapper :
Lambda 更新封装Wrapper
实际使用中,
如果要使用MP的查询、删除方法,通常使用QueryWrapper作为条件的封装实现类;因为它的功能比较强大。
如果要使用MP的修改方法,通常使用UpdateWrapper作为条件的封装实现类,因为它提供了一些独有的方法,适用于update操作,比如set和setSql方法;
其实QueryWrapper和UpdateWrapper的大多数方法都是继承自AbstractWrapper,两者在大部分条件下都是可以互相替换的。
QueryWrapper
-
eq 等于
-
ne 不等于
案例:
//eq:等于 ne:不等于
//创建查询的条件构造器
QueryWrapper<Student> studentQueryWrapper = new QueryWrapper<>();
//获取当前年龄等于2的数据库对象
QueryWrapper<Student> age = studentQueryWrapper.eq("age", 21);
//调用baseMapper中的方法将当前的条件构造器传入
//因为查询的条件使多个所以使用selectList方法
List<Student> list = dao.selectList(age);
//获得到的对象就是age=2的对象
list.forEach(a-> System.out.println(a));
-
gt 大于
-
ge 大于等于
-
lt 小于
-
le 小于等于
//创建查询的条件构造器
QueryWrapper<Student> studentQueryWrapper = new QueryWrapper<>();
//将当前的构造器条件准备好
QueryWrapper<Student> age = studentQueryWrapper.le("age", 32);
//调用baseMapper中的方法将当前的条件构造器传入
//因为查询的条件使多个所以使用selectList方法
List<Student> list = dao.selectList(age);
//获得到的对象就是条件构造器指定的条件的对象
list.forEach(a-> System.out.println(a));
between
介于 值1和值2之间notBetween
不介于值1和值2之间
//创建查询的条件构造器
QueryWrapper<Student> studentQueryWrapper = new QueryWrapper<>();
//将当前的构造器条件准备好
QueryWrapper<Student> age = studentQueryWrapper.notBetween("age", 23,32);
//调用baseMapper中的方法将当前的条件构造器传入
//因为查询的条件使多个所以使用selectList方法
List<Student> list = dao.selectList(age);
//获得到的对象就是条件构造器指定的条件的对象
list.forEach(a-> System.out.println(a));
like
获取包含值的对象notlike
获取不包含值的对象likeLeft
获取对象中最后一个是值的对象likeRight
获取对象中最前一个是值的对象
//创建查询的条件构造器
QueryWrapper<Student> studentQueryWrapper = new QueryWrapper<>();
//将当前的构造器条件准备好
QueryWrapper<Student> age = studentQueryWrapper.likeRight("name", "尚");
//调用baseMapper中的方法将当前的条件构造器传入
//因为查询的条件使多个所以使用selectList方法
List<Student> list = dao.selectList(age);
//获得到的对象就是条件构造器指定的条件的对象
list.forEach(a-> System.out.println(a));
isNull
字段是nullisNotNull
字段 IS NOT NULL
//创建查询的条件构造器
QueryWrapper<Student> studentQueryWrapper = new QueryWrapper<>();
//将当前的构造器条件准备好
QueryWrapper<Student> age = studentQueryWrapper.isNotNull("age");
//调用baseMapper中的方法将当前的条件构造器传入
//因为查询的条件使多个所以使用selectList方法
List<Student> list = dao.selectList(age);
//获得到的对象就是条件构造器指定的条件的对象
list.forEach(a-> System.out.println(a));
in
字段 IN(v0,v1,v2) 给定多个条件,找符合条件的对象notInt
字段 (v0,v1,v2) 给定的条件 排除所有符合条件对象
//创建查询的条件构造器
QueryWrapper<Student> studentQueryWrapper = new QueryWrapper<>();
//将当前的构造器条件准备好
QueryWrapper<Student> age = studentQueryWrapper.notIn("age",51,23);
//调用baseMapper中的方法将当前的条件构造器传入
//因为查询的条件使多个所以使用selectList方法
List<Student> list = dao.selectList(age);
//获得到的对象就是条件构造器指定的条件的对象
list.forEach(a-> System.out.println(a));
-
inSQL
查询指定列的 数据 根据指定条件查询,通过sql命令来指定 -
notInSQL
查询指定列的数据 除了指定条件的, 通过sql命令来指定
//创建查询的条件构造器
QueryWrapper<Student> studentQueryWrapper = new QueryWrapper<>();
//将当前的构造器条件准备好
QueryWrapper<Student> age = studentQueryWrapper.inSql("age","select age from student where age < 24");
//调用baseMapper中的方法将当前的条件构造器传入
//因为查询的条件使多个所以使用selectList方法
List<Student> list = dao.selectList(age);
//获得到的对象就是条件构造器指定的条件的对象
list.forEach(a-> System.out.println(a));
or
或者and
和 不适用and 就是默认and
注意事项:
主动调用or表示紧接着下一个方法不是用and连接!(不调用or则默认为使用and连接)
//创建查询的条件构造器
QueryWrapper<Student> studentQueryWrapper = new QueryWrapper<>();
//将当前的构造器条件准备好 当前构造器含义是查询名字叫做王二狗或者年龄是23的数据库信息 二者唯一即可
QueryWrapper<Student> age = studentQueryWrapper.eq("name","王二狗").or().eq("age","23");
//调用baseMapper中的方法将当前的条件构造器传入
//因为查询的条件使多个所以使用selectList方法
List<Student> list = dao.selectList(age);
//获得到的对象就是条件构造器指定的条件的对象
list.forEach(a-> System.out.println(a));
//创建查询的条件构造器
QueryWrapper<Student> studentQueryWrapper = new QueryWrapper<>();
//将当前的构造器条件准备好 当前构造器含义是同时满足两个条件的数据会被查询出来
studentQueryWrapper.eq("salary","22");
studentQueryWrapper.eq("age","21");
//调用baseMapper中的方法将当前的条件构造器传入
//因为查询的条件使多个所以使用selectList方法
List<Student> list = dao.selectList(studentQueryWrapper);
//获得到的对象就是条件构造器指定的条件的对象
list.forEach(a-> System.out.println(a));
exits
如果条件为真则会执行主sql语句notexits
如果条件为假则会执行主sql语句
/创建查询的条件构造器
QueryWrapper<Student> studentQueryWrapper = new QueryWrapper<>();
//将当前的构造器条件准备好
QueryWrapper<Student> noExits = studentQueryWrapper.notExists("select id from student where salary >124");
List<Student> list2 = dao.selectList(noExits);
//获得到的对象就是条件构造器指定的条件的对象
list2.forEach(a -> System.out.println(a));
orderByAsc
升序排列orderByDes
降序排列
//创建查询的条件构造器
QueryWrapper<Student> studentQueryWrapper = new QueryWrapper<>();
//将当前的构造器条件准备好
studentQueryWrapper.orderByDesc("id");
List<Student> list2 = dao.selectList(studentQueryWrapper);
//获得到的对象就是条件构造器指定的条件的对象
list2.forEach(a -> System.out.println(a));
ActiveRecord 活动记录
Activce Record 是一种领域模型模式,特点是一个模型类对应关系型数据库中的一个表,而模型类的一个实例对应表中的一行记录
ActiceRecord 一直广受动态语言 PHP Ruby 的喜 爱,而Java作为准静态语言 对于ActiveRecord 往往只能感叹其优雅,所以MP也在AR道路上进行了一定的探索
开发步骤
- 首先需要当前的实体类对象继承一个类
Model
public class Student extends Model<Student> //泛型指定当前的实体类对象即可
- 重写当前类中的方法 指向当前实体类属性所对应的表中主键
protected Serializable pkVal() {
return id;
}
- 测试
注意:因为使用Spring集成开发MyBatisPlus 所以需要先使用工厂创建当前的DAO对象,然后才可以使用ActiveRecord 来操纵实体类对数据库进行CRUD
public void test(){
//创建spring 工厂对象 读取Spring的配置文件
ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
//创建实现BaseMapper 的接口对象
StudentMapper sm = ac.getBean("studentMapper", StudentMapper.class);
//创建一个继承了 Model 的实体类对象
Student st = new Student();
//通过Model中的方法来获取当前数据库中的对象
Student student = st.selectById(5);
//打印输出
System.out.println(student);
}
代码生成器
MyBatisPlus代码生成器: 实体类 (可以控制当前实体类是否支持AR ActiveRecord) Mapper接口(DAO接口) Mapper 映射文件 Service 层 Controller 层 等等
在MyBatis 中,建议数据库 表名 和数据库字段名 采用驼峰命名方式,如果采用下划线命名方式,最好在配置文件中开启全局下划线开关,如果表名字段方式不一致需要使用注解指定,我们最好保持一致 这样做的原因是为了避免在对应实体类产生时的性能损耗,这样字段不用做映射就能直接和实体类对应,当然如果项目中不考虑这点性能损耗,那么采用下划线也是没有问题的
代码生成器依赖
- 模板引擎
Apache Velocity
Apache Velocity是一个基于Java的模板引擎,它提供了一个模板语言去引用由Java代码定义的对象。Velocity是Apache基金会旗下的一个开源软件项目,旨在确保Web应用程序在表示层和业务逻辑层之间的隔离(即MVC设计模式)。
用途
下面是一些利用Velocity的常见应用类型:
- Web应用程序:网页设计者创建HTML页面,并为动态信息预留占位符。页面再由VelocityViewServlet或任何支持Velocity的框架处理。
- 源代码生成:Velocity可基于模板生成Java、SQL或PostScript源代码。大量的开源和商业软件包的开发就是这样利用Velocity。[1]
- 电子邮件自动生成:许多应用程序为了账户注册、密码提醒或自动寄送报表之需自动生成电子邮件。利用Velocity,电子邮件模板可以存储在一个文本文件,而不是直接嵌入到电子邮件生成器的Java代码中。
- XML转化:Velocity提供一个Ant任务——Anakia。Anakia读取XML文件,利用Velocity模板转换成所需的文档格式。常见的应用是将某种格式的文档转换成的一个带样式的HTML文档。
开发步骤
- 添加依赖到当前项目中
<!-- 导入MyBatis Plus 的代码生成器依赖 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.3.1.tmp</version>
</dependency>
<!-- 导入Apache Velocity -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.0</version>
</dependency>
<!-- 导入对应的日志相关jar -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.7</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.7</version>
</dependency>
<!-- 提前导入springweb 相关的依赖,因为自动生成会使用到自动注入 所以提前导入当前的依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.3.6</version>
</dependency>
导入依赖完毕之后,开始完成当前的代码自动是生成的相关设置
@Test
public void test() {
//1.全局配置
GlobalConfig gc = new GlobalConfig();
gc.setAuthor("阿伟")//当前创建用户是谁
.setOutputDir("C:\\Users\\Administrator\\IdeaProjects\\MyBatisPlus\\src\\main\\java")//生成内容的输出路径 意思就是当前生成的内容要存放在那个项目中
.setActiveRecord(true)//代表是否支持AR 如果true 则会为当前的实体类生成过程中自动集成Model
.setIdType(IdType.AUTO)//设置主键自增策略
.setFileOverride(true)//文件覆盖
.setServiceName("%sService")//设置生成的Service 名称,默认格式 I+ServiceName s 代表不加I
.setBaseResultMap(true)//设置是否生成sql映射文件
.setBaseColumnList(true);//设置基本的sql片段
//2.数据源配置
DataSourceConfig dsConfig = new DataSourceConfig();
//设置使用的数据库类型
//设置数据库链接相关信息
dsConfig.setDbType(DbType.MYSQL)
.setDriverName("com.mysql.jdbc.Driver")
.setUrl("jdbc:mysql://localhost:3306/soft?characterEncoding=utf-8")
.setUsername("root")
.setPassword("root");
//3.策略配置
StrategyConfig stConfig = new StrategyConfig();
stConfig.setCapitalMode(true)//全局大写命名
.setNaming(NamingStrategy.underline_to_camel)//设置数据库命名下划线
.setTablePrefix()//设置数据库表名固定前缀
.setInclude("student");//设置使用的表
//4.包名策略配置
PackageConfig packageConfig = new PackageConfig();
packageConfig.setParent("com.tedu")//设置包的固定格式
.setMapper("mapper")//设置当前的mapper接口生成的包
.setEntity("entity")//设置实体类生成的包
.setService("service")//设置service 包名称
.setController("controller")//设置控制器的包名
.setXml("mapper");//设置配置文件的输出位置
//5.整合配置
//将上述所有内容进行相关配置
AutoGenerator ag = new AutoGenerator();
ag.setGlobalConfig(gc)
.setDataSource(dsConfig)
.setStrategy(stConfig)
.setPackageInfo(packageConfig);
//6.执行上述配置 来完成代码的生成
ag.execute();
}
执行当前测试类中的当前方法
当运行结束后,会自动弹出 并且刷新当前工作目录则会出现 我们预先配置好的相关设置 自动生成的类
位置
//5.整合配置
//将上述所有内容进行相关配置
AutoGenerator ag = new AutoGenerator();
ag.setGlobalConfig(gc)
.setDataSource(dsConfig)
.setStrategy(stConfig)
.setPackageInfo(packageConfig);
//6.执行上述配置 来完成代码的生成
ag.execute();
}
执行当前测试类中的当前方法
[外链图片转存中...(img-q0IKuCZZ-1626677656857)]
当运行结束后,会自动弹出 并且刷新当前工作目录则会出现 我们预先配置好的相关设置 自动生成的类