Spring Boot是由Pivotal团队提供的全新框架,设计目的是用来简化Spring应用的搭建以及开发过程
作用: SpringBoot的推出 让程序员更加专注于业务处理, SpringBoot是学习微服务框架基石(SpringCloud)
Spring 和SpringBoot关系 :SpringBoot是Spring的工具API框架
SpringBoot项目内置了Tomcat服务器,启动项目Tomcat服务器随之启动,Tomcat是项目部署的一个容器,项目需要持久的在服务器上运行,
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.4.5version>
<relativePath/>
parent>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
在target目录下找jar包,或是去本地库根据坐标寻找jar包
dos命令
根目录输入cmd (command )
1.cd 切换目录
2.dir 查看当前目录结构
3.cls 清屏
4.tab键自动补齐
项目关闭
1.直接将dos窗口关闭
2.ctrl + c 万能的关闭指令
2.当jar包加载完成之后,由于该项目也是maven工程,所以maven工具会解析该项目的pom.xml文件 , 根据POM.xml文件 再次加载依赖包 直到所有的jar包依赖加载完成
传输加密机制: SHA1算法
SHA-1(英语:Secure Hash Algorithm 1,中文名:安全散列算法1)是一种密码散列函数。SHA-1可以生成一个被称为消息摘要的160位(20字节)散列值,散列值通常的呈现形式为40个十六进制数。
java中常见hash码为8位16进制数,共有(2^32)中组合
一位数有16种可能即 (2^4 ), 8位数 即 (24)8
如果给定的key相同,那么计算所得的hashcode必然相同,key不同结果有可能一样(哈希碰撞,概率极低,位数越高碰撞几率越小)
一个数据1kb,一个数据1mb hash计算一样快
YML文件语法:
server:
port: 8090 #配置端口
servlet: #web项目发布路径
context-path: / #/表示根目录
#无业务交叉所以与server同级
#定义dept属性值 YML文件默认支持UTF-8
#配置文件本身就是字符串,赋值不要加引号
dept:
id: 100
name: 财务部
配置文件已经归于Spring容器进行管理
@Component //将对象交给Spring容器管理
public class Dept {
//spel表达式
//注入具体值 使用@value
//注入对象的引用 使用Autowire
@Value("${dept.id}")
private Integer id;
@Value("${dept.name}")
private String name;
Spring测试类中,需要手动调用容器,在容器中获取对象,执行方法
Springboot测试类简化了流程
注意事项: 以后写代码都必须写到主启动类的同包及子包中
因为包扫描看的是主启动类的位置
/**
* 在执行测试方法时,自动启动容器,所有对象都在容器内部,
* 所有对象想要手機用,直接注入即可
*/
@SpringBootTest
class DemoApplicationTests {
//容器启动成功之后,SpringBoot负责讲对象进行注入,对象的引用(注入)
@Autowired
private Dept dept;
@Test
void contextLoads() {
System.out.println(dept);
}
}
#程序读取时,默认iso-8859-1
dept.id2=888
dept.name2=SpringBoot测试
@Component //将对象交给Spring容器管理
@PropertySource(value = "classpath:/dept.properties",encoding ="utf-8")//加载指定的配置文件
public class Dept {
//spel表达式
//注入具体值 使用@value
//注入对象的引用 使用Autowire
@Value("${dept.id}")
private Integer id;
@Value("${dept.name}")
private String name;
//通过配置文件为属性赋值
@Value("${dept.id2}")
private Integer id2;
@Value("${dept.name2}")
private String name2;
安装插件,添加jar包
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
dependency>
@Data
:ombok插件提供 自动生成get/set/toString/equals/hashcode等方法
@Accessors(chain = true)
:链式加载注解,相当于重写了set方法,返回this对象
二进制—>十进制:按权展开求和
十进制—>二进制:
八进制—>二进制:
需求: 简化环境切换带来的影响
要求: 如果采用多环境测试,则要求每个环境中的数据项都应该保持一致.(不能只改端口,业务数据也要添加)缺失可能导致项目启动异常.
多环境配置:
#默认环境选项
spring:
profiles:
#默认环境配置名称
active: test
#环境分割
---
#YML文件语法
## 1.YML数据结构k-v结构
## 2.k与v 需要使用 :"空格" 连接
## 3.YMl配置文件有父子级关系 所以注意缩进项的位置
spring:
config:
activate:
on-profile: prod
server:
port: 80 #配置端口
servlet: #web项目发布路径
context-path: / #/表示根目录
#定义dept属性值 YML文件默认支持UTF-8
dept:
id: 100
name: 财务部
#环境分割线
---
# 每个环境都应该有自己的名称
spring:
config:
activate:
on-profile: test
server:
port: 8080 #配置端口
servlet: #web项目发布路径
context-path: / #/表示根目录
#定义dept属性值 YML文件默认支持UTF-8
dept:
id: 100
name: 集團本部
在开发阶段每次修改完源码都要重启服务器,程序才能生效. 热部署可以让程序自动的完成监控,重启服务器.
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
dependency>
组合键: ctrl + shift + alt + /
或者 ctrl + alt + a
POM+yml配置+xml+接口
课前资料1.数据库
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.4.5version>
<relativePath/>
parent>
<groupId>com.jtgroupId>
<artifactId>springboot_demo_2artifactId>
<version>0.0.1-SNAPSHOTversion>
<name>springboot_demo_2name>
<description>Demo project for Spring Bootdescription>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-jdbcartifactId>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<scope>runtimescope>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
<scope>runtimescope>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>3.4.2version>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
exclude>
excludes>
configuration>
plugin>
plugins>
build>
project>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
<scope>runtimescope>
<optional>trueoptional>
dependency>
server:
port: 8090
#SpringBoot 开箱即用
#对应pom文件中的启动项
#
# org.springframework.boot
# spring-boot-starter-jdbc
#
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/jtadmin?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
username: root
#检查密码是否正确
password: root
#SpringBoot整合MybatisPlus配置
mybatis-plus:
#定义别名包
type-aliases-package: com.jt.pojo
mapper-locations: classpath:/mappers/*.xml
#开启驼峰映射
configuration:
map-underscore-to-camel-case: true
#添加MP日志 打印执行的sql
logging:
level:
com.jt.mapper: debug
url: jdbc:mysql://127.0.0.1:3306/jtadmin?
3306为数据库的服务端口,8080位Tomcat服务器占用端口,不可混为一谈serverTimezone=GMT%2B8
%2B 是转义字符代表 “+” 号 .服务时区,新版本的驱动要求必须配置时区&useUnicode=true&characterEncoding=utf8
使用Unicode编码字符集 , 要求字符UTF-8编码&autoReconnect=true
是否自动重连.&allowMultiQueries=true
是否允许批量操作 同时执行多个sql!定义别名包:对相同的包路径进行公共的抽取
#SpringBoot整合Mybatis配置项
mybatis:
#定义别名包
type-aliases-package: com.jt.pojo
mapper-locations: classpath:/mybatis/mappers/*.xml
#开启驼峰映射
configuration:
map-underscore-to-camel-case: true
UserMapper.findAll();
我们写的是方法,数据库并不认识,只能识别sql语句,UserMapper所调用的方法(findAll)应与映射文件的id(sql)进行绑定,绑定之前应该找到UserMapper接口所关联的配置文件才行,关联映射文件后,通过方法映射Sql语句!!!resultType="包名.类名"
resultType="com.jt.pojo.DemoUser"
pojo对象DemoUser与数据库表demo_user
进行了对应
优化:将不变的包路径进行抽取,因为变化的只有类名.
解决方案: 定义别名包即可
yml配置文件中包路径进行公共的抽取,定义别名包
type-aliases-package: com.jt.pojo
则可以直接返回对象的名称:resultType="DemoUser"
程序解析时: 首先根据别名包的名称进路径的拼接 com.jt.pojo.DemoUser
<mapper namespace="com.jt.mapper.DemoUserMapper">
<update id="updateUser">
update demo_user set name=#{nowName} where name=#{oldName}
and sex=#{sex}
update>
<insert id="insertUser">
insert into demo_user(id,name,age,sex)
value(null,#{name},#{age},#{sex})
insert>
<select id="findAll" resultType="DemoUser">
select * from demo_user
select>
mapper>
@MapperScan("com.jt.mapper")
主启动类添加注解
package com.jt.mapper;
/*注意事项: basemapper必须添加泛型对象 切记!!!*/
//@Mapper //表示将mapper接口交给Spring容器管理,即可以通过Autowire的方式进行动态的注入
public interface DemoUserMapper extends BaseMapper<DemoUser> {
//使用MP不要重载里边的方法 容易解析异常
List<DemoUser> findAll();
void insertUser(DemoUser user);
void updateUser(String oldName, String nowName, String sex);
}
主启动类,管理了接口测试时才可以注入,测试类位置应与主启动类位置对应
@SpringBootApplication //标识主启动类的注解
@MapperScan("com.jt.mapper") //将Mapper接口交给容器管理
public class SpringBootRun {
public static void main(String[] args) {
SpringApplication.run(SpringBootRun.class,args);
}
}
@SpringBootTest
public class TestSpringBoot {
@Autowired
//通过jdk动态代理创建的代理对象
private DemoUserMapper userMapper;
/**
* Spring未优化前需要在容器中获取对象
* UserService userService = context.getBean(UserService.class);
*/
@Test
public void testFindAll(){
//检查是否为代理对象
System.out.println(userMapper.getClass());
/**
* class com.sun.proxy.$Proxy73
*/
//有数据说明整合mybatis成功
List<DemoUser> userList = userMapper.findAll();
System.out.println(userList);
}
public class MybatisTest02 {
SqlSession session = null;
@Before
public void beforeMethod() throws Exception {
//1.读取mybatis核心配置文件中的配置信息(起名:mybatis-config.xml)
InputStream in= Resources.getResourceAsStream("mybatis-config.xml");
//2.基于读取的配置信息获取SqlSessionFactory对象(工厂)
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//3.通过工厂对象打开与数据库的连接(即获取SqlSession对象,类似于connection)
//提交方式二:true: 表示自动提交事务, 默认是false, 表示关闭自动提交, 需要手动提交!
session = factory.openSession( true );
//4.获取由Mybatis提供的接口的子类对象实例(参数为接口的字节码对象),底层利用反射剖析这个接口
EmpMapper mapper = session.getMapper(EmpMapper.class);
//接口的实现类中实现了定义的查询方法
List<Emp> list = mapper.findAll();
for (Emp emp : list) {
System.out.println(emp);
}
}
将namespace和id拼接起来就可以通过session执行
public class EmpMapperImpl implements EmpMapper{
//当外部有需求与实现类提供的功能一样,就会去new实现类对象
/**new实现类对象时,将session对象作为参数传递进来,保存在实现类对象内部,类中就可以使用session对象提供的方法*/
public EmpMapperImpl( SqlSession session ) {
this.session = session;
}
private SqlSession session;
/* 查询所有的员工信息 */
public List<Emp> findAll() {
// 1.获取当前这个类的父接口的全类名(=namespace)
String interName = this.getClass().getInterfaces()[0].getName();
// 2.获取当前方法的名字(=SQL标签的id值)
StackTraceElement[] st = Thread.currentThread().getStackTrace();
String methodName = st[1].getMethodName();
List<Emp> list = session.selectList( interName+"."+methodName );
return list;
}
}
SpringBoot根据pom文件加载依赖项,Spring根据这些配置实例化对象,放入Spring容器进行统一管理
容器启动成功之后,通过容器即可注入要使用的对象
@Autowired
//通过jdk动态代理创建的代理对象
private DemoUserMapper userMapper;
先写方法,根据报错在接口中创建方法,复制方法名在映射文件中编写sql
如果前端传过来的数据封装在map集合中,#{ }占位符名称要和Map集合的key保持一致!
如果前端传过来的数据封装在POJO对象中,#{ }占位符名称要在POJO对象中有对应的getXxx方法,或者有对应的属性(名称和属性名相同)
<insert id="insertUser">
insert into demo_user(id,name,age,sex)
value(null,#{name},#{age},#{sex})
insert>
//入库操作
@Test
public void testInsert(){
DemoUser user = new DemoUser();
user.setId(null).setName("mybatis信息").setAge(18).setSex("男");
userMapper.insertUser(user);
}
<update id="updateUser">
update demo_user set name=#{nowName} where name=#{oldName}
and sex=#{sex}
update>
/**将mybatis name="mybatis信息" 改为"测试信息". 条件 sex="男"
update demo_user set name="测试信息"
where name="mybatis信息" and sex="男"
*/
@Test
public void testUpdate(){
//1.封装数据
String oldName = "mybatis信息";
String nowname = "测试信息";
String sex = "男";
userMapper.updateUser(oldName,nowname,sex);
}
MyBatis-Plus (简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
之前操作数据库采用sql(面向过程的语言)方法进行编辑. 但是如果所有的单表操作都由程序员完成.则开发效率低. MP开发了一种机制实现以面向对象的方式操作数据库即 动态拼接sql
userMapper.selectList(null)
)在底层自动的转化为Sql语句!int userMapper.insert(T entity);
Sql语句: insert into 表名(字段名) value(属性值…)
苞米豆家的jar包
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>3.4.2version>
dependency>
MP以面向对象的方式操作数据库.其中对象与表 , 属性与字段都一对一映射
type
属性取值 IdType.AUTO
表示定义主键自增type
属性取值 IdType.ASSIGN_UUID
表示定义主键UUID的取值方式
@Data
@Accessors(chain = true)
@TableName("demo_user")
public class DemoUser {
@TableId(type = IdType.AUTO)
//@TableId(type = IdType.ASSIGN_UUID)
private Integer id;
//@TableField(value = "name",exist = true) 名称一致可以省略
private String name;
private Integer age;
private String sex;
}
MP提供BaseMapper接口,接口中编辑了常见单表的CRUD操作,用于规范化常见方法的书写,我们的mapper接口在继承BaseMapper时注意添加泛型,泛型即与数据库表对应的接口对象的名称BaseMapper
,使用MP注意不要重写里面提供的方法,容易解析异常
//@Mapper
public interface DemoUserMapper extends BaseMapper<DemoUser> { }
//测试MybatisPlus
@Test
public void testMP(){
List<DemoUser> userList = userMapper.selectList(null);
System.out.println(userList);
/**
* com.jt.mapper.DemoUserMapper.selectList : ==>
* Preparing: SELECT id,name,age,sex FROM demo_user
*/
}
yml配置文件中添加日志打印配置,接口包路径对应日志级别debug
#添加MP日志 打印执行的sql
logging:
level:
com.jt.mapper: debug
/**
* 入库操作
* 结果: ==> Preparing: INSERT INTO demo_user ( name, age, sex ) VALUES ( ?, ?, ? ) 预编译
* ==> Parameters: MP测试(String), 19(Integer), 男(String)
* <== Updates: 1
*/
@Test
public void insert(){
DemoUser user = new DemoUser();
user.setName("MP测试").setSex("男").setAge(19);
userMapper.insert(user);
}
updateById
方法 , 原理是根据对象中不为null的属性当做set条件. 且Id必须赋值 并且ID当做唯一where条件
/**
* 更新操作:
* com.jt.mapper.DemoUserMapper.updateById :
* ==> Preparing: UPDATE demo_user SET name=?, age=? WHERE id=?
* ==> Parameters: 英雄联盟(String), 22(Integer), 231(Integer)
* <== Updates: 1
*/
@Test
public void updateById(){
DemoUser user = new DemoUser();
user.setName("英雄联盟").setAge(22).setId(231);
userMapper.updateById(user);
}
update(entity, updateWrapper);
参数说明:
1.entity 实体对象 需要修改的数据进行封装
2.updateWrapper 条件构造器
/**
* 需求: 更新数据
* 将name="中午吃什么" 改为name="晚上吃什么"
* 性别: 改为 其他
* Sql:
* update demo_user set name="xxx",sex="其他"
* where name="xxxx"
* 结果:
* Preparing: UPDATE demo_user SET name=?, sex=? WHERE (name = ?)
* Parameters: 卡特琳娜(String), 其他(String), 英雄联盟(String)
*
* Preparing: SELECT id,name,age,sex FROM demo_user WHERE (sex = ? AND name = ?)
* Parameters: 其他(String), 卡特琳娜(String)
*
*/
@Test
public void testSelect10(){
DemoUser user = new DemoUser();
user.setName("卡特琳娜").setSex("其他");
UpdateWrapper<DemoUser> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("name", "英雄联盟");
userMapper.update(user, updateWrapper);
QueryWrapper<DemoUser> queryWrapper1 = new QueryWrapper<>();
queryWrapper1.eq("sex", "其他").eq("name", "卡特琳娜");
DemoUser user1 = userMapper.selectOne(queryWrapper1);
System.out.println(user1);
}
返回的一条记录
/**
* 需求:id=21的用户 根据ID查询数据
* 结果: Preparing: SELECT id,name,age,sex FROM demo_user WHERE id=?
* Parameters: 21(Integer)
* DemoUser(id=21, name=孙尚香D, age=18, sex=女)
*/
@Test
public void testSelect(){
DemoUser user = userMapper.selectById(21);
System.out.println(user);
}
selectObjs
应用场景:MP虽然不支持多表关联查询,但是可以单表自关联查询
1.一般根据条件查询Id的值,查询之后为后续的sql提供数据支持
2.有时用户只需要查询ID的值,并不需要其他数据项时 使用objs.
/**
* 需求: 查询表中第一列数据 selectObjs
* 说明: queryWrapper=null 不需要where条件
* 结果:Preparing: SELECT id,name,age,sex FROM demo_user
* Parameters:
* Total: 48
* [1, 3, 4, 5, 6, 7, 8, 9, 11, 12, 16, 17, 18, 21, 22, 23, 24,
* 25, 27, 31, 38, 39, 40, 41, 43, 44, 46, 49, 50, 51, 52, 53, 55,
* 58, 62, 66, 68, 172, 173, 182, 194, 196, 227, 228, 229, 230, 231, 232]
*/
@Test
public void testSelect11(){
List objs = userMapper.selectObjs(null);
System.out.println(objs);
}
如下:此处查询到的objs可以作为参数按需查询
/**
* 需求: 查询表中所有男性用户的ID
* 结果: Preparing: SELECT id,name,age,sex FROM demo_user WHERE (sex = ?)
* Parameters: 男(String)
* Total: 30
* [1, 3, 4, 5, 6, 7, 8, 9, 22, 23, 24, 25, 43, 49, 50, 51, 52,
* 53, 55, 58, 62, 66, 68, 182, 194, 196, 227, 229, 231, 232]
*/
@Test
public void testSelect7(){
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.eq("sex","男");
List objs = userMapper.selectObjs(queryWrapper);
System.out.println(objs);
}
selectList()
返回的是满足所有条件的List集合单条数据包含表中所有列
selectList()
需要传递queryWrapper对象(条件构造器) , 用于拼接Where条件,值可以为null
原则:根据对象中不为null的属性生成Where条件,具体操作时,需要先封装要执行的条件对象,将条件对象传递给条件构造器,用于构造Where条件,左侧一定要加泛型才可以链式加载多个条件
给查询方法selectList()
传递条件构造器,即可完成查询
实现面向对象的方式操作数据库
/**
* 根据属性查询
* 需求:查询name="白骨精" sex=女 的数据 List
* 结果:Preparing: SELECT id,name,age,sex FROM demo_user WHERE name=? AND sex=?
* Parameters: 白骨精(String), 女(String)
* [DemoUser(id=41, name=白骨精, age=3000, sex=女)]
*/
@Test
public void test2(){
DemoUser user = new DemoUser();
DemoUser user1 = user.setName("白骨精").setSex("女");
QueryWrapper<DemoUser> queryWrapper = new QueryWrapper<>(user1);
List<DemoUser> users = userMapper.selectList(queryWrapper);
System.out.println(users);
}
条件构造器为空则查询泛型所对应的表的全部数据
条件构造器参数 :
/*Preparing: SELECT id,name,age,sex FROM demo_user
==> Parameters:
<== Total: 48*/
List<DemoUser> userList = userMapper.selectList(queryWrapper);
System.out.println(userList);
如果查询条件中有特殊关系符,则使用特殊转义字符查询
特殊关系符 | 转义 |
---|---|
> | gt |
< | lt |
= | eq |
> = | ge |
< = | le |
< > | ne |
默认连接符: AND 不用写
or直接点
/**
* 需求: 查询age>18岁 并且性别为女的用户
* Sql: select * from demo_user where age > 18 and sex="女"
* 结果:Preparing: SELECT id,name,age,sex FROM demo_user WHERE (age > ? AND sex = ?)
* Parameters: 18(Integer), 女(String)
* Total: 6
* */
@Test
public void testSelect2(){
QueryWrapper<DemoUser> queryWrapper = new QueryWrapper<>();
queryWrapper.gt("age", 18).eq("sex", "女");
List<DemoUser> userList = userMapper.selectList(queryWrapper);
System.out.println(userList);
}
主动调用or表示紧接着下一个方法不是用and连接!(不调用or则默认为使用and连接)
/**
* 需求: 查询 age>18 or age < 50 的数据
* Sql: select * from demo_user where age > 18 or age < 50
* 结果: SELECT id,name,age,sex FROM demo_user WHERE (age > ? OR age < ?)
* 18(Integer), 50(Integer)
* Total: 48
*/
@Test
public void testSelect2(){
QueryWrapper<DemoUser> queryWrapper = new QueryWrapper<>();
queryWrapper.gt("age", 18).or().lt("age", 50);
List<DemoUser> userList = userMapper.selectList(queryWrapper);
System.out.println(userList);
}
看 % 的位置 决定左右
释义 | Sql | 条件构造代码 |
---|---|---|
查询name中以精开头的数据 | name like " 精 % " | likeRight |
查询name中以精结尾的数据 | name like " % 精 " | LikeLeft |
查询name中含"精"字的数据 | name like " % 精 % " | Like |
查询name中不包含"精"字的数据 | notlike " % 精 % " | notLike |
/**
* like关键字
* 需求: 查询name中包含"精"字的数据
* 结果: Preparing: SELECT id,name,age,sex FROM demo_user WHERE (name LIKE ?)
* Parameters: %精%(String)
* Total: 2
*/
@Test
public void testSelect3(){
QueryWrapper<DemoUser> queryWrapper = new QueryWrapper<>();
QueryWrapper<DemoUser> like = queryWrapper.like("name", "精");
List<DemoUser> userList = userMapper.selectList(like);
System.out.println(userList);
}
orderByDesc()
降序排列,参数为字段column
/**
* 查询sex=男的数据,以id倒序排列
* Sql: select * from demo_user where sex='男' order by id desc
* 结果: Preparing: SELECT id,name,age,sex FROM demo_user WHERE (sex = ?) ORDER BY id DESC
* Parameters: 男(String)
*/
@Test
public void testSelect4(){
QueryWrapper<DemoUser> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("sex", "男")
.orderByDesc("id");
List<DemoUser> userList = userMapper.selectList(queryWrapper);
System.out.println(userList);
}
in(R column, Collection> value)
集合形式传递参数
in(R column, Object... values)
可变参数形式传递,注意是对象类型
==> Preparing: SELECT id,name,age,sex FROM demo_user WHERE (id IN (?,?,?,?,?))
==> Parameters: 1(Integer), 3(Integer), 5(Integer), 6(Integer), 7(Integer)
<== Total: 5
值得注意,用户查询数据时 1,3,5,6,7 是从前端传递来的参数,本身就是可变参数,此种方式不符合动态要求
MP在解析时,把数组整体当做了对象查询,并没有根据数组内的数据进行查询,需要将数组转化成集合
List<Integer> asList = Arrays.asList(1, 3, 5, 6, 7);
要么传递一个数组对象,所以数组类型不可用基本数据类型int
参与转换,应用包装类型
int[] ids = {1,3,5,6,7}; x
Integer[] ids = {1,3,5,6,7};
/**
* 5.查询id= 1,3,5,6,7的用户
* Sql: select * from demo_user where id in (xxx,xx,xx)
* 结果:Preparing: SELECT id,name,age,sex FROM demo_user WHERE (id IN (?,?,?,?,?))
* Parameters: 1(Integer), 3(Integer), 5(Integer), 6(Integer), 7(Integer)
* Total: 5
*/
@Test
public void testSelect5(){
Integer[] ids = {1,3,5,6,7};
List<Integer> idlist = Arrays.asList(ids);
//List asList = Arrays.asList(1, 3, 5, 6, 7);
QueryWrapper<DemoUser> queryWrapper = new QueryWrapper<>();
// queryWrapper.in("id",ids); 数组必须为包装类型,不如list集合好用
queryWrapper.in("id",idlist);
List<DemoUser> userList = userMapper.selectList(queryWrapper);
System.out.println(userList);
}
condition: 内部编辑一个判断的条件, 如果返回值结果为true 则拼接该字段 . 如果为false 则不拼接该字段.
select * from demo_user
where name!=null name=xxx and age!=null age>xxx
name不为空才会执行 name= xxx , 同理age不为空才会执行后面的语句
此处 name!=null 和 age!=null 就是 condition
CollectionUtils.isEmpty(ageList)
判断集合是否为空public static boolean isEmpty(@Nullable Collection<?> collection) {
return (collection == null || collection.isEmpty());
}
StringUtils.isEmpty(name)
判断字符串是否为空 基本不用
StringUtils.hasLength(str)
判断字符串是否有效
public static boolean hasLength(@Nullable CharSequence str) {
return str != null && str.length() > 0;
}
equals()
方法,则一定要重写后再使用,此处调用的是String 的equals()
,底层已经重写,比的就是内容boolean flag = name !=null && !"".equals(name);
/**
* 需求: 如果根据name属性和age属性查询数据. 有时某个数据可能为null,要求动态查询!!!
* where name=xxx age>xxxx mybatis中的if标签
*
* 伪Sql: select * from demo_user
* where name!=null name=xxx and age!=null age>xxx
*
* 结果:SELECT id,name,age,sex FROM demo_user WHERE (name = ? AND age > ?)
* Parameters: 小乔(String), 18(Integer)
* Total: 1---[DemoUser(id=43, name=小乔, age=19, sex=男)]
*/
@Test
public void testSelect6(){
QueryWrapper<DemoUser> queryWrapper = new QueryWrapper<>();
String name = "小乔";
int age = 18;
//boolean flag = name !=null && !"".equals(name);
queryWrapper.eq(StringUtils.hasLength(name),"name", name)
.gt(age>0,"age",age);
List<DemoUser> userList = userMapper.selectList(queryWrapper);
System.out.println(userList);
}
/**
* 需求:查询name包含字符小,并且age属于[17 , 18 , 19 , 20 ]。
* 伪sql: select * from demo_user
* where (name LIKE %小%) and age IN (?,?,?,?,?)
* 结果:Preparing: SELECT id,name,age,sex FROM demo_user WHERE (name LIKE ? AND age IN (?,?,?,?))
* Parameters: %小%(String), 17(Integer), 18(Integer), 19(Integer), 20(Integer)
* Total: 5
* [DemoUser(id=11, name=小乔, age=17, sex=女),
* DemoUser(id=43, name=小乔, age=19, sex=男),
* DemoUser(id=49, name=小兰兰, age=18, sex=男),
* DemoUser(id=53, name=小明, age=18, sex=男),
* DemoUser(id=227, name=小法, age=20, sex=男) ]
*/
@Test
public void testcondition(){
QueryWrapper<DemoUser> queryWrapper = new QueryWrapper<>();
String name = "小";
List<Integer> asList = Arrays.asList(17, 18, 19, 20);
queryWrapper.like(StringUtils.hasLength(name),"name",name)
.in(!asList.isEmpty(),"age",asList);
List<DemoUser> userList = userMapper.selectList(queryWrapper);
System.out.println(userList);
}
与 selectObjs 对比记忆
/**
* 需求: 想查询name/sex字段
* queryWrapper.select("name","sex"); 挑选指定字段
* Preparing: SELECT name,sex FROM demo_user
* [ DemoUser(id=null, name=黑熊精, age=null, sex=男),
* DemoUser(id=null, name=金角大王, age=null, sex=男),
* DemoUser(id=null, name=银角大王, age=null, sex=男),
* DemoUser(id=null, name=唐僧, age=null, sex=男), .....]
*/
@Test
public void testSelect8(){
QueryWrapper<DemoUser> queryWrapper = new QueryWrapper();
queryWrapper.select("name","sex");
List objs = userMapper.selectList(queryWrapper);
System.out.println(objs);
}
上述方法查询结果封装在了DemoUser对象中,结果有冗余数据,并不方便,应只返回有效字段更为高效,不能用DemoUser对象封装,selectMap要求返回数据使用Map集合封装,K取表字段名,所以是String类型,字段值类型繁杂,所以为objs类型,由于存在多条数据,所以最外层嵌套List集合.
/**
* 需求: 想查询name/age字段 要求只返回有效字段
* 返回有效字段的查询:selectMaps
* 结果: Preparing: SELECT name,age FROM demo_user
* Total: 48
* [ {name=黑熊精, age=3000},
* {name=金角大王, age=3000},
* {name=银角大王, age=4000},
* {name=唐僧, age=30},..... ]
*/
@Test
public void testSelect9(){
QueryWrapper<DemoUser> queryWrapper = new QueryWrapper<>();
queryWrapper.select("name","age");
List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);
System.out.println(maps);
}