## 一、持久层框架
Mybaits 、Hibernate 、`Mybatis-plus`、`Spring Data JPA`(基于hibernate),这些都属于ORM框架
## 二、mybaits-plus框架
mybaits-plus只对mybatis进行增强,不对mybaits做修改
## 三、Springboot整合mybaits-plus
### 1.整合mybatis-plus的步骤
#### (1)导入依赖
```xml
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
```
#### (2)配置数据源 application.yml
springboot默认采用的数据源是什么?HikariCP、Druid、common-pooled、c3p0等
springboot默认使用hikariCP,性能比较强
```yaml
#配置连接数据库使用的数据源
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/lanqiao
username: root
password: root
#给实体类起了别名
mybatis-plus:
type-aliases-package: org.lanqiao.entity
#日志,只监控org.lanqiao.mapper包下的
logging:
level:
org:
lanqiao:
mapper: debug
```
#### (3)创建数据库和实体类
可以通过正向工程或逆向工程 。
正向工程:java程序===》生成数据库
逆向工程:数据库的信息===》java程序
```java
package org.lanqiao.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("tb_student")
public class Student {
//让数据库来处理自增字段,否则mybaits-plus会自动生成一个字符串类型id插入到数据库中
@TableId(type = IdType.AUTO)
private Integer id;
//@TableField("user_name")
private String userName;
private Integer age;
}
```
#### (4)mapper层接口
```java
package org.lanqiao.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.lanqiao.entity.Student;
@Mapper
public interface StudentMapper extends BaseMapper<Student> {
}
```
#### (5)service层
```java
package org.lanqiao.service;
import org.lanqiao.entity.Student;
import java.util.List;
public interface StudentService {
int addStudent(Student student);
int deleteStudent(Integer id);
int updateStudent(Student student);
Student getStudentById(Integer id);
List<Student> getAllStudents();
}
```
```java
package org.lanqiao.service.impl;
import org.lanqiao.entity.Student;
import org.lanqiao.mapper.StudentMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class StudentService implements org.lanqiao.service.StudentService {
@Autowired
StudentMapper studentMapper;
@Override
public int addStudent(Student student) {
return studentMapper.insert(student);
}
@Override
public int deleteStudent(Integer id) {
return 0;
}
@Override
public int updateStudent(Student student) {
return 0;
}
@Override
public Student getStudentById(Integer id) {
return null;
}
@Override
public List<Student> getAllStudents() {
return null;
}
}
```
#### (6)配置类
```java
package org.lanqiao.config;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration;
@Configuration
//假如mapper接口中使用了@Mapper就可以不需要扫描,但是使用spring的注解@Repository,必须扫描
@MapperScan("org.lanqiao.mapper")
public class AppConfig {
}
```
#### (7)单元测试
```java
package org.lanqiao.test_springboot_02;
import org.junit.jupiter.api.Test;
import org.lanqiao.entity.Student;
import org.lanqiao.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class TestSpringboot02ApplicationTests {
@Autowired
StudentService studentService;
@Test
void contextLoads() {
int i = studentService.addStudent(new Student(null, "john", 23));
System.out.println(i);
}
}
```
#### (8)restful风格的controller
```java
package org.lanqiao.controller;
import org.lanqiao.entity.Student;
import org.lanqiao.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
public class StudentController {
@Autowired
StudentService studentService;
@PostMapping("/student/save")
public String insert(@RequestBody Student student){
int i = studentService.addStudent(student);
if(i >= 1) return "ok";
else return "fail";
}
@DeleteMapping("/student/{id}")
public String delete(@PathVariable("id") Integer id){
int i = studentService.deleteStudent(id);
if(i >= 1) return "ok";
else return "fail";
}
@PutMapping("/student/save")
public String update(Student student){
int i = studentService.updateStudent(student);
if(i >= 1) return "ok";
else return "fail";
}
@GetMapping("/student/{id}")
public Student getOne(@PathVariable("id") Integer id){
return studentService.getStudentById(id);
}
@GetMapping("/student")
public List<Student> getAll(){
return studentService.getAllStudents();
}
}
```
### 2.mybatis-plus条件查询
Wrapper QueryWrapper
```java
@Override
public List<Student> getStudentsByAge(Integer age) {
QueryWrapper<Student> wrapper = new QueryWrapper<>();
wrapper.ge("age",age);
return studentMapper.selectList(wrapper);
}
@Override
public List<Student> getStudentByName(String userName) {
QueryWrapper<Student> wrapper = new QueryWrapper<>();
wrapper.like("user_name",userName);
wrapper.gt("age",22);
return studentMapper.selectList(wrapper);
}
```
### 3.mybatis-plus提供的分页插件
#### (1)提供分页拦截器(配置类)
```java
package org.lanqiao.config;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@MapperScan("org.lanqiao.mapper")
public class AppConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
//创建mybatisplus拦截器总管
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
//添加一个分页拦截器
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return mybatisPlusInterceptor;
}
}
```
#### (2)在service层实现分页
分页有2种:
一种叫做逻辑分页(假分页)
会把数据库表中的所有数据一次性都查出来,返回给前端页面,前端页面通过js进行分页
一种叫做物理分页(真分页)
每次查询只查询一页的数据,下一页又要到数据库再次查询
IPage Page<Student>
mysql分页sql: select * from student limit startRecord,pageSize
```java
@Override
public IPage<Student> getAllStudents(Page<Student> page) {
IPage<Student> iPage = studentMapper.selectPage(page,null);
return iPage;
}
```
```java
@Test
void contextLoad9() {
Page<Student> page = new Page<>();
//设定每页显示2条记录
page.setSize(2);
//设置查询第二页
page.setCurrent(2);
IPage<Student> iPage = studentService.getAllStudents(page);
//获取总数
System.out.println("总数:"+iPage.getTotal());
//获取总页数
System.out.println(iPage.getPages());
//查询当前页码
System.out.println(iPage.getCurrent());
//获取每页多少条记录
System.out.println(iPage.getSize());
List<Student> list = iPage.getRecords();
//使用了lanmda表达式
list.forEach(e-> System.out.println(e));
//students.forEach(System.out::println);
}
```
### 4.自定义方法(实现多表查询)
假如mybatis-plus的BaseMapper没有提供我们想要的方法,我可以仍然使用mybatis的用法
```java
package org.lanqiao.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.lanqiao.entity.Student;
import org.springframework.stereotype.Repository;
import java.util.List;
//@Mapper
@Repository
public interface StudentMapper extends BaseMapper<Student> {
@Select("select * from tb_student where user_name = #{name}")
public Student selectStudentsByName(String name);
}
```
mybatis-plus的BaseMapper没有提供很好多表查询的方式,所以大部分多表查询需要自定义
### 5.使用事务
配置类上添加注解
```java
package org.lanqiao.config;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@MapperScan("org.lanqiao.mapper")
//<aop:aspectj-autoproxy/>启用aop的注解
@EnableAspectJAutoProxy
// <tx:annotation-driven transaction-manager="transactionManager"/>启用事务的注解
@EnableTransactionManagement
public class AppConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
//创建mybatisplus拦截器总管
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
//添加一个分页拦截器
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return mybatisPlusInterceptor;
}
}
```
```java
@Transactional
public int updateStudent(Student student) {
return studentMapper.updateById(student);
}
```