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 {
@Autowired
private UserMapper userMapper;
@Autowired
private UserService userService;
// PostMapping RequestBody可以把前台传来的json数据变成后台java对象
// 使用mybatis plus 返回有Integer变为boolean
@PostMapping
public boolean save(@RequestBody User user){ //返回条数
return userService.saveUser(user);
}
// GetMapping是为了浏览器请求后,从数据库获取数据,List<User>表示返回数组
@GetMapping //get接口表示根据浏览器请求返回数据
public List<User> index(){
// List<User> all=userMapper.findAll();
// mybatis-plus
return userService.list();
}
@DeleteMapping("/{id}")
public boolean delete(@PathVariable Integer id){ //本处的参数id 与@deletemapping路径里面的一致
// return userMapper.deleteByID(id);
// mybatis-plus
return 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": "[email protected]",
"phone": "13245679899",
"address": "陕西西安",
"avatarUrl": null
},
{
"id": 3,
"username": "liqingzhao245",
"nickname": "杜甫",
"email": "[email protected]",
"phone": "13456778899",
"address": "四川成都",
"avatarUrl": "ddd"
},
{
"id": 5,
"username": "admin",
"nickname": "管理员",
"email": "[email protected]",
"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分组显示[email protected] 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方法
@Override
public 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 {
@Override
public 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
*/
@Bean
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"))
.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", "[email protected]"))
.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;
}
@Override
public 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);
}
@Override
public 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为数据库url
FastAutoGenerator.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;
@Autowired
private UserService userService;
// PostMapping RequestBody可以把前台传来的json数据变成后台java对象
// 使用mybatis plus 返回有Integer变为boolean
@PostMapping
public boolean save(@RequestBody User user){ //返回条数
return userService.saveUser(user);
}
// GetMapping是为了浏览器请求后,从数据库获取数据,List<User>表示返回数组
@GetMapping //get接口表示根据浏览器请求返回数据
public List<User> index(){
// List<User> all=userMapper.findAll();
// mybatis-plus
return userService.list();
}
@DeleteMapping("/{id}")
public boolean delete(@PathVariable Integer id){ //本处的参数id 与@deletemapping路径里面的一致
// return userMapper.deleteByID(id);
// mybatis-plus
return userService.removeById(id);
}
//批量删除
@PostMapping("/del/batch")
public boolean deleteBatch(@RequestBody List<Integer> ids){ //本处的参数id 与@deletemapping路径里面的一致
// return userMapper.deleteByID(id);
// mybatis-plus
return 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;
@Resource
private ${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
文章评论