MyBatis-Plus
MyBatis-Plus 是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
官网 MyBatis-Plus
连接池: 传统开发中,每一次请求都要建立一次数据库连接。每一次数据库连接,使用完后都得断开。频繁的数据库连接操作势必占用很多的系统资源,响应速度必定下降。另外,在高并发时,系统资源被毫无顾及的分配出去,如连接过多,也可能导致内存泄漏,服务器崩溃。
解决方案: 为数据库连接建立一个“缓冲池”(连接池)。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕再放回去。通过设定连接池最大连接数来防止系统无休止的数据库连接。
工作流程: 当客户端请求服务器,服务器需要使用连接对象操作数据库的数据。这时,需要从连接池中申请一个连接对象。连接池会分配一个空闲连接给该客户。如果连接池中没有空闲连接,就看有没有到达最大连接数。如果没有到达最大连接数,就创建新连接分配给客户。如果已经到达最大连接,那么,请求用户会等待一段时间,在等待时间内,有连接对象被释放,则分配给等待用户。等待时间结束后,还没有连接被释放,则返回null。
Mybatis — 环境搭建
1、导入相关依赖
org.springframework.bootspring-boot-starter-parent2.4.2mysqlmysql-connector-java5.1.48org.springframework.bootspring-boot-starterorg.springframework.bootspring-boot-starter-testtestcom.baomidoumybatis-plus-boot-starter3.4.3junitjunit4.12testcom.alibabadruid1.2.9
2、创建实体类
//声明该实体类映射的表名@TableName("t_product")public class ProductBean {//表示该列为主键列,value表示该列映射的列名//type = IdType.AUTO 表示该列的值使用自动增长列生成@TableId(value = "pk_productId",type = IdType.AUTO)private Integer id;//指定当前属性映射的列名@TableField("p_name")private String name;@TableField("p_createDate")private LocalDate createDate;@TableField("p_price")private Integer price;}
3、在 resources 目录下,创建 application.yml 配置文件
spring: datasource:driver-class-name: com.mysql.jdbc.Driver #定义配置驱动类username: root #mysql登录用户名password: 123 #mysql登录密码url: jdbc:mysql://localhost:12345/shopDB?characterEncoding=utf8&allowMultiQueries=true type: com.alibaba.druid.pool.DruidDataSource #配置连接池druid: one:max-active: 100 #最大连接数min-idle: 20 #最小连接数max-wait: 2000 #超时时间(ms)mybatis-plus: configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #配置日志 type-aliases-package: com.project.bean #实体类所在包,允许用实体类类名作为别名 mapper-locations: classpath:*/*Mapper.xml #链接 mapper文件
4、创建业务接口
public interface IProductService {public void add(ProductBean productBean);public void del(Integer id);public void update(Integer id,Integer price);public List findAll();public ProductBean findById(Integer id);public List findByItem(String name, LocalDate startDate,LocalDate endDate);}
5、创建 mapper 接口
@Mapperpublic interface IProductMapper extends BaseMapper {}
6、书写业务接口实现类
@Service@Transactional//该类所有方法支持事务public class ProductServiceImpl implements IProductService {@Autowiredprivate IProductMapper mapper;@Overridepublic void add(ProductBean productBean) {mapper.insert(productBean);//添加实体数据 }@Overridepublic void del(Integer id) {mapper.deleteById(id);//根据id删除实体数据 }@Overridepublic void update(Integer id, Integer price) {ProductBean productBean = new ProductBean();productBean.setId(id);productBean.setPrice(price);mapper.updateById(productBean);//按id修改实体属性 }@Overridepublic List findAll() {return mapper.selectList(null);//查询所有 }@Overridepublic ProductBean findById(Integer id) {return mapper.selectById(id);//按id查询实体对象 }@Overridepublic List findByItem(String name, LocalDate startDate, LocalDate endDate) {QueryWrapper qw = new QueryWrapper();//条件集合if (name != null && name.length() != 0){qw.like("p_name",name);//like 模糊查询 }if (startDate != null){qw.ge("p_creatDate",startDate);//ge 大于等于 }if (endDate != null){qw.le("p_createDate",endDate);//le 小于等于 }return mapper.selectList(qw);//按条件查询 }}
7、测试类
@RunWith(SpringRunner.class)@SpringBootTest(classes = Main.class)//启动类类模板public class ProductTest {@Autowiredprivate IProductService service;@Testpublic void test(){// service.add(new ProductBean("999感冒灵", LocalDate.parse("2022-06-06"),18));System.out.println(service.findAll()); }}
分页查询
1、创建配置类,定义数据库 SQL 语句的方言。Mybatis-plus会根据配置的方言,产生分页的 SQL 语句
@Configurationpublic class MyBatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return interceptor;}}
2、定义业务接口方法
/** * 动态条件分页查询 * @param pageNO 页码 * @param name 姓名 * @param startDate 生产起始日期 * @param endDate 生成结束日期 * @return 分页对象 */public IPage findByItem(Integer pageNO, String name, LocalDate startDate,LocalDate endDate);
3、定义 mapper 接口
@Mapperpublic interface IProductMapper extends BaseMapper {}
4、书写业务方法
@Overridepublic IPage findByItem(Integer pageNO, String name, LocalDate startDate, LocalDate endDate) {QueryWrapper qw = new QueryWrapper();if (name != null && name.length() != 0){qw.like("p_name",name); }if (startDate != null){qw.ge("p_createDate",startDate); }if (endDate != null){qw.le("p_createDate",endDate); }return mapper.selectPage(new Page(pageNO,3),qw);}
5、测试类
@RunWith(SpringRunner.class)@SpringBootTest(classes = PlusMain.class)public class Test {@Autowiredprivate IProductService service;@org.junit.Testpublic void test(){// System.out.println(service.findAll());IPage ip = service.findByItem(1,"",null,null);System.out.println(ip.getRecords()//得到当前数据+""+ip.getTotal()//得到总记录数+""+ip.getPages()//总页数+""+ip.getCurrent()//得到页码+""+ip.getSize()//得到每页记录数 ); }}
Mybatis-plus 关联操作
一对多:
1、创建实体类
/** * 部门实体类 */@TableName("t_dept")public class DeptBean {@TableId(value = "pk_deptId",type = IdType.AUTO)private Integer id;@TableField("d_name")private String name;@TableField(exist = false)//标识该属性没有对应的列private Integer emNum;@TableField(exist = false)//标识该属性没有对应的列private List emList;}/** * 员工实体类 */@TableName("t_employee")public class EmployeeBean {@TableId(value = "pk_emId",type = IdType.AUTO)private Integer id;@TableField("e_name")private String name;@TableField("e_job")private String job;@TableField("e_birthday")private LocalDate birthday;@TableField("fk_deptId")private Integer deptId;@TableField(exist = false)private DeptBean dept;}
注意:如果一个属性没有对应的列,必须加上@TableField(exist = false)。否则,maybatis-plus会认为数据库表中有一个和该属性同名列。
2、建立业务接口
/***部门业务接口*/public interface IDeptService {/** * 查询所有部门,同时统计每个部门的人数 * @return 部门集合 */public List findAll();/** * 级联添加,添加部门,同时添加该部门的员工集合 * @param dept 部门对象 * @param emList 新员工集合 */public void add(DeptBean dept, List emList);/** * 删除部门,同时级联删除部门的员工 * @param id 部门ID */public void delCasede(Integer id);/** * 删除部门,同时将该部门员工外键设置为null * @param id 部门ID */public void delSerNull(Integer id);/** * 按id查询部门,同时查询该部门中所有的员工 * @param id 部门id * @return 部门对象 */public DeptBean findById(Integer id);}/** * 员工业务接口 */public interface IEmployeeService {/** * 添加员工 * @param employee 员工对象 */public void add(EmployeeBean employee);/** * 动态条件分页查询,同时查询每个员工所在部门的名称 * @param pageNO 页码 * @param deptName 部门名称 * @param name 员工姓名 * @return 分页对象 */public IPage findByItem(Integer pageNO,String deptName,String name);/** * 按id查询员工,同时查询员工的部门信息 * @param id 员工编号 * @return 员工对象33 */public EmployeeBean findById(Integer id);}
3、建立 Mapper 接口
/***部门 mapper 接口*/@Mapperpublic interface IDeptMapper extends BaseMapper {@Select("SELECT d.*,COUNT(e.`pk_emId`) emNum FROM t_dept d LEFT JOIN t_employee e ON d.`pk_deptId`=e.`fk_deptId`\n" +"GROUP BY d.`pk_deptId`")@ResultMap("deptMap")public List findAll();@Delete("delete from t_employee where fk_deptId=#{id};" +"delete from t_dept where pk_deptId=#{id};")public void delCasede(Integer id);@Delete("update t_employee set fk_deptId=null where fk_deptId=#{id};" +"delete from t_dept where pk_deptId=#{id};")public void delSetNull(Integer id);}/***员工 mapper 接口*/@Mapperpublic interface IEmployeeMapper extends BaseMapper {public void addMore(@Param("deptId") Integer deptId,@Param("emList") List emList);public IPage findByItem(Page pageNO,@Param("deptName") String deptName,@Param("name") String name);}
对于联表查询的结果集,动态条件查询、循环,都需要在 mapper 文件中完成。
4、书写 mapper 文件
IDeptMapper:
IEmployeeMapper:
insert into t_employee (e_name,e_job,e_birthday,fk_deptId) values (#{em.name},#{em.job},#{em.birthday},#{deptId})select e.*,d.d_name from t_dept d,t_employee e where d.pk_deptId=e.fk_deptIdand d_name like "%"#{deptName}"%"and e_name like "%"#{name}"%"
5、书写业务方法
/** * 部门业务方法 */@Service@Transactionalpublic class DeptServiceImpl implements IDeptService {@Autowiredprivate IDeptMapper deptMapper;@Autowiredprivate IEmployeeMapper employeeMapper;@Overridepublic List findAll() {return deptMapper.findAll(); }@Overridepublic void add(DeptBean dept, List emList) {deptMapper.insert(dept);employeeMapper.addMore(dept.getId(),emList); }@Overridepublic void delCasede(Integer id) {deptMapper.delCasede(id); }@Overridepublic void delSerNull(Integer id) {deptMapper.delSetNull(id); }@Overridepublic DeptBean findById(Integer id) {DeptBean dept = deptMapper.selectById(id);QueryWrapper qw = new QueryWrapper();qw.eq("fk_deptId",id);dept.setEmList(employeeMapper.selectList(qw));return dept; }}/** * 员工业务方法 */@Service@Transactionalpublic class EmployeeServiceImpl implements IEmployeeService {@AutowiredIEmployeeMapper employeeMapper;@AutowiredIDeptMapper deptMapper;@Overridepublic void add(EmployeeBean employee) {employeeMapper.insert(employee); }@Overridepublic IPage findByItem(Integer pageNO, String deptName, String name) {return employeeMapper.findByItem(new Page(pageNO,3),deptName,name); }@Overridepublic EmployeeBean findById(Integer id) {EmployeeBean em = employeeMapper.selectById(id);em.setDept(deptMapper.selectById(em.getDeptId())); ·· return em; }}
统计查询记录数
QueryWrapper qw = new QueryWrapper();qw.eq("fk.classId",classId);Integer num = studentMapper.selectCount(qw);