一,持久层框架MyBatis介绍
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAOs)
二,项目搭建所需要的jar依赖信息
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jdbc</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.2</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-aop --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> <version>2.2.5.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper-spring-boot-starter --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>1.2.12</version> </dependency>
三,项目所依赖的application.yaml配置信息如下
server: port: 8080spring: application: name: mybatis-annotation
datasource: url: jdbc:mysql://localhost:3306/annotation?useSSL=false&serverTimezone=UTC username: root password: root driver-class-name: com.mysql.cj.jdbc.Drivermybatis: configuration: ##配置项:开启下划线到驼峰的自动转换,作用:将数据库字段根据驼峰规则自动注入到对象属性 map-underscore-to-camel-case: onlogging: level: com.wpw.mybatisannotation: debug
四:项目依赖的sql信息如下
create database annotation;##创建数据库use annotation;##切换数据库为annotationselect database();##查看当前数据是否为annotationshow tables;##查看当前数据库annotation都有哪些表DROP TABLE IF EXISTS `user`;CREATE TABLE `user`( `id` int auto_increment primary key, `username` varchar(50), `password` varchar(50), `mobile_num` varchar(15));desc user;##查看表结构INSERT INTO `user`VALUES ('1', 'admin001', '123456', '13507660631');INSERT INTO `user`VALUES ('2', 'admin002', '123456', '13507660632');INSERT INTO `user`VALUES ('3', 'admin003', '123456', '13507660633');INSERT INTO `user`VALUES ('4', 'admin004', '123456', '13507660634');INSERT INTO `user`VALUES ('5', 'admin005', '123456', '13507660635');INSERT INTO `user`VALUES ('6', 'admin006', '123456', '13507660636');INSERT INTO `user`VALUES ('7', 'admin007', '123456', '13507660637');INSERT INTO `user`VALUES ('8', 'admin008', '123456', '13507660638');INSERT INTO `user`VALUES ('9', 'admin010', '123456', '13507660639');INSERT INTO `user`VALUES ('10', 'admin010', '123456', '13607660631');INSERT INTO `user`VALUES ('11', 'admin011', '123456', '13607660632');INSERT INTO `user`VALUES ('12', 'admin012', '123456', '13607660633');INSERT INTO `user`VALUES ('13', 'admin013', '123456', '13607660634');INSERT INTO `user`VALUES ('14', 'admin014', '123456', '13607660635');INSERT INTO `user`VALUES ('15', 'admin', '123456', '13507660636');show index from user;##当前表都有哪些索引explain select * from user ;##查看当前sql的执行计划
五,controller层代码逻辑编写
package com.wpw.mybatisannotation.controller;
import com.wpw.mybatisannotation.config.CountTime;import com.wpw.mybatisannotation.constant.URLConstant;import com.wpw.mybatisannotation.entity.User;import com.wpw.mybatisannotation.service.UserService;import org.springframework.web.bind.annotation.*;
import java.util.List;
/** * 用户控制器 * * @author wpw */@RestControllerpublic class UserController { public final UserService userService;
public UserController(UserService userService) { this.userService = userService; }
/** * @return 用户列表 */ @CountTime @GetMapping(value = URLConstant.LIST) public List<User> listUser() { return userService.listUser(); }
/** * 获取用户列表 * * @param userName 用户名称 * @return 用户列表 */ @CountTime @GetMapping(value = URLConstant.SEARCH) public List<User> listUserByUserName(@RequestParam(value = "userName") String userName) { return userService.listUserByUserName(userName); }
/** * @param userName 用户名称 * @param passWord 用户密码 * @return 用户信息 */ @CountTime @GetMapping(value = URLConstant.GET) public User search(@RequestParam(value = "userName") String userName, @RequestParam(value = "passWord") String passWord) { return userService.select(userName, passWord); }
/** * 根据用户名称和用户密码获取用户信息 * * @param userName 用户名称 * @param passWord 用户密码 * @return 用户信息 */ @CountTime @GetMapping(value = URLConstant.OPTION) public User searchUser(@RequestParam(value = "userName") String userName, @RequestParam(value = "passWord") String passWord) { return userService.selectUser(userName, passWord); }
/** * 保存用户信息 * * @param user 用户信息 * @return 是否成功 */ @PostMapping(value = URLConstant.INSERT) public Integer saveUser(@RequestBody User user) { return userService.saveUser(user); }
/** * 更新用户信息 * * @param user 用户信息 * @return 更新是否成功 */ @PutMapping(value = URLConstant.UPDATE) public Integer updateUser(@RequestBody User user) { return userService.updateUser(user); }
/** * 根据用户id删除用户信息 * * @param user 用户信息 * @return 删除是否成功 */ @DeleteMapping(value = URLConstant.DELETE) public Integer deleteUser(@RequestBody User user) { return userService.deleteUser(user); }
@GetMapping(value = "/list-pagination") public List<User> listPagination(@RequestBody User user) { return userService.listPagination(user); }}
六,业务逻辑层接口代码的编写
package com.wpw.mybatisannotation.service;
import com.wpw.mybatisannotation.entity.User;
import java.util.List;
/** * 业务处理类 * * @author wpw */public interface UserService { /** * 获取用户列表信息 * * @return 用户列表信息 */ List<User> listUser();
/** * 根据用户名称获取用户列表 * * @param userName 用户名称 * @retur 用户列表 */ List<User> listUserByUserName(String userName);
/** * 根据用户名称和密码查询用户信息 * * @param userName 用户名称 * @param passWord 用户密码 * @return user用户信息 */ User select(String userName, String passWord);
/** * 根据用户名称和用户密码查询用户信息 * * @param userName 用户名称 * @param passWord 用户密码 * @return 用户信息 */ User selectUser(String userName, String passWord);
/** * 保存用户信息 * * @param user 用户信息 * @return 自增主键 */ Integer saveUser(User user);
/** * 更新用户信息 * * @param user 用户信息 * @return 更新成功与否 */ Integer updateUser(User user);
/** * 根据用户id删除用户信息 * * @param user 用户信息 * @return 删除是否成功 */ Integer deleteUser(User user);
/** * 分页查询用户信息 * * @param user 用户信息 * @return 分页后的数据信息 */ List<User> listPagination(User user);}
七:业务逻辑层实现逻辑代码的编写
package com.wpw.mybatisannotation.service.impl;
import com.wpw.mybatisannotation.service.UserService;import com.wpw.mybatisannotation.entity.User;import com.wpw.mybatisannotation.mapper.UserMapper;import org.springframework.stereotype.Service;
import java.util.List;
/** * 业务处理类 * * @author wpw */@Servicepublic class UserServiceImpl implements UserService { private final UserMapper userMapper;
public UserServiceImpl(UserMapper userMapper) { this.userMapper = userMapper; }
@Override public List<User> listUser() { return userMapper.listUser(); }
@Override public List<User> listUserByUserName(String userName) { return userMapper.listUserByUserName(userName); }
@Override public User select(String userName, String passWord) { return userMapper.select(userName, passWord); }
@Override public User selectUser(String userName, String passWord) { return userMapper.selectUser(userName, passWord); }
@Override public Integer saveUser(User user) { return userMapper.saveUser(user); }
@Override public Integer updateUser(User user) { return userMapper.updateUser(user); }
@Override public Integer deleteUser(User user) { return userMapper.deleteUser(user); }
@Override public List<User> listPagination(User user) { return userMapper.listPagination(user); }}
八,操作数据库Mapper接口的代码编写
package com.wpw.mybatisannotation.mapper;
import com.wpw.mybatisannotation.entity.User;import org.apache.ibatis.annotations.*;import org.springframework.stereotype.Repository;
import java.util.List;
/** * dao操作类 * * @author wpw */@Mapper@Repositorypublic interface UserMapper { /** * 获取用户列表信息 * * @return 用户列表信息 */ @Select(value = "select * from user") List<User> listUser();
/** * 根据用户名称获取用户列表 * * @param userName 用户名称 * @retur 用户列表 */ @SelectProvider(type = UserSqlProvider.class, method = "listUserByUserName") List<User> listUserByUserName(@Param("userName") String userName);
/** * 根据用户名称和密码查询用户信息 * * @param userName 用户名称 * @param passWord 用户密码 * @return user用户信息 */ @Select(value = "select * from user where username=#{username} and password=#{password}") User select(@Param(value = "username") String userName, @Param(value = "password") String passWord);
/** * 根据用户名称和用户密码查询用户信息 * * @param userName 用户名称 * @param passWord 用户密码 * @return 用户信息 */ @SelectProvider(value = UserSqlProvider.class, method = "selectUser") User selectUser(String userName, String passWord);
/** * 保存用户信息 * * @param user 用户信息 * @return 自增主键 */ @InsertProvider(value = UserSqlProvider.class, method = "saveUser") @Options(useGeneratedKeys = true, keyProperty = "id") Integer saveUser(User user);
/** * 更新用户信息 * * @param user 用户信息 * @return 更新成功与否 */ @UpdateProvider(type = UserSqlProvider.class, method = "updateUser") Integer updateUser(User user);
/** * 删除用户信息 * * @param user 用户信息 * @return 删除是否成功 */ @DeleteProvider(type = UserSqlProvider.class, method = "deleteUser") Integer deleteUser(User user);
/** * 分页查询用户信息 * * @param user 用户信息 * @return 分页查询后的信息 */ @SelectProvider(type = UserSqlProvider.class, method = "listPagination") List<User> listPagination(User user);}
九,数据库Mapper实现类代码的逻辑编写
package com.wpw.mybatisannotation.mapper;
import com.wpw.mybatisannotation.entity.User;import org.apache.ibatis.jdbc.SQL;
/** * @author wpw */public class UserSqlProvider { /** * 根据用户名称查询用户列表 * * @param userName 用户名称 * @return sql */ public String listUserByUserName(String userName) { return "select * from user where username=#{userName}"; }
/** * 根据用户名称和用户密码查询用户 * * @param userName 用户名称 * @param passWord 用户密码 * @return sql */ public String selectUser(String userName, String passWord) { return new SQL() {{ SELECT("*"); FROM("user"); if (userName != null && passWord != null) { WHERE("username =#{userName} and password=#{passWord}"); } else { WHERE("1=2"); } }}.toString(); }
/** * 保存用户信息 * * @param user 用户信息 * @return sql */ public String saveUser(User user) { return new SQL() { { INSERT_INTO("user"); if (user.getUserName() != null) { VALUES("username", "#{userName}"); } if (user.getPassWord() != null) { VALUES("password", "#{passWord}"); } if (user.getMobileNum() != null) { VALUES("mobile_num", "#{mobileNum}"); } } }.toString(); }
/** * 更新用户信息 * * @param user 用户信息 * @return sql */ public String updateUser(User user) { return new SQL() { { UPDATE("user"); if (user.getUserName() != null) { SET("username = #{userName}"); } if (user.getPassWord() != null) { SET("password = #{passWord}"); } if (user.getMobileNum() != null) { SET("mobile_num=#{mobileNum}"); } WHERE("id= #{id}"); } }.toString(); }
/** * 删除用户信息 * * @param user 用户信息 * @return sql语句 */ public String deleteUser(User user) { SQL sql = new SQL() {{ DELETE_FROM("user"); if (user.getId() != null) { WHERE("id=#{id}"); } }}; return sql.toString(); }
/** * 分页查询用户列表信息 * * @param user 用户信息 * @return 用户列表信息 */ public String listPagination(User user) { SQL sql = new SQL() {{ SELECT("*"); FROM("user"); if (user.getUserName() != null) { SET("username=#{userName}"); } if (user.getPassWord() != null) { SET("password=#{passWord}"); } if (user.getMobileNum() != null) { SET("mobile_num=#{mobileNum}"); } if (user.getPageNumber() != null && user.getPageSize() != null) { LIMIT(user.getPageSize()); } }}; return sql.toString(); }}
十:控制器常量的代码配置
package com.wpw.mybatisannotation.constant;
/** * 处理映射器地址的常量类 * * @author wpw */public interface URLConstant { String LIST = "/list"; String INSERT = "/insert"; String UPDATE = "/update"; String DELETE = "/delete"; String GET = "/get"; String SEARCH = "/search"; String OPTION = "/option";}
十一:用于统计方法耗时时间的自定义注解
package com.wpw.mybatisannotation.config;
import java.lang.annotation.*;
/** * 自定义注解用于统计方法的耗时 */@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface CountTime {}
十二:自定义Aop结合自定义注解实现方法的耗时统计
package com.wpw.mybatisannotation.config;
import lombok.extern.slf4j.Slf4j;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.springframework.stereotype.Component;
/** * 定义一个统计方法执行耗时的切面类,基于@Component注解注入到spring容器进行管理 * * @author wpw */@Aspect@Component@Slf4jpublic class CountTimeAspect { /** * 首先定义一个切点 */ @org.aspectj.lang.annotation.Pointcut("@annotation(com.wpw.mybatisannotation.config.CountTime)") public void countTime() { }
@Around("countTime()") public Object doAround(ProceedingJoinPoint joinPoint) { Object obj = null; try { long beginTime = System.currentTimeMillis(); obj = joinPoint.proceed(); //获取方法名称 String methodName = joinPoint.getSignature().getName(); //获取类名称 String className = joinPoint.getSignature().getDeclaringTypeName(); log.debug("类:[{}],方法:[{}]耗时时间为:[{}]", className, methodName, System.currentTimeMillis() - beginTime + "毫秒"); } catch (Throwable throwable) { throwable.printStackTrace(); } return obj; }
}
十二:简单模拟分页请求的业务请求类
package com.wpw.mybatisannotation.config;
import lombok.AllArgsConstructor;import lombok.Builder;import lombok.Data;import lombok.NoArgsConstructor;import lombok.experimental.Accessors;
import java.io.Serializable;
/** * 用户请求类,暂时用作分页请求的类 * * @author wpw */@AllArgsConstructor@NoArgsConstructor@Data@Builder@Accessors(chain = true)public class PageVo implements Serializable { private Integer pageNumber; private Integer pageSize;}
十三:业务基础类
package com.wpw.mybatisannotation.config;
import lombok.AllArgsConstructor;import lombok.Builder;import lombok.Data;import lombok.NoArgsConstructor;import lombok.experimental.Accessors;
import java.io.Serializable;
/** * 用户请求类,暂时用作分页请求的类 * * @author wpw */@AllArgsConstructor@NoArgsConstructor@Data@Builder@Accessors(chain = true)public class PageVo implements Serializable { private Integer pageNumber; private Integer pageSize;}
整个整合以及实现的过程到这里就结束了,代码的实现逻辑都在文中已标注详细说明了,这里就不再解释了,整个实现逻辑都结束了。
代码地址:https://github.com/myownmyway/mybatis-annotation.git
需要相关代码拉取的
git clone https://github.com/myownmyway/mybatis-annotation.git//建议使用idea工具进行下载
整个代码的结构图如下: