Mybatis-Plus一般使用方法
一、什么是mybatis-plus
官网:https://mp.baomidou.com/guide/
mybatis-plus可以看作是mybatis的升级,对mybais没有做出任何改变,只是做出了升级,所以,他们具有良好的合作效率,mybatis-plus的定位就是做一个mybatis的好伙伴。
二、mybatis-plus的特点
使用mybatis-plus,可以开箱即用,减少了大量的代码,在对单表的操作中,基本可以让代码编辑者不用自己写dao层方法,就能对表实现操作。
三、分解解释
创建mybatis-plus项目
正常创建一个springboot项目,然后在pom.xml中导入mybatis-plus的依赖包,此时mybatis的依赖包就不用导入了,其他数据库连接等包正常依赖。项目结构如下
Ⅰ、导入依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>Latest Version</version>
</dependency>
Ⅱ、配置数据源
spring.datasource.druid.username=root
spring.datasource.druid.password=root
spring.datasource.druid.url=jdbc:mysql:///test
spring.datasource.druid.driver-class-name=com.mysql.jdbc.Driver
Ⅲ、创建实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
// 以下注解后文解释
@TableId(type=IdType.AUTO)
private Long id;
private String name;
private Integer age;
private String email;
@TableField(fill = FieldFill.INSERT)
private Date gmt_created;//创建时间
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date gmt_updated;//更改时间
@TableLogic
private Integer isdeleted;//逻辑删除字段
Ⅳ、创建dao,dao层必须要继承mybatis-plus的BaseMapper
public interface UserDao extends BaseMapper<User> {
}
Ⅴ、启动类上加包扫描
@SpringBootApplication
@MapperScan("com.fy.demo.dao")
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
Ⅵ、查询测试
①、无参查询
@Test
public void selectNoArg(){
// null处为queryWrapper:条件构造器。下文介绍
List<User> users = userDao.selectList(null);
System.out.println(users);
}
②、分页查询
首先先构造一个分页查询拦截器·
@Configuration
public class MybatisPlusConfig {
// 最新版
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
测试
@Test
public void fenye(){
// page类是分页查询需要的参数,类中构造两个参数,current:当前页 size:每页的条数
Page page=new Page(1,2);
Page page1 = userDao.selectPage(page, null);
System.out.println(page1.getRecords());
}
③、使用Wrapper(条件构造器)查询
@Test
public void selectWrapper(){
User user = new User();
user.setName("宁姚");
QueryWrapper queryWrapper = new QueryWrapper();
// 查询name=宁姚的
queryWrapper.eq("name","宁姚");
List list = userDao.selectList(queryWrapper);
System.out.println(list);
// 模糊查询
if(StringUtils.isNotEmpty(user.getName())){
queryWrapper.like("name","宁");
}
List list = userDao.selectList(queryWrapper);
System.out.println(list);
}
Ⅶ、新增测试
@Test
public void mp(){
//新增功能中有两个点,一个是主键的新增方法,一个是自动填充
//1、设置主键的新增方式:在实体类中添加@TableId(type=IdType.AUTO),注解的值有AUTO:自增,ASSIGN_ID:雪花id,官网有详细解释
//2、自动填充:自动填充可以在新增和更改时发挥作用。主要用于对数据的新增和更改信息时标记操作的时间。在实体类中加@TableField(),取值请参考官网。还需要添加配置类,请看下文(是从官网上参考的)
User user = new User();
user.setName("NINGYAO");
user.setAge(18);
user.setEmail("219331@qq.com");
userDao.insert(user);
List<User> users = userDao.selectList(null);
System.out.println(users);
}
字段自动填充的配置类:
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
this.strictInsertFill(metaObject, "gmt_created", Date.class, new Date()); // 起始版本 3.3.0(推荐使用)
// 或者
this.strictUpdateFill(metaObject, "gmt_updated", Date.class, new Date()); // 起始版本 3.3.3(推荐)
}
@Override
public void updateFill(MetaObject metaObject) {
this.strictUpdateFill(metaObject, "gmt_updated", Date.class, new Date()); // 起始版本 3.3.0(推荐)
}
}
Ⅷ、修改功能
@Test
public void upDATE(){
/*更改信息可以使用自动填充功能,如果数据库中存在更改时间和新增时间这种字段,就可以使用自动
填充功能来对时间字段进行在操作时自动更改*/
/*自动填充
* 1、实体类需要自动填充的字段加注解 @TableField()
* 2、加配置类
* */
User user = new User();
user.setId(1L);
user.setName("宁姚");
userDao.updateById(user);//该更新用了动态sql,只更改传入的实体类中有的字段
}
Ⅸ、删除功能
删除包含两种删除:物理删除和逻辑删除。物理删除就是从表中删除这条数据。逻辑删除是改变数据的状态,让这个数据查询不到。
①物理删除
@Test
// 物理删除
public void delETE(){
userDao.deleteById(2L);
}
②逻辑删除
逻辑删除需要先配置:
1、配置注解:在实体类中需要更改的字段上添加注解@TableLogic,这样再执行删除时,就会是更改字段的值
2、添加配置文件的配置,在properties文件中添加以下配置
#逻辑删除 0代表已经删除,1代表没有删除
mybatis-plus.global-config.db-config.logic-delete-value=0
mybatis-plus.global-config.db-config.logic-not-delete-value=1
@Test
// 逻辑删除
public void deleteLogic(){
/*
逻辑删除:
1、在需要逻辑删除的字段名上加注解
2、在配置文件中设置逻辑删除的默认值
*/
userDao.deleteById(4L);
}
四、Mybatis-plus代码生成器
(1)、项目结构
(2)、导入依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.3</version>
</dependency>
(3)、codeGenerator.java
执行main方法即可:
public class codeGenerator {
/**
* <p>
* 读取控制台内容
* </p>
*/
// 不执行该方法
public static String scanner(String tip) {
Scanner scanner = new Scanner(System.in);
StringBuilder help = new StringBuilder();
help.append("请输入" + tip + ":");
System.out.println(help.toString());
if (scanner.hasNext()) {
String ipt = scanner.next();
if (StringUtils.isNotBlank(ipt)) {
return ipt;
}
}
throw new MybatisPlusException("请输入正确的" + tip + "!");
}
public static void main(String[] args) {
// 代码生成器
AutoGenerator mpg = new AutoGenerator();
// 全局配置
GlobalConfig gc = new GlobalConfig();
String projectPath = System.getProperty("user.dir");//当前工程路径
gc.setOutputDir(projectPath + "/src/main/java");
gc.setAuthor("fy");
// 设置service的接口名
gc.setServiceName("%sService");
// 设置dao接口文件名
gc.setMapperName("%sDao");
gc.setOpen(false);
gc.setSwagger2(true); //实体属性 Swagger2 注解
mpg.setGlobalConfig(gc);
// 数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://localhost:3306/test?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai");
// dsc.setSchemaName("public");
dsc.setDriverName("com.mysql.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("root");
mpg.setDataSource(dsc);
// 包配置
PackageConfig pc = new PackageConfig();
pc.setModuleName("demo");
pc.setParent("com.fy");
pc.setMapper("dao");
mpg.setPackageInfo(pc);
// 自定义配置
InjectionConfig cfg = new InjectionConfig() {
@Override
public void initMap() {
// to do nothing
}
};
// 如果模板引擎是 velocity
String templatePath = "/templates/mapper.xml.vm";
// 自定义Mapper文件的输出配置
List<FileOutConfig> focList = new ArrayList<>();
// 自定义配置会被优先输出
focList.add(new FileOutConfig(templatePath) {
@Override
public String outputFile(TableInfo tableInfo) {
// 自定义输出文件名及输入路径 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
return projectPath + "/src/main/resources/mapper/"
+ tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
}
});
/*
cfg.setFileCreate(new IFileCreate() {
@Override
public boolean isCreate(ConfigBuilder configBuilder, FileType fileType, String filePath) {
// 判断自定义文件夹是否需要创建
checkDir("调用默认方法创建的目录,自定义目录用");
if (fileType == FileType.MAPPER) {
// 已经生成 mapper 文件判断存在,不想重新生成返回 false
return !new File(filePath).exists();
}
// 允许生成模板文件
return true;
}
});
*/
cfg.setFileOutConfigList(focList);
mpg.setCfg(cfg);
/*// 配置模板
TemplateConfig templateConfig = new TemplateConfig();
// 配置自定义输出模板
//指定自定义模板路径,注意不要带上.ftl/.vm, 会根据使用的模板引擎自动识别
templateConfig.setXml(null);
mpg.setTemplate(templateConfig);*/
// 策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setNaming(NamingStrategy.underline_to_camel);
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
strategy.setEntityLombokModel(true);
strategy.setRestControllerStyle(true);//controller是否使用restful风格
mpg.setStrategy(strategy);
mpg.execute();
}
}
(4) 遇到的异常(可能出现)
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested
exception is org.springframework.dao.InvalidDataAccessApiUsageException: Error attempting to get column 'gmt_create' from result set. Cause:
java.sql.SQLFeatureNotSupportedException; null; nested exception is java.sql.SQLFeatureNotSupportedException] with root cause
根据提示报错可知:是gmt_create字段处的问题,我检查了数据库,发现数据类型是DateTime,而生成的实体类中类型是LocalDateTime,这是java8中的API。数据类型匹配出现了错误。
问题解决:
第一种方式:
将实体类中的事件类型改成Date
第二种方式:
在代码生成器的文件中加入:
gc.setDateType(DateType.ONLY_DATE);
DateType的取值(官方底层代码):
public enum DateType {
/**
* 只使用 java.util.date 代替
*/
ONLY_DATE,
/**
* 使用 java.sql 包下的
*/
SQL_PACK,
/**
* 使用 java.time 包下的
* <p>java8 新的时间类型</p>
*/
TIME_PACK
}