Mybatis plus
1.查询没找到请求参数
Parameter 'pageNum' not found. Available parameters are [arg1, arg0, param3, param1, param2, username]
原因:
Mapper文件中都要加上 @Param("pageNum")
@Select("SELECT * FROM user where username like #{username} limit #{pageNum},#{pageSize}")List<User> selectPage(@Param("pageNum")Integer pageNum, @Param("pageSize") Integer pageSize,@Param("username") String username);
2.增加字段
数据表增加带线划线的
回到entity增加驼峰,并命名
@TableField(value="avatar_url") private String avatarUrl;
之后重启idea即可更新成功
3.报错
改造Usercontroller
package com.i7i8i9.eleven.controller;import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.i7i8i9.eleven.entity.User;
import com.i7i8i9.eleven.mapper.UserMapper;
import com.i7i8i9.eleven.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;@RestController
@RequestMapping("/user")
public class UserController {@Autowiredprivate UserMapper userMapper;@Autowiredprivate UserService userService;// PostMapping RequestBody可以把前台传来的json数据变成后台java对象// 使用mybatis plus 返回有Integer变为boolean@PostMappingpublic boolean save(@RequestBody User user){ //返回条数return userService.saveUser(user);}// GetMapping是为了浏览器请求后,从数据库获取数据,List<User>表示返回数组@GetMapping //get接口表示根据浏览器请求返回数据public List<User> index(){
// List<User> all=userMapper.findAll();
// mybatis-plusreturn userService.list();}@DeleteMapping("/{id}")public boolean delete(@PathVariable Integer id){ //本处的参数id 与@deletemapping路径里面的一致// return userMapper.deleteByID(id);// mybatis-plusreturn userService.removeById(id);}
// 分页查询
// 请求路径会是组合 /user?pageNum=1&pageSize=10
// RequestParam会接收 ?pageNum=1&pageSize=10这样的数据,并把1和10传给形参
//@GetMapping("/page") //get接口表示根据浏览器请求返回数据
//public Map<String, Object> findPage(@RequestParam Integer pageNum,
// @RequestParam Integer pageSize,
// @RequestParam String username){
// pageNum=(pageNum-1)*pageSize; //limit第一个参数
// username="%"+username+"%";
// List<User> data=userMapper.selectPage(pageNum,pageSize,username);
// Integer total=userMapper.selectTotal(username); //查询总条数
// Map<String, Object> res=new HashMap<>();
// res.put("data",data);
// res.put("total",total);
// return res ;
//}//mybatis plus分页查询@GetMapping("/page") //get接口表示根据浏览器请求返回数据public IPage<User> findPage(@RequestParam Integer pageNum,
// public Map<String, Object> findPage(@RequestParam Integer pageNum,@RequestParam Integer pageSize,@RequestParam String username){IPage<User> page=new Page<>(pageNum,pageSize);QueryWrapper<User> queryWrapper=new QueryWrapper<>();IPage<User> userPage=userService.page(page, queryWrapper);return userPage;}
}
Parameter 'username' not found. Available parameters are [ew, page, param1, param2]
原因是UserMapper中出现了与Mabatis-plus同样的方法名
selectPage
改造UserMapper,几乎不用
package com.i7i8i9.eleven.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.i7i8i9.eleven.entity.User;
import org.apache.ibatis.annotations.*;import java.util.List;//专门用于跟数据库交互用
//@Mapper //通过Mapper注入mapper接口,但不应该在这里注入,应该在 MybatisPlusConfig中注入
public interface UserMapper extends BaseMapper<User> {
// 使用mybatis注解
//@Select("SELECT * FROM sys_user")
// List<User> findAll();
//@Insert("INSERT INTO user(username,password,nickname,email,phone,address)" +
// "values (#{username},#{password},#{nickname},#{email},#{phone},#{address});")
// int insert(User user);
//
//
修改@Update("Update sys_user set username=#{username},password=#{password}," +"nickname=#{nickname},email=#{email},phone=#{phone},address=#{address} where id=#{id};")
// //注意int不是void
// int update(User user);
// @Delete("delete from sys_user where id=#{id} ")
// Integer deleteByID(@Param("id") Integer id); //让框架知道参数叫什么名字分页
// @Select("SELECT * FROM user where username like #{username} limit #{pageNum},#{pageSize}")
// List<User> selectPage(@Param("pageNum")Integer pageNum, @Param("pageSize") Integer pageSize,@Param("username") String username);
//查询总条数
// @Select("SELECT count(*) FROM user where username like #{username}")
// Integer selectTotal(String username);
}
另外以下resources/mapper xml也不要有与Mabatis-plus重名的
成功后返回的是records,相当于以前的data
{"records": [{"id": 2,"username": "libai","nickname": "李白","email": "libai@qq.com","phone": "13245679899","address": "陕西西安","avatarUrl": null},{"id": 3,"username": "liqingzhao245","nickname": "杜甫","email": "dufu@qq.com","phone": "13456778899","address": "四川成都","avatarUrl": "ddd"},{"id": 5,"username": "admin","nickname": "管理员","email": "admin@qq.com","phone": "13256789988","address": "北京","avatarUrl": null}],"total": 12,"size": 3,"current": 1,"orders": [],"optimizeCountSql": true,"searchCount": true,"countId": null,"maxLimit": null,"pages": 4
4.日志
application.yml中开启日志
mybatis-plus:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
后端控制台中Preparing就是语句
Swagger
这是springfox-swagger
配置
1.参考 SpringBoot集成swagger-ui以及swagger分组显示_swagger-ui@5.10.5 postinstall: `patch-package`-CSDN博客注意修改
.apis(RequestHandlerSelectors.basePackage("com.i7i8i9.eleven.controller"))
public Docket restApi() {return new Docket(DocumentationType.SWAGGER_2).groupName("标准接口").apiInfo(apiInfo("Spring Boot中使用Swagger2构建RESTful APIs", "1.0")).useDefaultResponseMessages(true).forCodeGeneration(false).select().apis(RequestHandlerSelectors.basePackage("com.i7i8i9.eleven.controller"))
启动
报错空指针
Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException
启动类上增加@EnableWebMvc
@EnableWebMvc
@SpringBootApplication
public class ElevenApplication {public static void main(String[] args) {SpringApplication.run(ElevenApplication.class, args);}}
http://localhost:9090/swagger-ui.html
swagger页面无法访问,
No mapping for GET /swagger-ui.html
一般说是因为
#springboot2.6.x的版本中springmvc默认路径匹配策略从ANT_PATH_MATCHER变更为PATH_PATTERN_PARSER 进而导致无法访问swagger-ui.html mvc:pathmatch:matching-strategy: ANT_PATH_MATCHER
但是改了也没有用,参考https://www.cnblogs.com/luoking/p/16032349.html
查询到加了@EnableWebMvc,需要修改swaggerConfig增加 implements WebMvcConfigurer
以及重写addResourceHandlers方法
@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");WebMvcConfigurer.super.addResourceHandlers(registry);}
修改后的配置文件
package com.i7i8i9.eleven.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;@Configuration
@EnableSwagger2
public class swaggerConfig implements WebMvcConfigurer {@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");WebMvcConfigurer.super.addResourceHandlers(registry);}/*** 创建API应用* apiInfo() 增加API相关信息* 通过select()函数返回一个ApiSelectorBuilder实例,用来控制哪些接口暴露给Swagger来展现,* 本例采用指定扫描的包路径来定义指定要建立API的目录。** @return*/@Beanpublic Docket restApi() {return new Docket(DocumentationType.SWAGGER_2).groupName("标准接口").apiInfo(apiInfo("Spring Boot中使用Swagger2构建RESTful APIs", "1.0")).useDefaultResponseMessages(true).forCodeGeneration(false).select().apis(RequestHandlerSelectors.basePackage("com.i7i8i9.eleven.controller")).paths(PathSelectors.any()).build();}/*** 创建该API的基本信息(这些基本信息会展现在文档页面中)* 访问地址:http://ip:port/swagger-ui.html** @return*/private ApiInfo apiInfo(String title, String version) {return new ApiInfoBuilder().title(title).description("更多请关注: https://blog.csdn.net/xqnode").termsOfServiceUrl("https://blog.csdn.net/xqnode").contact(new Contact("xqnode", "https://blog.csdn.net/xqnode", "xiaqingweb@163.com")).version(version).build();}
}
使用
打开user-controller
输入参数,点击try it out
版本升级
https://mvnrepository.com/search?q=springfox-swagger
先升级到2.10.5 报错,放弃
再升级到3.0.0
注释和新增
<!--swagger2.7-->
<!-- <dependency>-->
<!-- <groupId>io.springfox</groupId>-->
<!-- <artifactId>springfox-swagger2</artifactId>-->
<!-- <version>2.7.0</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>io.springfox</groupId>-->
<!-- <artifactId>springfox-swagger-ui</artifactId>-->
<!-- <version>2.7.0</version>-->
<!-- </dependency>--><dependency><groupId>io.springfox</groupId><artifactId>springfox-boot-starter</artifactId><version>3.0.0</version></dependency>
修改 swaggerConfig,网上找的参考太复杂,重新去
Springfox Reference Documentation
查看以下配置简单了很多
package com.i7i8i9.eleven.config;import org.springframework.util.StringUtils;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;public class SwaggerUiWebMvcConfigurer implements WebMvcConfigurer {private final String baseUrl;public SwaggerUiWebMvcConfigurer(String baseUrl) {this.baseUrl = baseUrl;}@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {String baseUrl = StringUtils.trimTrailingCharacter(this.baseUrl, '/');registry.addResourceHandler(baseUrl + "/swagger-ui/**").addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/").resourceChain(false);}@Overridepublic void addViewControllers(ViewControllerRegistry registry) {registry.addViewController(baseUrl + "/swagger-ui/").setViewName("forward:" + baseUrl + "/swagger-ui/index.html");}
}
访问网址
http://localhost:9090/swagger-ui/index.html
使用方法
先点Try it out,在输入参数,
再点execute
代码生成器
参考 Mybatis-Plus自动生成代码,自定义Controller_mybatisplus ${package.controller} 修改-CSDN博客
引入包
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId><version>3.5.1</version>
</dependency>
还有velocity 这个java模版引擎
https://mvnrepository.com/search?q=velocity
<dependency><groupId>org.apache.velocity</groupId><artifactId>velocity-engine-core</artifactId><version>2.3</version>
</dependency>
增加目录和文件
package com.i7i8i9.eleven.utils;import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;import java.sql.Types;
import java.util.Collections;//mp代码生成器
public class CodeGenerator {public static void main(String[] args) {generate();}private static void generate(){
// 1 要更换url为数据库urlFastAutoGenerator.create("jdbc:mysql://localhost:3306/test1?serverTimezone=GMT%2b8", "root", "123456").globalConfig(builder -> {builder.author("i7i8i9") // 设置作者.enableSwagger() // 开启 swagger 模式 因为本项目已经安装,故开启.fileOverride() // 覆盖已生成文件
// 2 可以指定为当前项目目录,到包上层.outputDir("D:\\src\\learn\\eleven\\src\\main\\java"); // 指定输出目录}).dataSourceConfig(builder -> builder.typeConvertHandler((globalConfig, typeRegistry, metaInfo) -> {int typeCode = metaInfo.getJdbcType().TYPE_CODE;if (typeCode == Types.SMALLINT) {// 自定义类型转换return DbColumnType.INTEGER;}return typeRegistry.getColumnType(metaInfo);})).packageConfig(builder -> {
// 3 设置父包名以及模块名builder.parent("com.i7i8i9.eleven") // 设置父包名.moduleName("") // 设置父包模块名,没有为空,如果生成的路径有两个斜杠,()可以写为null
// 4 设置mapper绝对路径,追后有两个\\.pathInfo(Collections.singletonMap(OutputFile.xml, "D:\\src\\learn\\eleven\\src\\main\\resources\\mapper\\")); // 设置mapperXml生成路径}).strategyConfig(builder -> {
// 5 设置要生成的表名builder.addInclude("user") // 设置需要生成的表// 6 设置根据表明要生成代码时忽略的字母比如 sys_user表,要葫芦sys.addTablePrefix("t_", "c_") // 设置过滤表前缀,意思.entityBuilder().enableLombok().enableFileOverride().controllerBuilder().enableFileOverride().controllerBuilder().enableHyphenStyle() //开启驼峰转字符,保证接口路径比如有/batch_ids.enableRestStyle()//不加在Controller会返回@Controller而不是 @RestController.mapperBuilder().enableFileOverride().serviceBuilder().enableFileOverride();})// .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板.execute();
}
}
报红参见,原因是版本不对
https://blog.csdn.net/weixin_43529394/article/details/131048976
使用前注意备份工程
运行:
代码自动生成运行方法
报错
Caused by: java.lang.ClassNotFoundException: freemarker.template.Configuration
原因是freemarker没有注释掉
// .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
代码生成逻辑:controller-->entity-->mapper-->service-->resoures mapper下xml
自动生成文件缺陷观察
运行后,有些包没有被重新生成,原因是fileOveride被取消
改成了:
.strategyConfig(builder -> {
// 5 设置要生成的表名builder.addInclude("user") // 设置需要生成的表// 6 设置根据表明要生成代码时忽略的字母比如 sys_user表,要忽略sys
//为了覆盖包.addTablePrefix("t_", "c_") // 设置过滤表前缀,意思.entityBuilder().enableLombok().enableFileOverride().controllerBuilder().enableFileOverride().mapperBuilder().enableFileOverride().serviceBuilder().enableFileOverride();
生成后的usercontroller几乎是空的
package com.i7i8i9.eleven.controller;import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.stereotype.Controller;/*** <p>* 前端控制器* </p>** @author i7i8i9* @since 2024-03-02*/
@Controller
@RequestMapping("/user")
public class UserController {}
对比原来的
package com.i7i8i9.eleven.controller;import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.i7i8i9.eleven.entity.User;
import com.i7i8i9.eleven.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;@RestController
@RequestMapping("/user")
public class UserController {//使用mabatis-plus后可以去掉
// @Autowired
// private UserMapper userMapper;@Autowiredprivate UserService userService;// PostMapping RequestBody可以把前台传来的json数据变成后台java对象// 使用mybatis plus 返回有Integer变为boolean@PostMappingpublic boolean save(@RequestBody User user){ //返回条数return userService.saveUser(user);}// GetMapping是为了浏览器请求后,从数据库获取数据,List<User>表示返回数组@GetMapping //get接口表示根据浏览器请求返回数据public List<User> index(){
// List<User> all=userMapper.findAll();
// mybatis-plusreturn userService.list();}@DeleteMapping("/{id}")public boolean delete(@PathVariable Integer id){ //本处的参数id 与@deletemapping路径里面的一致// return userMapper.deleteByID(id);// mybatis-plusreturn userService.removeById(id);}
//批量删除@PostMapping("/del/batch")public boolean deleteBatch(@RequestBody List<Integer> ids){ //本处的参数id 与@deletemapping路径里面的一致// return userMapper.deleteByID(id);// mybatis-plusreturn userService.removeBatchByIds(ids);}
// 分页查询
// 请求路径会是组合 /user?pageNum=1&pageSize=10
// RequestParam会接收 ?pageNum=1&pageSize=10这样的数据,并把1和10传给形参
//@GetMapping("/page") //get接口表示根据浏览器请求返回数据
//public Map<String, Object> findPage(@RequestParam Integer pageNum,
// @RequestParam Integer pageSize,
// @RequestParam String username){
// pageNum=(pageNum-1)*pageSize; //limit第一个参数
// username="%"+username+"%";
// List<User> data=userMapper.selectPage(pageNum,pageSize,username);
// Integer total=userMapper.selectTotal(username); //查询总条数
// Map<String, Object> res=new HashMap<>();
// res.put("data",data);
// res.put("total",total);
// return res ;
//}//mybatis plus分页查询@GetMapping("/page") //get接口表示根据浏览器请求返回数据public IPage<User> findPage(@RequestParam Integer pageNum,
// public Map<String, Object> findPage(@RequestParam Integer pageNum,
// defaultValue设置默认值,这样不会报400@RequestParam(defaultValue = "") Integer pageSize,@RequestParam(defaultValue = "") String username,@RequestParam(defaultValue = "") String email,@RequestParam(defaultValue = "") String address){IPage<User> page=new Page<>(pageNum,pageSize);QueryWrapper<User> queryWrapper=new QueryWrapper<>();
// 下面引号里面的要是数据库字段名,多个字段写多次,是And条件,如果有一个用了orLike就都变成or
// 字段如果在数据库里面是null,不一定查出来if(!"".equals(username)){queryWrapper.like("username",username);}if(!"".equals(email)) {queryWrapper.like("email",email);}if(!"".equals(address)) {queryWrapper.like("address",address);}queryWrapper.orderByDesc("id");IPage<User> userPage=userService.page(page, queryWrapper);return userPage;}
}
这样就可以通过修改模版来达成想要的controller
自定义模版
参考
可以复制一份controller.java.vm到
文件夹名字一定要有s,也就是templates,不然代码生成器主程序找不到
然后通过修改获得想要的代码
生成的controller如果不正确可以删掉
package ${package.Controller};##原来模版
##import org.springframework.web.bind.annotation.RequestMapping;
##step1 自定义根据之前项目 ${entity}相当于User单词 ${table.entityPath}相当于user单词
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
##step2 导入比如import com.i7i8i9.eleven.service.UserService; import com.i7i8i9.eleven.entity.User;包
import ${package.Service}.${table.serviceName};
import ${package.Entity}.${entity};#if(${restControllerStyle})
import org.springframework.web.bind.annotation.RestController;
#else
import org.springframework.stereotype.Controller;
#end
#if(${superControllerClassPackage})
import ${superControllerClassPackage};
#end/*** <p>* $!{table.comment} 前端控制器* </p>** @author ${author}* @since ${date}*/
#if(${restControllerStyle})
@RestController
#else
@Controller
#end
@RequestMapping("#if(${package.ModuleName})/${package.ModuleName}#end/#if(${controllerMappingHyphenStyle})${controllerMappingHyphen}#else${table.entityPath}#end")
#if(${kotlin})
class ${table.controllerName}#if(${superControllerClass}) : ${superControllerClass}()#end#else
#if(${superControllerClass})
public class ${table.controllerName} extends ${superControllerClass} {
#else
public class ${table.controllerName} {
#end##step3 相当于到了service包,@Autowired 和private UserService userService;@Resourceprivate ${table.serviceName} ${table.entityPath}Service;##step4 改造原语句${entity}相当于User单词 ${table.entityPath}相当于user单词@PostMapping
## 新增修改 原语句 public boolean save(@RequestBody User user){return userService.saveOrUpdate(user);}public boolean save(@RequestBody ${entity} ${table.entityPath}){return ${table.entityPath}Service.saveOrUpdate(${table.entityPath});}
##删除 原语句 @DeleteMapping("/{id}") public boolean delete(@PathVariable Integer id){return userService.removeById(id);}
@DeleteMapping("/{id}")
public boolean delete(@PathVariable Integer id){return ${table.entityPath}Service.removeById(id);}
##批量删除
@PostMapping("/del/batch")
public boolean deleteBatch(@RequestBody List<Integer> ids){return ${table.entityPath}Service.removeBatchByIds(ids);}##查询所有 public List<User> index(){return userService.list();}
@GetMapping //get接口表示根据浏览器请求返回数据
public List<${entity}> index(){return ${table.entityPath}Service.list();}##根据id查询
@GetMapping("/{id}") //get接口表示根据浏览器请求返回数据
public ${entity} findOne(@PathVariable Integer id){return ${table.entityPath}Service.getById(id);}##分页查询,具体条件无法放到模版
@GetMapping("/page")
public IPage<${entity}> findPage(@RequestParam Integer pageNum,@RequestParam(defaultValue = "") Integer pageSize){IPage<${entity}> page=new Page<>(pageNum,pageSize);QueryWrapper<${entity}> queryWrapper=new QueryWrapper<>();IPage<${entity}> userPage=${table.entityPath}Service.page(page, queryWrapper);queryWrapper.orderByDesc("id");return userPage;}}
#end