一、MybatisPlus学习
(1) MybatisPlus介绍
MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
(2) MybatisPlus 特性
无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作
(4) ORM思想
对象关系映射(英语:Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序设计技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。从效果上说,它其实是创建了一个可在编程语言里使用的“虚拟对象数据库”。如今已有很多免费和付费的ORM产品,而有些程序员更倾向于创建自己的ORM工具。
概括: 使用对象的方式操作数据库.
(5) MybatisPlus工作原理
1).对象(属性)与数据库中的表(字段)一一映射. 利用注解实现映射
2).将公共的CRUD的接口的方法进行抽取,采用父级的方式进行定义,如果需要子级只需继承即可.
3).由于用户操作的是对象,但是数据库只能识别Sql语句.所以需要将对象按照特定的规则转化为Sql.
1、添加jar包
<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.1</version>
</dependency>
2、yml文件配置
#配置tomcat服务器相关信息
server:
port: 8090
servlet:
#项目发布路径 一般都是默认值/
context-path: /
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/jtdb?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
username: root
password: root
#添加mybatis相关配置信息
mybatis:
#只要定义了别名包 之后的映射类型可以自动的完成拼接.
type-aliases-package: com.jt.demo.pojo
mapper-locations: classpath:/mybatis/mappers/*.xml
#开启驼峰映射
configuration:
map-underscore-to-camel-case: true
mybatis-plus:
//xml映射文件路径
mapper-locations: classpath*:**/mapper/xml/**/*.xml
//定义别名包 映射类型完成自动拼接
type-aliases-package: com.jd.demo.pojo
configuration:
#驼峰下划线转换
map-underscore-to-camel-case: true
3、pojo,mapper,service配置
//pojo
@Data
@EqualsAndHashCode(callSuper=true)
@Accessors(chain = true)
@TableName("t_secret")
//model封装了CRUD
public class Secret extends Model<Secret>{
private static final long serialVersionUID = 1L;
@TableId(value="id",type=IdType.ASSIGN_UUID)
private String id; // id
//@TableField("name") 字段映射如果名称相同,刚可以省略不写
private string name.
}
//mapper层 继承basenapper 记得加泛型 封装了CRUD
//@MapperScan("com.xx.mapper")启动类加上此注解,就不用写下面注解
@Mapper//此注解告知该接口的实现类由框架实现,并交给spring管理
public interface SecretMapper extends BaseMapper<Secret>{
}
//service层 继承IService 封装了CRUD
public interface SecretService extends IService<Secret>{
}
//service层实现类
@Service
@Transactional
public class SecretServiceImpl extends ServiceImpl<SecretMapper, Secret> implements SecretService {
@Autowired
private SecretMapper secretMapper;
}
这样就可以在service使用mapper的crud功能,在controller使用service层的CRUD功能。service的封装在basemapper上更进一步进行封装,功能都差不多,只是多了一个批量使用功能。
4、MP API介绍
package com.jt.demo.test;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jt.demo.mapper.UserMapper;
import com.jt.demo.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Arrays;
import java.util.List;
@SpringBootTest
public class TestMybatis {
@Autowired
private UserMapper userMapper;
@Test
public void testFindAll(){
List<User> userList = userMapper.findAll();
System.out.println(userList);
}
/*
* 完成用户信息入库
*/
@Test
public void testInsert(){
User user = new User();
user.setName("郑爽").setAge(30).setSex("女");
//单表sql语句几乎不写
userMapper.insert(user);
}
/**
* 查询案例1: 查询Id=4 的用户
* Id代表主机的含义
*/
@Test
public void testSelectById(){
User user = userMapper.selectById(4);
System.out.println(user);
}
/**
* 查询案例2: 查询name="八戒"的人
* queryWrapper.lambda().eq(User::getName, "八戒");lambda写法
* Sql: select * from user where name="八戒"
* QueryWrapper<> 条件构造器 用来拼接where条件
* 常见逻辑运算符: = eq, > gt , < lt
* >= ge, <= le
*/
@Test
public void testSelectByName(){
/*
该方法只能做=号的判断
User user = new User();
user.setName("八戒");
//根据对象中不为null的属性拼接where条件
QueryWrapper<User> queryWrapper = new QueryWrapper<>(user);
List<User> userList = userMapper.selectList(queryWrapper);
System.out.println(userList);*/
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
//queryWrapper.lambda().eq(User::getName, "小乔");lambda写法
queryWrapper.eq("name", "小乔");
System.out.println(userMapper.selectList(queryWrapper));
}
/**
* 查询案例3: 查询age>18岁,并且name中包含 *君*用户
* Sql: select * from user where age>18 and name like '%君%'
* 如果中间是and连接符可以省略不写
*/
@Test
public void testSelectAnd(){
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.gt("age", 18)
.like("name", "君");
System.out.println(userMapper.selectList(queryWrapper));
}
/**
* 查询案例4:
* 查询name不为null的用户,并且 sex=女, name要求以"君"结尾
* 最后将数据按照id倒序排列
*/
@Test
public void testSelectDemo4(){
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.isNotNull("name")
.eq("sex", "女")
.likeLeft("name", "君")
.orderByDesc("id");
System.out.println(userMapper.selectList(queryWrapper));
}
/**
* 批量查询: 查询id=1,2,5,7,8 1000 的数据
* 关键字: in
*/
@Test
public void testSelectIn(){
//数据基本结构没有取值方法.所以需要通过集合处理.
Integer[] idArray = {1,2,5,7};
//数组转化时使用包装类型
List<Integer> idList = Arrays.asList(idArray);
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.in("id", idList);
System.out.println(userMapper.selectList(queryWrapper));
//该方法与上述操作sql一致,只不过写法不同
userMapper.selectBatchIds(idList);
//获取数据表中第一个字段信息(主键)
System.out.println(userMapper.selectObjs(null));
}
}
注意:在使用ybatis-plus查询的时候对null值和空值的判断
例:1、当表中没有数据的时候
List<Users> selectList = usersMapper.selectList(null);
System.out.println(selectList==null);
System.out.println(selectList.isEmpty());
for(Users users:selectList) {
System.out.println("111111111111111111111");
}
for (int i = 0; i < selectList.size(); i++) {
System.out.println(i);
}
可以看出结果不为null,但是为空,不会进入遍历
2、当表中有数据的时候
List<Users> selectList = usersMapper.selectList(null);
System.out.println(selectList==null);
System.out.println(selectList.isEmpty());
for(Users users:selectList) {
System.out.println(users==null);
System.out.println("111111111111111111111");
System.out.println("------"+users);
}
for (int i = 0; i < selectList.size(); i++) {
System.out.println(i);
}
}
当表中有值的时候,查询表中全部数据的的时候,查询出的结果不会 为null和空(因为表中有值),进入遍历,遍历后的对象也不会为null和空(因为表中主键不为null)。
3、当表中有数据,查询某个字段,但这个字段可能为空或者null
QueryWrapper<Users> queryWrapper=new QueryWrapper<>();
queryWrapper.select("password");
List<Users> selectList = usersMapper.selectList(queryWrapper);
System.out.println(selectList==null);
System.out.println(selectList.isEmpty());
System.out.println("=========================================");
for(Users users:selectList) {
System.out.println(users==null);
System.out.println("111111111111111111111");
System.out.println("------"+users);
}
for (int i = 0; i < selectList.size(); i++) {
System.out.println(i);
}
}
当表中有值的时候,查询表中部分字段的时候,查询出的结果不会 为null和空(因为表中有值),进入遍历,遍历后的对象有可能为null值或者空值(因为查询字段为null的时候,对象就会为null),因为查询的这个字段为空或者null时候,需要对遍历后的对象进行判断。
总之:查询多个返回值为list集合,集合不会为null,但有可能为空,集合中的对象也有可能为null或者空