<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--lombok用来简化实体类-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
引入mybatisplus 后就不需要引入mybatis和mybatis-spring了
lombok还需要安装插件才能使用
在application.properties里
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis-plus?serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=root
使用这个mysql8的驱动url需要加上时区
项目结构
启动类上需要加上
@MapperScan("com.xu.mpdemo1010.mapper")
这样就不需要在每一个mapper接口上加@Mapper了
mapper接口继承BaseMapper接口,就可以使用mybatisplus为我们提供的很多数据库操作的方法,只有特别复杂的sql才需要自己编写xml文件
public interface UserMapper extends BaseMapper<User>
service接口需要继承IService接口,并且接口的实现类还需继承ServiceImpl<xxxMapper,泛型类>,同样为我们提供了很多方法来使用。(若实现类不继承,那么需要重写所有的方法,很不方便)
service的实现类上需要加注解@Service交给spring容器管理,@Autowired注入XxxMapper,
return xxxMapper.方法
在controller需要加上@Controller注解用于页面跳转,或者@Restcontroller用于返回数据
@Autowired注入XxxService,调用方法
mybatisplus自带的主键生成策略
id是string类型就用下面那个
mp的自动填充功能
表加上create_time和update_time两个字段
第一步添加实体类属性及注解:
@TableField(fill = FieldFill.INSERT)//直接自动填充时间
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
第二步创建一个类实现MetaObjectHandler接口并重写方法
类上加@Component交给ioc容器管理
@Component//交给spring管理
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);
}
}
乐观锁
表加version字段,默认为1
原理:提交事务之前需比较当前版本号和数据库的版本号是否相同,不相同则不能修改。
还需将版本号加1,这样若是有正在拿相同版本号修改的人就改不了了,因为版本号加1了
第一步实体类加@Version
@Version
@TableField(fill = FieldFill.INSERT)//去方法里添加一个默认值1
private Integer version;//版本号(用于乐观锁)
第二步编写一个配置类引入乐观锁插件
@Configuration//配置类
public class MpConfig {
/**
* 乐观锁插件
*/
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
}
也可以将启动类上面的
@MapperScan("com.xu.mpdemo1010.mapper")//扫描mapper包
放到这个配置类上,效果相同
第三步在实体类的属性version上加上,为了实现自动填充功能
@TableField(fill = FieldFill.INSERT)
第四步在上面讲到的自动填充功能的类中给version一个默认值1
@Component//交给spring管理
public class MyMetaObjectHandler implements MetaObjectHandler {
//使用mp实现添加操作时这个方法执行
@Override
public void insertFill(MetaObject metaObject) {
this.setFieldValByName("createTime", new Date(), metaObject);//三个参数属性名,属性值,源数据
this.setFieldValByName("updateTime", new Date(), metaObject);
this.setFieldValByName("version", 1, metaObject);
}
//使用mp实现修改操作时这个方法执行
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updateTime", new Date(), metaObject);
}
}
分页
第一步在mp的配置类里引入分页插件
/**
*分页插件
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
第二步
new一个page对象传入当前页和每页记录数(可以加泛型)
xxxService.Page(page,条件),得到的数据都存在page里(下面的实例没用到service层,只是测试)
//分页查询(通过分页插件)
@Test
public void testPage() {
Page<User> page = new Page<>(1,3);//第一个参数是当前页,第二个参数是记录数
//调用分页查询方法,在查询过程中底层会将查到的数据封装到page对象中
userMapper.selectPage(page, null);
//通过page对象获取分页数据
System.out.println(page.getCurrent());//当前页
System.out.println(page.getRecords());//每页数据list集合
System.out.println(page.getSize());//每页显示记录数
System.out.println(page.getTotal());//总记录数
System.out.println(page.getPages());//总页数
System.out.println(page.hasNext());//是否有下一页
System.out.println(page.hasPrevious());//是否有上一页
}
逻辑删除(加入这个功能以后进行删除操作就不删除数据而是置1,同样的mp框架自动在查询的时候不查1的数据)
(表中数据仍存在,但是处于删除状态无法查到)
第一步表中加入deleted字段
第二步实体类属性上加上注解
@TableLogic//这个注解代表逻辑删除 @TableField(fill = FieldFill.INSERT) private Integer deleted;
第三步在自动填充功能里加上(默认0表示未删除,1表示已删除)
这部分可以通过数据库对字段加默认值实现,两者取其一
this.setFieldValByName("deleted", 0, metaObject);
#逻辑删除字段为0表示未删除,1表示删除,0和1是默认值,下面两句可不写可用于自定义值 #mybatis-plus.global-config.db-config.logic-delete-value=1 #mybatis-plus.global-config.db-config.logic-not-delete-value=0
第四步配置类加入逻辑删除插件
/**
*逻辑删除插件
*/
@Bean
public ISqlInjector sqlInjector() {
return new LogicSqlInjector();
}
如果需要查逻辑删除已删除的数据,只能通过自己写xml文件写sql语句来查,用mp提供的查不了
性能分析插件
第一步引入性能分析插件
/**
* SQL 执行性能分析插件
* 开发环境使用,线上不推荐。 maxTime 指的是 sql 最大执行时长
*dev开发环境
*test测试环境
*prod生产环境
*/
@Bean
@Profile({"dev","test"})// 设置 dev test 环境开启
public PerformanceInterceptor performanceInterceptor() {
PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
performanceInterceptor.setMaxTime(500);//ms,超过此处设置的ms则sql不执行
performanceInterceptor.setFormat(true);
return performanceInterceptor;
}
第二步设置当前环境为dev开发环境
#环境设置:dev、test、prod spring.profiles.active=dev
wapper条件选择器
wapper是一个抽象类,通常用他的实现类queryWapper
测试
//mp实现复杂查询操作
@Test
public void testSelectQuery() {
//创建querywrapper对象
QueryWrapper<User> wrapper = new QueryWrapper<>();
//通过wrapper设置条件
//ge,gt,le,lt >= > <= <
//查询age>=30
// wrapper.ge("age", 30);//第一个参数字段,第二个参数值
// List<User> users = userMapper.selectList(wrapper);
// System.out.println(users);
//eq,ne = !=
// wrapper.eq("name", "Sandy");
// List<User> users = userMapper.selectList(wrapper);
// System.out.println(users);
//between
// wrapper.between("age", 20, 30);
// List<User> users = userMapper.selectList(wrapper);
// System.out.println(users);
//like
// wrapper.like("name", "S");
// List<User> users = userMapper.selectList(wrapper);
// System.out.println(users);
//orderbydesc
// wrapper.orderByDesc("id");
// List<User> users = userMapper.selectList(wrapper);
// System.out.println(users);
//last拼接语句
// wrapper.last("limit 1");
// List<User> users = userMapper.selectList(wrapper);
// System.out.println(users);
//查询指定的列
wrapper.select("id", "name");//只查所写字段
List<User> users = userMapper.selectList(wrapper);
System.out.println(users);
}
}
mp提供的代码生成器
第一步引入依赖(版本号自己找)
<!-- velocity 模板引擎, Mybatis Plus 代码生成器需要 --> <dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity-engine-core</artifactId> </dependency>
第二步执行代码
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import org.junit.Test;
/**
* @author
* @since 2018/12/13
*/
public class CodeGenerator {
@Test
public void run() {
// 1、创建代码生成器
AutoGenerator mpg = new AutoGenerator();
// 2、全局配置,加上项目的绝对路径
GlobalConfig gc = new GlobalConfig();
String projectPath = System.getProperty("user.dir");
gc.setOutputDir("D:\\Spring\\gulischool\\guli_parent\\service\\service_edu" + "/src/main/java");
gc.setAuthor("testjava");
gc.setOpen(false); //生成后是否打开资源管理器
gc.setFileOverride(false); //重新生成时文件是否覆盖
gc.setServiceName("%sService"); //去掉Service接口的首字母I
gc.setIdType(IdType.ID_WORKER_STR); //主键策略,这个表主键是字符类型,如果是long类型就不需要加_STR
gc.setDateType(DateType.ONLY_DATE);//定义生成的实体类中日期类型
gc.setSwagger2(true);//开启Swagger2模式
mpg.setGlobalConfig(gc);
// 3、数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://localhost:3306/guli?serverTimezone=GMT%2B8");
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("root");
dsc.setDbType(DbType.MYSQL);
mpg.setDataSource(dsc);
// 4、包配置
PackageConfig pc = new PackageConfig();
pc.setParent("com.xu");
pc.setModuleName("eduservice"); //模块名
pc.setController("controller");
pc.setEntity("entity");
pc.setService("service");
pc.setMapper("mapper");
mpg.setPackageInfo(pc);
// 5、策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setInclude("edu_comment");//表名
strategy.setNaming(NamingStrategy.underline_to_camel);//数据库表映射到实体的命名策略
strategy.setTablePrefix(pc.getModuleName() + "_"); //生成实体时去掉表前缀
strategy.setColumnNaming(NamingStrategy.underline_to_camel);//数据库表字段映射到实体的命名策略
strategy.setEntityLombokModel(true); // lombok 模型 @Accessors(chain = true) setter链式操作
strategy.setRestControllerStyle(true); //restful api风格控制器
strategy.setControllerMappingHyphenStyle(true); //url中驼峰转连字符
mpg.setStrategy(strategy);
// 6、执行
mpg.execute();
}
}
注解
1.表名注解
@TableName("表名")用在实体类上面
2.主键注解
@TableId![](https://i-blog.csdnimg.cn/blog_migrate/c4bf625f4048878e9fb3484e2dd5d76c.png)
3.字段注解