1.application.properties的图标没有变成绿叶,把这个文件复制到target/classes下即可
2.mybatis查看详细mysql执行过程
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
3.主键的生成策略:
id自增:常用的策略,但是当数据量较为庞大的时候,我们会采用分表存入数据,此时每个表采用自增策略需要查询上一张表的最后一个id,不太方便;
uuid:每次生成随机唯一的值,缺点是排序不方便,不利于检索;
redis生成步进id:第一台机器生成1,6,11,16,21;第二台机器生成2,7,12,17,22;第三台机器生成3,8,13,18,23;第四台机器4,9,14,19,24;第五台机器生成5,10,15,20,25,这也是分表比较常用的方法;
mybatis-plus自带生成策略:雪花算法生成的id,数据中心id+机器id+毫秒流水号(1毫秒可以产生4096个随机id)+符号位(0)
4.自动填充字段,例如create_time与update_time
bean里设置字段
import java.util.Date;
@Data
public class Director {
@TableId
private Integer directorId;
@TableField(fill = FieldFill.INSERT)
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
}
实现元对象句柄MetaObjectHandler
//交给spring容器管理
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
//使用mp实现添加操作则自动执行这个方法
@Override
public void insertFill(MetaObject metaObject) {
this.setFieldValByName("createTime", new Date(), metaObject);
this.setFieldValByName("updateTime", new Date(), metaObject);
}
//使用mp实现修改操作则自动执行这个方法
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updateTime", new Date(), metaObject);
}
}
执行方法
@Test
void updateDir(){
Director director = new Director();
director.setBirthYear("1985");
director.setDirectorId(2);
int i = directorMapper.updateById(director);
System.out.println(i);
}
5.mybatis-plus实现乐观锁
表字段加个version
bean加字段
@Version
private Integer version;
配置乐观锁插件
@Configuration
@MapperScan("com.moviemanage.mapper") //放在配置类里面代码更简洁
public class MpConfig {
//旧版本写法
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
}
测试
//测试乐观锁
@Test
void optimisticTest(){
//先查询再修改
Director director = directorMapper.selectById(7);
director.setName("宁浩");
int i = directorMapper.updateById(director);
System.out.println(i);
}
6.分页查询
配置分页插件
@Configuration
@MapperScan("com.moviemanage.mapper")
public class MpConfig {
//乐观锁插件
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
//分页插件
@Bean
public PaginationInterceptor paginationInterceptor(){
return new PaginationInterceptor();
}
}
调用
@Test
void testPage(){
//创建page对象
Page<Director> objectPage = new Page<>(1, 3);
//调用mybatisPlus的分页查询方法,把分页的所有数据封装到page对象中
directorMapper.selectPage(objectPage,null);
System.out.println(objectPage.getCurrent()); //当前页
System.out.println(objectPage.getRecords()); //当前页list集合
System.out.println(objectPage.getSize()); //每页的记录数
System.out.println(objectPage.getTotal()); //所有记录数
System.out.println(objectPage.getPages()); //总页数
System.out.println(objectPage.hasNext()); //是否有下一页
System.out.println(objectPage.hasPrevious()); //是否有上一页
}
7.虚拟删除
配置类里面添加插件
//逻辑删除插件
@Bean
public ISqlInjector sqlInjector(){
return new LogicSqlInjector();
}
先在表字段添加deleted字段,0没删除,1删除,默认0;
在实体类添加deleted字段
@TableLogic
private Integer deleted;
测试
@Test
void delete(){
int deleteBatchIds = directorMapper.deleteBatchIds(Arrays.asList(10, 11));
System.out.println(deleteBatchIds);
}
8.mybatisPlus查询
@Test
void queryWarpperTest(){
QueryWrapper<Director> objectQueryWrapper = new QueryWrapper<>();
// objectQueryWrapper.ge("birth_year",1985);
// List<Director> directors = directorMapper.selectList(objectQueryWrapper);
// objectQueryWrapper.eq("birth_year",1985);
// objectQueryWrapper.ne("birth_year",1985);
// objectQueryWrapper.between("birth_year",1983,1985);
// objectQueryWrapper.like("name",2);
// objectQueryWrapper.orderByDesc("director_id");
// objectQueryWrapper.last("limit 1");
objectQueryWrapper.select("director_id","name");
List<Director> directors = directorMapper.selectList(objectQueryWrapper);
System.out.println(directors);
}
9.项目结构
10.扫描其他模块的组件
//Springboot默认只会扫描启动类所在包极其子包下的带有@Component注解的类
//添加包的扫描规则。使其能够扫描到com.ywxk包下的所有配置类,就能扫描到common模块下的service_base模块下的配置类
@ComponentScan(basePackages = {"com.ywxk"})
public class DirectorApplication {
public static void main(String[] args) {
SpringApplication.run(DirectorApplication.class,args);
}
}
11.lombok自动生成方法
@Data //lombok的data注解可以为属性自动添加get和set方法
@AllArgsConstructor //lombok自动生成有参构造方法
@NoArgsConstructor //lombok自动生成无参构造方法
public class SelfException extends RuntimeException{
private Integer code; //状态码
private String message; //信息
}
12.统一异常处理
/**
* 统一异常处理类
*/
@ControllerAdvice
public class GlobalExceptionHandler {
//统一处理
@ExceptionHandler(Exception.class) //出现任何异常都会执行这个方法
@ResponseBody //返回数据
public Result error(Exception e){
e.printStackTrace();
return Result.err().message("异常处理...");
}
//特定异常处理
@ExceptionHandler(ArithmeticException.class)
@ResponseBody
public Result error(ArithmeticException e){
e.printStackTrace();
return Result.err().message("除数不能为0");
}
//自定义异常处理
@ExceptionHandler(SelfException.class)
@ResponseBody
public Result error(SelfException e){
e.printStackTrace();
return Result.err().code(e.getCode()).message(e.getMessage());
}
}
13.logback日志
先注释mybatis-plus的日志设置
#设置日志级别
#logging.level.root=INFO
#mybatis日志
#mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
在resources文件夹下添加logback-spring.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="10 seconds">
<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 -->
<!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true -->
<!-- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
<!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
<contextName>logback</contextName>
<!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 -->
<property name="log.path" value="D:/movie_online/director" />
<!-- 彩色日志 -->
<!-- 配置格式变量:CONSOLE_LOG_PATTERN 彩色日志格式 -->
<!-- magenta:洋红 -->
<!-- boldMagenta:粗红-->
<!-- cyan:青色 -->
<!-- white:白色 -->
<!-- magenta:洋红 -->
<property name="CONSOLE_LOG_PATTERN"
value="%yellow(%date{yyyy-MM-dd HH:mm:ss}) |%highlight(%-5level) |%blue(%thread) |%blue(%file:%line) |%green(%logger) |%cyan(%msg%n)"/>
<!--输出到控制台-->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
<!-- 例如:如果此处配置了INFO级别,则后面其他位置即使配置了DEBUG级别的日志,也不会被输出 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<encoder>
<Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
<!-- 设置字符集 -->
<charset>UTF-8</charset>
</encoder>
</appender>
<!--输出到文件-->
<!-- 时间滚动输出 level为 INFO 日志 -->
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${log.path}/log_info.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 每天日志归档路径以及格式 -->
<fileNamePattern>${log.path}/info/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录info级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 时间滚动输出 level为 WARN 日志 -->
<appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${log.path}/log_warn.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/warn/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录warn级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>warn</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 时间滚动输出 level为 ERROR 日志 -->
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${log.path}/log_error.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录ERROR级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!--
<logger>用来设置某一个包或者具体的某一个类的日志打印级别、以及指定<appender>。
<logger>仅有一个name属性,
一个可选的level和一个可选的addtivity属性。
name:用来指定受此logger约束的某一个包或者具体的某一个类。
level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
如果未设置此属性,那么当前logger将会继承上级的级别。
-->
<!--
使用mybatis的时候,sql语句是debug下才会打印,而这里我们只配置了info,所以想要查看sql语句的话,有以下两种操作:
第一种把<root level="INFO">改成<root level="DEBUG">这样就会打印sql,不过这样日志那边会出现很多其他消息
第二种就是单独给mapper下目录配置DEBUG模式,代码如下,这样配置sql语句会打印,其他还是正常DEBUG级别:
-->
<!--开发环境:打印控制台-->
<springProfile name="dev">
<!--可以输出项目中的debug日志,包括mybatis的sql日志-->
<logger name="com.guli" level="INFO" />
<!--
root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性
level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,默认是DEBUG
可以包含零个或多个appender元素。
-->
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="INFO_FILE" />
<appender-ref ref="WARN_FILE" />
<appender-ref ref="ERROR_FILE" />
</root>
</springProfile>
<!--生产环境:输出到文件-->
<springProfile name="pro">
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="DEBUG_FILE" />
<appender-ref ref="INFO_FILE" />
<appender-ref ref="ERROR_FILE" />
<appender-ref ref="WARN_FILE" />
</root>
</springProfile>
</configuration>
14.将异常写入日志
/**
* 统一异常处理类
*/
@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
//统一处理
@ExceptionHandler(Exception.class) //出现任何异常都会执行这个方法
@ResponseBody //返回数据
public Result error(Exception e){
log.error(e.getMessage());
e.printStackTrace();
return Result.err().message("异常处理...");
}
}