创建项目
spring web,mybatis,mysql勾选
加入mp和druid,依赖见SpringBoot基础认识_阳光明媚UPUP的博客-CSDN博客
yml数据源
server:
port: 81
spring:
datasource:
druid: #整合方式配置
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/jdbc
username: root
password: root123
写个数据表,写个domain包实体类。
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Book {
private Integer id;
private String name;
private String price ;//decimal
}
写个mappr包接口@Mapper生成实现类,继承mp
@Mapper
public interface BookMapper extends BaseMapper<Book> {
}
新增报错
//mybatis-plus默认生成的id的方式为自己自订的雪花算法
//而数据库提供的id自增的方法 yml中配置id自增的方式:设置为auto自增:id-type:auto
mybatis-plus:
global-config:
db-config:
id-type: auto
测试用例
@SpringBootTest
class SpringbootBeginQuickstartApplicationTests {
@Autowired
private BookMapper bookMapper;
@Test
void contextLoads() {
System.out.println(bookMapper.selectById(1));
System.out.println(bookMapper.insert(new Book(null,"ddd","12")));
System.out.println(bookMapper.updateById(new Book(1,"update","12")));//返回值 成功1,失败0
System.out.println(bookMapper.deleteById(1)); //成功1,失败0
System.out.println(bookMapper.selectList(null));
//mybatis-plus默认生成的id的方式为自己自订的雪花算法
//而数据库提供的id自增的方法 yml中配置id自增的方式:设置为auto自增:id-type:auto
}
}
开启mp日志
运行测试程序后,控制台打印sql语句和预编译参数和结果。
不开就只有结果。
mybatis-plus:
global-config:
db-config:
id-type: auto
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #输出控制台
mp的分页查询
配置分页拦截:
Mp在进行查询的时候是通过拦截器进行拼接sql语句来实现的:
我们先创建一个拦截器的包:创建一个放拦截器的配置类:MPConfig:
配置类放入引导类所在的包及子包中才能被读取加载到spring容器中:
@Configuration
public class MPConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return interceptor;
}
}
配置类定义详见Spring_阳光明媚UPUP的博客-CSDN博客
会把page(1,5)拼接sql的limit
mp的Page对象
@SpringBootTest(classes = SpringbootBeginQuickstartApplication.class)
class SpringbootBeginQuickstartApplicationTests {
@Autowired
private BookMapper bookMapper;
@Test
void contextLoads() {
Page page = new Page(1, 5);
System.out.println(bookMapper.selectPage(page,null));
//mybatis-plus默认生成的id的方式为自己自订的雪花算法
//而数据库提供的id自增的方法 yml中配置id自增的方式:设置为auto自增:id-type:auto
System.out.println(page);//com.baomidou.mybatisplus.extension.plugins.pagination.Page@6413d7e7
System.out.println(page.getCurrent());//1
System.out.println(page.getSize());//5
System.out.println(page.getTotal());//13
System.out.println(page.getPages());//3
System.out.println(page.getRecords());//[Book(id=2, name=ghet, price=78), Book(id=3, name=ddd, price=12), Book(id=4, name=ddd, price=12), Book(id=5, name=ddd, price=12), Book(id=6, name=ddd, price=12)]
}
}
条件查询
使用的like %预编译拼接的sql的
@SpringBootTest(classes = SpringbootBeginQuickstartApplication.class)
class SpringbootBeginQuickstartApplicationTests {
@Autowired
private BookMapper bookMapper;
@Test
void contextLoads() {
String name="ddd";
QueryWrapper<Book> qw = new QueryWrapper<>();
qw.like("name", name);//实际中,name可能为null
//qw.eq , qw.ne , lt , gt , le , ge , between , group
List<Book> bookList = bookMapper.selectList(qw);
System.out.println(bookList);
//防止参数name误写错,我们可以借助lambda表达式的Qw查询:
LambdaQueryWrapper<Book> lqw = new LambdaQueryWrapper<>();
//if(name!=null)lqw.like(Book::getName,name);//方法引用:只要保证lambda的入参可用放入Book类的成员方法getName中的入参中即可。
lqw.like(name != null, Book::getName, name);
List<Book> books = bookMapper.selectList(lqw);
System.out.println(books);
}
}
对于上面分页查询后面也能拿国家qw或lqw
System.out.println(bookMapper.selectPage(page,qw或lqw));
MP简化业务层Service层
普通service
@Service
public class BookServiceImpl implements BookService{
@Autowired
private BookMapper bookMapper;
public Boolean save(Book book){
return bookMapper.insert(book)>0;
}
public Boolean update(Book book){
return bookMapper.updateById(book)>0;
}
public Boolean delete(Integer id){
return bookMapper.deleteById(id)>0;
}
public Book getById(Integer id){
return bookMapper.selectById(id);
}
public List<Book> getAll(Integer id){
return bookMapper.selectList(null);
}
public IPage<Book> getPage(int currentPage,int pageSize){
Page page = new Page(currentPage, pageSize);
bookMapper.selectPage(page,null);
return page;
}
}
service接口层只需继承
public interface BookService extends IService<Book> {
}
impl除了实现接口层还需继承
@Service
public class BookServiceImpl extends ServiceImpl<BookMapper,Book> implements BookService{
}
ctrl+f12勾选第一个框,即可看到里面继承的方法
mp业务层有的方法直接用,没有的接着写。尽量不与Mp的业务层方法重名,可以使用@Override进行检查有无重名覆盖。
然后就可贼测试类注入service接口并测试了。
表现层开发
@RestController//restful风格的controller
@RequestMapping("/books")
public class BookController {
@Autowired
private BookService bookService;
@GetMapping
public List<Book> getAll(){
return bookService.list();
}
@PostMapping
public Boolean save(@RequestBody Book book){//RequestBody接收json
return bookService.save(book);
}
@PutMapping
public Boolean update(@RequestBody Book book){//RequestBody接收json
return bookService.updateById(book);
}
@DeleteMapping("/{id}")
public Boolean delete(@PathVariable Integer id){//RequestBody接收json
return bookService.removeById(id);
}
@GetMapping("/{id}")
public Book getById(@PathVariable Integer id){//RequestBody接收json
return bookService.getById(id);
}
@GetMapping("{currentPage}/{pageSize}")
public IPage<Book> getPage(@PathVariable int currentPage,@PathVariable int pageSize){
Page<Book> page = new Page<>(1,5);
return bookService.page(page);
}
}
postman测试
选择REST动作GET/...
POST/PUT请求body里面加上json数据{ "":"", "":""}
DELETE请求路径传参/1
表现层消息一致性处理
查询返回list<user>的数据、新增返回true,修改返回true,删除返回true,分页查询返回IPage<Book>
由于:
查询id不存在的数据,返回null,查询过程中抛出异常,catch中返回null。
这时:
我们就不知道这个null,是查询数据库返回的,还是报异常返回的。
我们可以设置一个flag,如果是正常查询就返回true:如果报异常没正常查询返回false:
设计表现层返回结果的模型类,用于后端与前端进行数据格式统一,也称为前后端数据协议
我们需要加一个返回结果的数据的模型类:
util包下
@Data
@NoArgsConstructor
@AllArgsConstructor
public class R {
private Boolean flag;
private Object data;
public R(Boolean flag) {
this.flag = flag;
}
}
@RestController//restful风格的controller
@RequestMapping("/books")
public class BookController {
@Autowired
private BookService bookService;
@GetMapping
public R getAll(){
return new R(true,bookService.list());
}
@PostMapping
public R save(@RequestBody Book book){//RequestBody接收json
R r = new R();
boolean flag = bookService.save(book);
r.setFlag(flag);
return r;
}
@PutMapping
public R update(@RequestBody Book book){//RequestBody接收json
return new R(bookService.updateById(book));
}
@DeleteMapping("/{id}")
public R delete(@PathVariable Integer id){
return new R(bookService.removeById(id));
}
@GetMapping("/{id}")
public R getById(@PathVariable Integer id){
return new R(true,bookService.getById(id));
}
@GetMapping("{currentPage}/{pageSize}")
public R getPage(@PathVariable int currentPage,@PathVariable int pageSize){
Page<Book> page = new Page<>(1,5);
return new R(true,bookService.page(page));
}
}
现在查询成功或失败都会有状态了。
前后端联调
先不整这块了
前后端分离结构设计中页面归属前端服务器
单体工程中页面放置在resources目录下的static目录中(建议执行clean)
异常消息处理
当抛异常就不返回R了,接着springmvc异常处理
util包下的R先加个属性private String msg;
util包下创建一个异常处理器作为springmvc异常处理器
@RestControllerAdvice
public class ProjectRxceptionAdvice {
@ExceptionHandler
public R doException(Exception e){
//记录日志
//通知运维
//通知开发
e.printStackTrace();
return new R("服务器故障,请稍后再试");
}
}
controller的某个资源随便造一个异常,postman访问测试。