1.SpringBoot简介
- 独立运行的 Spring 项目Spring Boot 可以以 jar 包的形式独立运行,Spring Boot 项目只需通过命令“ java–jar xx.jar” 即可运行。
- 内嵌 Servlet 容器Spring Boot 使用嵌入式的 Servlet 容器(例如 Tomcat、Jetty 或者 Undertow 等),应用无需打成 WAR 包 。
- 提供 starter 简化 Maven 配置Spring Boot 提供了一系列的“starter”项目对象模型(POMS)来简化 Maven 配置。
- 提供了大量的自动配置Spring Boot 提供了大量的默认自动配置,来简化项目的开发,开发人员也通过配置文件修改默认配置。
- 自带应用监控Spring Boot 可以对正在运行的项目提供监控。6. 无代码生成和 xml 配置Spring Boot 不需要任何 xml 配置即可实现 Spring 的所有配置。
2.构建SpringBoot
SpringBoot采用内置容器(默认容器Tomcat)的方式进行部署,所以不用在idea中再配置Tomcat了,直接运行启动类的main方法即可
启动效果
认准这行,代表启动成功!默认运行在了8080端口
编写案例
1. Controller返回json
@RequestMapping(value = "/test",method = RequestMethod.GET)
@ResponseBody
public Map<String,Object> test(){
Map<String,Object> map = new HashMap<>();
map.put("msg","测试成功!");
return map;
}
4.SpringBoot配置文件-YAML
5. Spring Boot配置绑定
所谓“配置绑定”就是把配置文件中的值与 JavaBean 中对应的属性进行绑定。通常,我们会把一些配置信息(例如,数据库配置)放在配置文件中,然后通过 Java 代码去读取该配置文件,并且把配置文件中指定的配置封装到 JavaBean(实体类) 中。
1. 使用 @ConfigurationProperties 注解
yml文件
# 测试配置
person:
name: 蔡徐坤
age: 180
birth: 1994/11/12
list:
- a
- b
- c
map:
name: 宇将军
age: 90
son:
name: 阿耶夫
age: 18
java类
@Data
@Component
@ConfigurationProperties(prefix = "person")
public class Person implements Serializable {
private String name;
private int age;
private Date birth;
private List<String> list;
private Map<String,Object> map;
private Person son;
}
2.使用@Value注解获取配置
@Data
@Component
public class Person implements Serializable {
@Value("${person.map.name}")
private String name;
private int age;
private Date birth;
private List<String> list;
private Map<String,Object> map;
private Person son;
}
3.加载除application配置文件之外的配置文件内容
使用@PropertySource
创建一个aabbcc.properties配置文件,编写内容
cxk.name: giao哥
加载方法
@Data
@Component
@PropertySource(value= "classpath:aabbcc.properties")
public class Person implements Serializable {
@Value("${cxk.name}")
private String name;
private int age;
private Date birth;
private List<String> list;
private Map<String,Object> map;
private Person son;
}
6.SpringBoot加载Spring配置文件
1.@ImportResource 注解
创建一个xml配置文件在resources目录下
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 注册一个person的实例 -->
<bean id="person" class="com.example.springbootdemo2023.core.dto.Person" />
</beans>
在启动类头部添加注解@ImportResource
@ImportResource(locations = "classpath:spring.xml")//导入spring配置文件
@SpringBootApplication
public class SpringBootDemo2023Application {
public static void main(String[] args) {
SpringApplication.run(SpringBootDemo2023Application.class, args);
}
}
使用测试
@Controller
@RequestMapping("/login")
public class LoginController {
@Autowired
private Person person;
@RequestMapping(value = "/test",method = RequestMethod.GET)
@ResponseBody
public Map<String,Object> test(){
Map<String,Object> map = new HashMap<>();
map.put("msg","测试成功!");
System.out.println(person);
return map;
}
打印
Person(name=null, age=0, birth=null, list=null, map=null, son=null)
2.使用Spring注解化导入配置的方法
配置类
@Configuration
public class MyConfig {
//等同于 <bean id="getPerson" class="com.example.springbootdemo2023.core.dto.Person" />
@Bean
public Person getPerson(){
Person person = new Person();
person.setName("gaojingbo");
return person;
}
}
7.SpringBoot多环境配置
从环境配置+主环境配置=boot项目完整配置
1. 创建不同环境下的配置文件
创建的规则:
开发环境:application-dev.yml
测试环境:application-test.yml
生产环境:application-prod.yml
application-dev.yml
# 开发环境配置
server:
port: 8090
application-test.yml
# 测试环境配置
server:
port: 8100
application-prod.yml
# 生产环境配置
server:
port: 9010
主配置文件-application.yml
主环境配置文件编写一些不会变化的配置项目即可
# 主配置文件
# 激活环境配置
spring:
profiles:
active: test
2.定义激活环境配置的方法
1. 运行jar包时通过指令参数设置
2. idea开发时可以使用工具设置
3.打包运行时使用jvm参数设置
8.SpringBoot默认配置文件的加载优先级
根目录下配置文件 > classpath目录中config文件夹下的配置文件 > classpath目录中的配置文件
所有写法优先级:(序号越小优先级越高)
- file:./config/
- file:./config/*/
- file:./
- classpath:/config/
- classpath:/
注:file: 指当前项目根目录;classpath: 指当前项目的类路径,即 resources 目录。
1. 当注解化配置和引入外部配置杂糅在一起时,完整加载优先级
- 命令行参数
- 来自 java:comp/env 的 JNDI 属性
- Java 系统属性(System.getProperties())
- 操作系统环境变量
- RandomValuePropertySource 配置的 random.* 属性值
- 配置文件(YAML 文件、Properties 文件)
- @Configuration 注解类上的 @PropertySource 指定的配置文件
- 通过 SpringApplication.setDefaultProperties 指定的默认属性
9.SpringBoot使用日志
1. 配置日志:在springboot配置文件中添加以下内容
# 日志配置
logging:
level:
com.example.springbootdemo2023: debug # 描述根包下所有的类都要进行日志记录
file:
path: F:\idea_logs\SpringBootDemo2023 # 离线生成的日志文件位置
pattern:
# 控制台日志的模板效果
console: "%red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %yellow(%-5level) %logger{50} - %m%n"
# 保存到文件中的日志效果
file: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{50} - %m%n"
10.SpringBoot拦截器
1.定义拦截器
和SpringMVC写法完全一致
/**
* 模块名称:登录会话验证拦截器
* 模块类型:
* 编码人:高靖博
* 创建时间:2023/3/1
* 联系电话:18587388612
*/
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("登录拦截器被调用!");
return true;
}
}
2.注册拦截器
创建一个实现了 WebMvcConfigurer 接口的配置类(使用了 @Configuration 注解的类),重写 addInterceptors() 方法,并在该方法中调用 registry.addInterceptor() 方法将自定义的拦截器注册到容器中。
InterceptorRegistration 配置拦截器规则:
addPathPatterns:设置进入拦截器的规则
excludePathPatterns:设置不进入拦截器的规则
注意: 路径不存在如果是404的话是绝对会进入拦截器的
// 1. 实现WebMvcConfigurer 接口
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
//2.重写addInterceptors方法
@Override
public void addInterceptors(InterceptorRegistry registry) {
//3. 注册自定义编写的拦截器
// 调用addInterceptor,参数传递拦截器实例
InterceptorRegistration ic = registry.addInterceptor(new LoginInterceptor());
//设置拦截器的拦截规则
ic.addPathPatterns("/**");
//放行拦截器(登录页面、登录请求、静态资源(js、css、img、video、font(字体文件))、阿里druid连接池监控中心、swaggerui)
ic.excludePathPatterns(
"/login/test2",
"/sys/user/doLogin",
"/js/**",
"/css/**",
"/imgs/**",
"/druid/**",
"/swagger-ui.html",
"/v2/**",
"/webjars/**",
"/swagger-resources/**",
"/sys/user/captcha",
"/sys/platform/**",
"/sys/files/**");
}
}
11.SpringBoot整合Druid连接池
1.引入依赖
<!-- 和数据源相关操作必须引入 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
<!-- 数据源依赖 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
2. 配置springboot配置文件
# spring数据源配置
spring:
datasource:
# druid连接池
type: com.alibaba.druid.pool.DruidDataSource
# mysql驱动
driver-class-name: com.mysql.cj.jdbc.Driver
# 数据库连接地址
url: jdbc:mysql://localhost:3306/javatest?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
# 用户名、密码
username: root
password: cxk666
# druid连接池配置
# 初始化连接池最大值,连接中活跃数量最大值
initial-size: 10
max-active: 8
# 获取连接等待的最长时间(毫秒)
max-wait: 60000
# 申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
test-while-idle: true
# 既作为检测的间隔时间又作为testWhileIdel执行的依据
time-between-eviction-runs-millis: 60000
# 销毁线程时检测当前连接的最后活动时间和当前时间差大于该值时,关闭当前连接(配置连接在池中的最小生存时间)
min-evictable-idle-time-millis: 30000
# 用来检测数据库连接是否有效的sql 必须是一个查询语句(oracle中为 select 1 from dual)
validation-query: select 1 from dual
# 申请连接时会执行validationQuery检测连接是否有效,开启会降低性能,默认为true
test-on-borrow: false
# 归还连接时会执行validationQuery检测连接是否有效,开启会降低性能,默认为true
test-on-return: false
# 是否缓存preparedStatement, 也就是PSCache,PSCache对支持游标的数据库性能提升巨大,比如说oracle,在mysql下建议关闭。
pool-prepared-statements: false
# 置监控统计拦截的filters,去掉后监控界面sql无法统计,stat: 监控统计、Slf4j:日志记录、waLL: 防御sqL注入
filters: stat,wall,slf4j
# 要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100
max-pool-prepared-statement-per-connection-size: -1
# 合并多个DruidDataSource的监控数据
use-global-data-source-stat: true
# 通过connectProperties属性来打开mergeSql功能;慢SQL记录
connect-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
web-stat-filter:
# 是否启用StatFilter默认值true
enabled: true
# 添加过滤规则
url-pattern: /*
# 忽略过滤的格式
exclusions: /druid/*,*.js,*.gif,*.jpg,*.png,*.css,*.ico
stat-view-servlet:
# 是否启用StatViewServlet默认值true
enabled: true
# 访问路径为/druid时,跳转到StatViewServlet
url-pattern: /druid/*
# 是否能够重置数据
reset-enable: false
# 需要账号密码才能访问控制台,默认为root
login-username: admin
login-password: 123456
# IP白名单
allow: 127.0.0.1
# IP黑名单(共同存在时,deny优先于allow)
deny:
12.SpringBoot整合MyBatis
1.引入依赖
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
2.修改SpringBoot配置文件
mybatis:
#xml文件路径映射(xml文件要和接口文件同名)
mapper-locations: com/huawei/bootdemo2/mybatis/dao/*.xml
#dto别名映射
type-aliases-package: com.huawei.bootdemo2.mybatis.domain
configuration:
map-underscore-to-camel-case: true #驼峰映射规则
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #mybatis默认日志
3. 在启动类上添加一个扫描mapper接口的注解
@MapperScan("com.example.springbootdemo2023.mybatis.dao")// mapper接口所在的包
@SpringBootApplication
public class SpringBootDemo2023Application {
public static void main(String[] args) {
SpringApplication.run(SpringBootDemo2023Application.class, args);
}
}
4.正常编写mybatis的接口和xml文件
使用代码生成器做,忽略
5.配置maven静态资源打包
因为xml文件是存在java源代码目录,默认情况下maven只会打包java文件
pom.xml中配置
<build>
...
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
<include>**/*.yml</include>
<include>**/*.yaml</include>
<include>**/banner.txt</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
5. 测试
此案例为在controller中引入mapper接口,在开发中要进行分层哟
@Controller
@RequestMapping("/login")
public class LoginController {
@Autowired
private TGoodsMapper goodsMapper;
@RequestMapping(value = "/test",method = RequestMethod.GET)
@ResponseBody
public TGoods test(){
TGoods tGoods = goodsMapper.selectByPrimaryKey("101");
return tGoods;
}
}
6.SpringBoot集成Mybatis分页工具
PageHepler
1. 引入依赖
<!-- 分页插件pagehelper -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.3.0</version>
<!-- 排除依赖,因为pageHelper是和Mybatis天然集成所以强依赖mybatis,但是我们项目中已经有了mybatis依赖就去掉 -->
<exclusions>
<exclusion>
<artifactId>mybatis-spring-boot-starter</artifactId>
<groupId>org.mybatis.spring.boot</groupId>
</exclusion>
</exclusions>
</dependency>
2.创建分页结果集对象
/**
* 模块名称:接收分页的结果DTO
* 模块类型:
* 编码人:高靖博
* 创建时间:2023/3/1
* 联系电话:18587388612
*/
@Data
public class MyPager<T> implements Serializable {
private int page;//结果的页码
private int pageSize;//每页显示行数
private List<T> rows;//分页当前页的结果集
private long total;//不分页所有数据总和(用于页码生成)
}
3.创建接收分页查询参数实体
/**
* 模块名称:用于接收分页查询参数
* 模块类型:
* 编码人:高靖博
* 创建时间:2023/3/1
* 联系电话:18587388612
*/
@Data
public class MyPageBand implements Serializable {
private int page;
private int size;
}
4. 如果出现循环依赖问题
如果你使用的jdk是8~10版本,只能将springBoot版本降低至2.5.5
5.测试
@Autowired
private TGoodsMapper goodsMapper;
@RequestMapping(value = "/test",method = RequestMethod.GET)
@ResponseBody
public MyPager test(MyPageBand page){
//创建条件对象
TGoodsExample example = new TGoodsExample();
//创建mybatis条件对象
TGoodsExample.Criteria criteria = example.createCriteria();
// criteria.andNameLike("%六个核弹%");
// criteria.andPriceBetween(new BigDecimal(20),new BigDecimal(30));
//1.创建分页对象
MyPager<TGoods> myPager = new MyPager<TGoods>();
//2.调用分页工具设置分页参数(页码,每页显示多少行数据)
Page<TGoods> goodsPage = PageHelper.startPage(page.getPage(), page.getSize());
//3.执行mapper的查询接口操作
goodsMapper.selectByExample(example);// !!!!!!!
List<TGoods> result = goodsPage.getResult();
long total = goodsPage.getTotal();//数据查询的所有行数值
myPager.setTotal(total);
myPager.setRows(result);
myPager.setPage(page.getPage());
myPager.setPageSize(page.getSize());
return myPager;
}
13.SpringBoot整合MyBatis-plus
一切为简单而生
1. 替换依赖
<!-- 删除mybati、pagehepler依赖 -->
<!-- 新:版本升级 mybatis-plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
2.修改SpringBoot配置文件
#mybatis-plus配置
mybatis-plus:
#dto别名映射
type-aliases-package: com.example.springbootdemo2023.mybatis.domain
#xml文件路径映射(xml文件要和接口文件同名)
mapper-locations: com/example/springbootdemo2023/mybatis/dao/**/*.xml
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #开启日志
map-underscore-to-camel-case: false
# 全局变量配置
# 逻辑删除-如:每个表中都有一个通用的字段isDelete描述当前数据是否被删除,1:已删除 0:未删除
global-config:
db-config:
# 当逻辑删除应该设置什么值:1
logic-delete-value: 1
logic-not-delete-value: 0
logic-delete-field: isDelete
3.定义myBatis-plus数据库表实体
@Data
@TableName("t_goods")
public class TGoods implements Serializable {
// id一定要标注,也就表明:每个表都必须有主键
@TableId(value = "goodsID",type = IdType.NONE)
private String goodsID;
private String name;
private BigDecimal price;
private String typeName;
}
4. 使用MyBatis-plus定义mapper接口的方法(发生改变)
- 创建mybatismapper接口集成mybatis-plus的BaseMapper接口
- 接口处定义泛型:泛型是当前mapper接口操作对应的数据库实体类型
baseMapper已经提前准备好所有通用的接口方法(增、删、改、查、分页查)
特殊需要自己手动实现的内容在定义到接口和xml文件中
@Mapper
public interface TGoodsMapper extends BaseMapper<TGoods> {
}
5. 定义一个空的和mapper接口同名的xml文件
<?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.example.springbootdemo2023.mybatis.dao.goods.TGoodsMapper">
</mapper>
只要完成以上3、4两个步骤,mybatis-plus就已经完成了代码生成自动注入
6.测试
@Autowired
private TGoodsMapper goodsMapper;
@RequestMapping(value = "/test",method = RequestMethod.GET)
@ResponseBody
public MyResult test(MyPageBand page){
MyResult result = new MyResult();
TGoods tGoods = goodsMapper.selectById("101");
result.setData(tGoods);
return result;
}
14. MyBatis-Plus
- mybatis-plus:关于DO实体类的定义方法(Java中要有一个类和数据库中的表一一对应)
- mybatis-plus:mapper映射文件和接口的写法
- MyBatis-plus:实现零sql代码增删改查(使用baseMapper中的方法)
- Mybatis-plus代码生成器的配置
1. MyBatis-plus-DO实体的定义规则
1.@TableName(表名)-必写
实现类和表一一映射
@Data
@TableName("t_goods")
public class TGoods implements Serializable {
...
}
2. @TableId-描述主键字段-必写
value参数:规定映射的表中主键字段名称
type参数:用于定义主键的类型(主键策略 使用IdType来定义)
IdType.AUTO:使用数据库自己的自增键模式实现id生成,一定记住数据库要设置自增才管用
IdType.NONE: 不实现自动生成主键,没有约束
IdType.INPUT: 不实现自动生成主键,约束该属性必须有值,且要让开发者自己定义
IdType.ASSIGN_ID:通过mybatis机制生成自增的整型值
IdType.ASSIGN_UUID: 通过mybatis机制生成-UUID值
@Data
@TableName("t_goods")
public class TGoods implements Serializable {
// id一定要标注,也就表明:每个表都必须有主键
@TableId(value = "goodsID",type = IdType.ASSIGN_UUID)
private String goodsID;
private String name;
private BigDecimal price;
private String typeName;
}
3.@TableField- 普通字段的定义描述-非必填
value参数:规定映射的表中与之映射的字段名
exist参数:(boolean)
false:当前实体对应表中可能没有这个字段,防止mybatis会生成该字段的增、删、‘改代码
true:当前实体对应表中有这个字段,且true是默认值
fill参数:填充功能( 删除的节点也会触发UPDATE修改策略 )
FieldFill.INSERT: 当插入时触发填充策略
FieldFill.UPDATE:当修改时触发填充策略
FieldFill.INSERT_UPDATE: 当修改或新增时触发填充策略
@Data
@TableName("t_goods")
public class TGoods implements Serializable {
// id一定要标注,也就表明:每个表都必须有主键
@TableId(value = "goodsID",type = IdType.ASSIGN_UUID)
private String goodsID;
private String name;
private BigDecimal price;
private String typeName;
//当操作新增时,该字段自动填写当前时间
@TableField(value = "insertTime",fill = FieldFill.INSERT)// 在什么时候要做某个事情
private Date insertTime;
@TableField(value = "updateTime",fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
}
当填充策略定义好,该如何填充需要手动定义实现
/**
* 模块名称:mybatis-plus字段自动填充策略实现
* 模块类型:
* 编码人:高靖博
* 创建时间:2023/3/2
* 联系电话:18587388612
*/
@Component
public class MyBatisPlusFillHandler implements MetaObjectHandler {
//当触发新增填充策略时会调用的方法
@Override
public void insertFill(MetaObject metaObject) {
//要给表中的insertTime字段设置一个当前系统时间
setFieldValByName("inserTime",new Date(),metaObject);
}
//当触发修改填充策略时会调用的方法
@Override
public void updateFill(MetaObject metaObject) {
//要给表中的insertTime字段设置一个当前系统时间
setFieldValByName("updateTime",new Date(),metaObject);
}
}
测试代码
@Autowired
private TGoodsMapper goodsMapper;
@RequestMapping(value = "/test",method = RequestMethod.GET)
@ResponseBody
public MyResult test(MyPageBand page){
MyResult result = new MyResult();
TGoods tGoods = new TGoods();
tGoods.setName("iPhone1000");
tGoods.setPrice(new BigDecimal("50"));
tGoods.setTypeName("手机");
int insert = goodsMapper.insert(tGoods);
result.setData(insert);
return result;
}
@RequestMapping(value = "/test2",method = RequestMethod.GET)
@ResponseBody
public MyResult test2(MyPageBand page){
MyResult result = new MyResult();
TGoods tGoods = new TGoods();
tGoods.setGoodsID("101");
tGoods.setName("switch");
tGoods.setPrice(new BigDecimal("2"));
int insert = goodsMapper.updateById(tGoods);
result.setData(insert);
return result;
}
@RequestMapping(value = "/test3",method = RequestMethod.GET)
@ResponseBody
public MyResult test3(MyPageBand page){
MyResult result = new MyResult();
int insert = goodsMapper.deleteById("101");
result.setData(insert);
return result;
}
2.mybatis-plus:mapper映射文件和接口的写法
接口文件(XXXMapper.java)
实现 BaseMapper接口
BaseMapper提供了基于泛型定义的增、删、改、查、分页方法
BaseMapper源码
public interface BaseMapper<T> extends Mapper<T> {
int insert(T entity);
int deleteById(Serializable id);
int deleteById(T entity);
int deleteByMap(@Param("cm") Map<String, Object> columnMap);
int delete(@Param("ew") Wrapper<T> queryWrapper);
int deleteBatchIds(@Param("coll") Collection<?> idList);
int updateById(@Param("et") T entity);
int update(@Param("et") T entity, @Param("ew") Wrapper<T> updateWrapper);
T selectById(Serializable id);
List<T> selectBatchIds(@Param("coll") Collection<? extends Serializable> idList);
List<T> selectByMap(@Param("cm") Map<String, Object> columnMap);
default T selectOne(@Param("ew") Wrapper<T> queryWrapper) {
List<T> ts = this.selectList(queryWrapper);
if (CollectionUtils.isNotEmpty(ts)) {
if (ts.size() != 1) {
throw ExceptionUtils.mpe("One record is expected, but the query result is multiple records", new Object[0]);
} else {
return ts.get(0);
}
} else {
return null;
}
}
default boolean exists(Wrapper<T> queryWrapper) {
Long count = this.selectCount(queryWrapper);
return null != count && count > 0L;
}
Long selectCount(@Param("ew") Wrapper<T> queryWrapper);
List<T> selectList(@Param("ew") Wrapper<T> queryWrapper);
List<Map<String, Object>> selectMaps(@Param("ew") Wrapper<T> queryWrapper);
List<Object> selectObjs(@Param("ew") Wrapper<T> queryWrapper);
<P extends IPage<T>> P selectPage(P page, @Param("ew") Wrapper<T> queryWrapper);
<P extends IPage<Map<String, Object>>> P selectMapsPage(P page, @Param("ew") Wrapper<T> queryWrapper);
}
sql映射文件xml(XXXXMapper.xml)
和mybatis没有区分,只要mapper标签中 namespace属性定义的是同名的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.example.springbootdemo2023.mybatis.dao.goods.TGoodsMapper">
...
</mapper>
3.MyBatis-plus:实现零sql代码增删改查(使用baseMapper中的方法)
1. 新增-insert
TGoods tGoods = new TGoods();
tGoods.setName("iPhone1000");
tGoods.setPrice(new BigDecimal("50"));
tGoods.setTypeName("手机");
int insert = goodsMapper.insert(tGoods);
2.修改
update方法:
参数1:需要更新的实体对象
参数2:更新条件
TGoods tGoods = new TGoods();
tGoods.setName("掌中宝");
//更新条件
QueryWrapper<TGoods> updateWrapper = new QueryWrapper<>();
// 修改goodsID为101的数据
// where goodsID = '101'
updateWrapper.eq("goodsID","101");
int insert = goodsMapper.update((tGoods),updateWrapper);
updateById
参数1:需要更新的实体对象,必须传递要更新数据的主键字段值
TGoods tGoods = new TGoods();
tGoods.setGoodsID("101");
tGoods.setName("掌中宝12312312312");
// where 主键字段名=101
int insert = goodsMapper.updateById(tGoods);// 主键字段必须有值
3.删除操作
deleteById(Serializable keyid) : 直接传入主键值
参数1: 必须传递要删除数据的主键字段值
int insert = goodsMapper.deleteById("101");
deleteById(实体参数):该实体对象中主键属性必须有值
TGoods tGoods = new TGoods();
tGoods.setGoodsID("101");
int insert = goodsMapper.deleteById(tGoods);
delete:
参数1:传递条件对象
//删除价格在10元以及10元以上,30元以下的数据
QueryWrapper<TGoods> deleteWarapper = new QueryWrapper<>();
/**
* ge:双参数写法==》 >=
* ge:三参数写法:第一个参数描述是否使用等于
* 如: ge(true,"price",10); ===》 price>=10
* ge(false,"price",10); ===》 price>10
*/
deleteWarapper.ge(true,"price",10);
deleteWarapper.le(false,"price",30);
int insert = goodsMapper.delete(deleteWarapper);
deleteBatchIds: 批量根据主键值删除
参数1:传递保存着要删除的主键值的集合
List<String> ids = new ArrayList<>();
ids.add("101");
ids.add("3552f64ba1f71fb41b2a612d636ce186");
int insert = goodsMapper.deleteBatchIds(ids);
4.查询
1.selectList-根据条件查询结果集
//查询未被删除的数据
QueryWrapper<TGoods> tGoodsQueryWrapper = new QueryWrapper<>();
List<TGoods> tGoods = goodsMapper.selectList(tGoodsQueryWrapper);
result.setData(tGoods);
2.selectMap-根据条件查询结果集-结果集是List
//查询未被删除的数据
QueryWrapper<TGoods> tGoodsQueryWrapper = new QueryWrapper<>();
List<Map<String, Object>> maps = goodsMapper.selectMaps(tGoodsQueryWrapper);
3.selectCount-条件查询统计结果集的行数
//查询未被删除的数据
QueryWrapper<TGoods> tGoodsQueryWrapper = new QueryWrapper<>();
Long aLong = goodsMapper.selectCount(tGoodsQueryWrapper);
4.selectOne-条件查询结果只接收一行数据
//查询未被删除的数据
QueryWrapper<TGoods> tGoodsQueryWrapper = new QueryWrapper<>();
// 查询结果只有一行数据时可以使用该方法,
//如果有多行数据就会抛出:One record is expected, but the query result is multiple records
TGoods tGoods = goodsMapper.selectOne(tGoodsQueryWrapper);
5.selectById-根据主键字段查询
TGoods tGoods = goodsMapper.selectById("101");
6. mybatis-plus分页查询
想要实现分页,首先要进行分页组件的配置
在启动类中添加如下代码
//分页配置
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));// 分页的方法-以mysql分页方式实现
return interceptor;
}
1.selectPage-条件分页方法-使用baseMapper接口中的分页方法
page.setPage(1);//第一页
page.setSize(2);//每页显示2行
MyPager<TGoods> pager = new MyPager<>();
//查询商品名字中有"P"的商品
QueryWrapper<TGoods> queryWrapper = new QueryWrapper<>();
queryWrapper.like("name","P");
Page<TGoods> tGoodsPage = goodsMapper.selectPage(PageDTO.of(page.getPage(), page.getSize()), queryWrapper);
List<TGoods> records = tGoodsPage.getRecords();//分页的结果
long total = tGoodsPage.getTotal();//不分页所有数据的行数
pager.setPageSize(page.getSize());
pager.setRows(records);
pager.setTotal(total);
pager.setPage(page.getPage());
2.特殊自定义的接口方法如何分页
mapper接口定义
/**
* 自定义分页写法
* @param of mp 的分页参数
* @param goods 自己条件实体
* @return IPage<TGoods>
*/
IPage<TGoods> selectGoodsPages(Page of, @Param("goods") TGoods goods);
xml定义
<!-- 虽然传入了分页参数,但是不需要用参数写limit语句,mp会自动拼接生成 -->
<!-- 自定义查询sql语句,就不会拼接逻辑删除字段条件了,需要手动添加 -->
<select id="selectGoodsPages" resultType="com.example.springbootdemo2023.mybatis.domain.goods.TGoods">
select * from t_goods
<where>
<if test="goods.name!=null and goods.name!=''">
and name like '%${goods.name}%'
</if>
</where>
</select>
测试实现
page.setPage(1);//第一页
page.setSize(2);//每页显示2行
MyPager<TGoods> pager = new MyPager<>();
TGoods tGoods = new TGoods();
tGoods.setName("P");// 查询name中包含P的商品条件
IPage<TGoods> tGoodsIPage = goodsMapper.selectGoodsPages(PageDTO.of(page.getPage(), page.getSize()), tGoods);
List<TGoods> records = tGoodsIPage.getRecords();//分页的结果
long total = tGoodsIPage.getTotal();//不分页所有数据的行数
pager.setPageSize(page.getSize());
pager.setRows(records);
pager.setTotal(total);
pager.setPage(page.getPage());
15.MyBatis-plus代码生成器
生成:
controller类、service接口、service实现类、数据库映射实体类、mapper接口和mapper.xmlsql映射文件
1. 引入freemarker框架依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
2.引入mybatis-plus代码生成工具包
<!-- mp代码生成器 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.2</version>
</dependency>
3.编写一个代码生成器
private final static String URL = "jdbc:mysql://localhost:3306/familydb?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai";
private final static String USER_NAME = "root";
private final static String PWD = "cxk666";
private final static String AUTHOR = "GaoJingBo";
private final static String OUT_PUT_DIR = "D://mybatis";
private final static String PARENT_PACKAGE_NAME = "com.gdones.fmbase.business";
private final static String PARENT_MODEL_NAME = "ckt";
private final static String TABLE_NAME = "t_ckt_designes";
private final static String PREFIX = "t_";
public static void main(String[] args) {
FastAutoGenerator.create(URL, USER_NAME, PWD)
.globalConfig(builder -> {
builder.author(AUTHOR) // 设置作者
.enableSwagger() // 开启 swagger 模式
.fileOverride() // 覆盖已生成文件
.dateType(DateType.ONLY_DATE)// 日期类型
.commentDate("yyyy-MM-dd") //公共默认日期格式
.outputDir(OUT_PUT_DIR); // 指定输出目录
})
.packageConfig(builder -> {
builder.parent(PARENT_PACKAGE_NAME) //设置父路径根包
.moduleName(PARENT_MODEL_NAME) //设置模块名称
.entity("dto") //dto实体
.service("service") //业务接口
.serviceImpl("service.impl") //业务实现
.mapper("mapper") //mybatis-plus-mapper接口
.xml("mapper.xml") mybatis-plus-mapper接口映射xml
.controller("controller") //控制器
.other("other");
})
.strategyConfig(builder -> {
builder.controllerBuilder()
.enableHyphenStyle()
.enableRestStyle();
builder.mapperBuilder()
.enableMapperAnnotation();
builder.entityBuilder()
.enableLombok()
.logicDeleteColumnName("isDelete")// 逻辑删除表字段名
.logicDeletePropertyName("isDelete")// 逻辑删除实体属性名
// 添加填充规则
.addTableFills(new Column("insertTime", FieldFill.INSERT))
.addTableFills(new Column("updateTime", FieldFill.INSERT_UPDATE))
.idType(IdType.NONE);
builder.addInclude(TABLE_NAME) // 设置需要生成的表名
.enableSkipView()//跳过视图
.addTablePrefix(PREFIX); // 设置过滤表前缀
})
.templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
.execute();
4. 完整的使用方法
1. 将生成的代码拷贝到根包下
2. 修改mybatis-plus-mapper以及xml映射规则路径
#mybatis-plus配置
mybatis-plus:
#dto别名映射 !!!!!!!!!
type-aliases-package: com.example.springbootdemo2023.bus.**.dto
#xml文件路径映射(xml文件要和接口文件同名) !!!!!!!
mapper-locations: classpath*:com/example/springbootdemo2023/bus/dao/**/mapper/*.xml
3. 修改启动类上MapperSacn的路径
@MapperScan("com.example.springbootdemo2023.bus.**.mapper") !!!!!
@SpringBootApplication
public class SpringBootDemo2023Application {
。。。
4. 检查一下你的包结构
5.编写代码-Controller为入口编写
@RestController
@RequestMapping("/goods/goods")
public class GoodsController {
@Resource(name = "goodsServiceImpl")
private IGoodsService goodsService;
@GetMapping("/getGoodsByID")
public MyResult getGoodDataByGoodID(String id){
MyResult result = new MyResult();
// 调用代码生成器生成的方法,业务层零代码直接可以实现增删改查
Goods byId = goodsService.getById(id);
result.setData(byId);
return result;
}
}