做者:追梦1819
原文:https://www.cnblogs.com/yanfei1819/p/10876339.html
版权声明:本文为博主原创文章,转载请附上博文连接!
html
在以往的项目中,对于dao层的常规 CRUD 操做,咱们一般使用 JPA、JDBC 时会作一个所谓的 BaseDaoMapper 以减小代码量。而通用 Mapper 恰好是这一环节的替代品,代码更简单,更优雅,也是 Mybatis 用的很普遍的一个插件。java
不过须要注意的一点是,通用 Mapper 支持单表操做,不支持通用的多表联合查询。mysql
下面经过用增删改查的简单示例,演示 Mapper 的用法,本系列的demo都是按照 Java web 的项目架构来,因此仍是按照 MVC 的模式进行。不过注意,由于此处只是为了演示最基本的功能。为了防止舍本逐末,故代码做了最简单的优化,只保留最基本的功能代码,实际业务代码可能会复杂得多。git
准备工做,初始化数据库:github
SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for user -- ---------------------------- DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(40) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, `age` int(3) NOT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 50 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of user -- ---------------------------- INSERT INTO `user` VALUES (14, 'admin', 21); INSERT INTO `user` VALUES (48, 'teacher', 20); INSERT INTO `user` VALUES (49, 'student', 22); SET FOREIGN_KEY_CHECKS = 1;
建立 SpringBoot 项目。web
首先,引入maven依赖(由于通用 Mapper 是创建在 Mybatis 的基础上的,因此在引入 Mapper 以前,必须先引入Mybatis 依赖):spring
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.0.1</version> </dependency> <dependency> <groupId>tk.mybatis</groupId> <artifactId>mapper-spring-boot-starter</artifactId> <version>2.1.4</version> </dependency>
而后,配置数据库信息:sql
spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://192.168.1.88:3306/test?serverTimezone=GMT%2B8 spring.datasource.username=root spring.datasource.password=pass123
下一步,建立实体类以做数据库映射:数据库
package com.yanfei1819.mybatismapperdemo.entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; /** * Created by 追梦1819 on 2019-05-07. */ @Table(name = "user") public class User { @Id @GeneratedValue(generator = "JDBC") // 自增字段 private Long id; private String name; private int age; // set/get 省略 }
上述的注解:apache
@Table(name = "user")
映射数据表名
@Id
主键id
@GeneratedValue(generator = "JDBC")
自增字段
这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(好比:像 MySQL 和 SQL Server 这样的关系数据库管理系统的自动递增字段)。 这种状况对应的xml相似下面这样:
<insert id="insertAuthor" useGeneratedKeys="true" keyProperty="id"> insert into Author (username,password,email,bio) values (#{username},#{password},#{email},#{bio}) </insert>
若是表字段与实体类属性不一致,能够用注解
再下一步,建立代理接口:
package com.yanfei1819.mybatismapperdemo.dao; import com.yanfei1819.mybatismapperdemo.entity.User; import tk.mybatis.mapper.common.Mapper; /** * Created by 追梦1819 on 2019-05-07. */ @org.apache.ibatis.annotations.Mapper public interface UserMapper extends Mapper<User> { }
该接口就是通用 Mapper 的核心部分。该接口继承 Mapper。
再者,建立service层接口和实现类:
package com.yanfei1819.mybatismapperdemo.service; import com.yanfei1819.mybatismapperdemo.entity.User; import java.util.List; /** * Created by 追梦1819 on 2019-05-07. */ public interface UserService { int insertUser(User user); int updateUser(User user); int deleteUser(Long id); List<User> listUsers(); User getUserById(Long id); }
实现类:
package com.yanfei1819.mybatismapperdemo.service.impl; import com.yanfei1819.mybatismapperdemo.dao.UserMapper; import com.yanfei1819.mybatismapperdemo.entity.User; import com.yanfei1819.mybatismapperdemo.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; /** * Created by 追梦1819 on 2019-05-07. */ @Service public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Override public int insertUser(User user) { return userMapper.insert(user); } @Override public int updateUser(User user) { return userMapper.updateByPrimaryKey(user); } @Override public int deleteUser(Long id) { return userMapper.deleteByPrimaryKey(id); } @Override public List<User> listUsers() { return userMapper.selectAll(); } @Override public User getUserById(Long id) { return userMapper.selectByPrimaryKey(id); } }
最后,建立controller层:
package com.yanfei1819.mybatismapperdemo.web.controller; import com.yanfei1819.mybatismapperdemo.entity.User; import com.yanfei1819.mybatismapperdemo.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; /** * Created by 追梦1819 on 2019-05-07. */ @RestController public class UserController { @Autowired private UserService service; @GetMapping("/listUsers") public List<User> listUser(){ return service.listUsers(); } @GetMapping("/getUserById/{id}") public User getUserById(@PathVariable Long id){ return service.getUserById(id); } @PostMapping("/insertUser") public int insertUser(User user){ return service.insertUser(user); } @PostMapping("/updateUser") public int updateUser(User user){ return service.updateUser(user); } @GetMapping("/deleteUser/{id}") public int deleteUser(@PathVariable Long id){ return service.deleteUser(id); } }
启动类是:
package com.yanfei1819.mybatismapperdemo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; //import tk.mybatis.spring.annotation.MapperScan; // 注意此处引入的jar @SpringBootApplication //@MapperScan("com.yanfei1819.mybatismapperdemo.db") public class MybatisMapperDemoApplication { public static void main(String[] args) { SpringApplication.run(MybatisMapperDemoApplication.class, args); } }
要注意一点, UserMapper 接口中的 @org.apache.ibatis.annotations.Mapper
注解能够被启动类中的注解 @MapperScan(value = {"com.yanfei1819.mybatismapperdemo.db.*"})
代替。
可是这里要注意一个坑,使用了通用 Mapper 的导入的 @MapperScan
的jar包,再也不是 import org.mybatis.spring.annotation.MapperScan;
,而是 import tk.mybatis.spring.annotation.MapperScan;
,否则会报错。
启动项目,可测试结果。
此处列举一些经常使用的API:
增
int insert(T record);
保存一个实体,null的属性也会保存,不会使用数据库默认值
int insertSelective(T record);
保存一个实体,null的属性不会保存,会使用数据库默认值
查
List<T> selectAll();
查询所有结果
T selectByPrimaryKey(Object key);
根据主键字段进行查询,方法参数必须包含完整的主键属性,查询条件使用等号
List<T> selectByExample(Object example);
根据Example条件进行查询
List<T> select(T record);
根据实体中的属性值进行查询,查询条件使用等号
T selectOne(T record);
根据实体中的属性进行查询,只能有一个返回值,有多个结果是抛出异常,查询条件使用等号
int selectCount(T record);
根据实体中的属性查询总数,查询条件使用等号
改
int updateByPrimaryKey(T record);
根据主键更新实体所有字段,null值会被更新
int updateByExample(@Param("record") T record, @Param("example") Object example);
根据Example条件更新实体record
包含的所有属性,null值会被更新
int updateByPrimaryKeySelective(T record);
根据主键更新属性不为null的值
删
int deleteByPrimaryKey(Object key);
根据主键字段进行删除,方法参数必须包含完整的主键属性
int delete(T record);
根据实体属性做为条件进行删除,查询条件使用等号
int deleteByExample(Object example);
根据Example条件删除数据
文档一:https://mapperhelper.github.io/docs
文档二:https://github.com/abel533/Mapper
项目中常规的增删改查是避免不了的,并且逻辑几乎不变。若是每个增删改查都写一个方法,那冗余代码想必很多。即便是代码生成器生成代码【参考本人博客:SpringBoot第八篇:整合 MyBatis-Generator】,也是不利于代码的拓展的。
针对这个问题,有不少解决方案,甚至本身封装一个通用方法,也何尝不可(本人工做初期,项目中所用的基本都是这种解决方案)。不过在多方案中,我的仍是比较喜欢通用 Mapper,一是它与 MyBatis 无缝对接;二是代码量极少,无需配置;固然,更重要的是,已经有现成的轮子了,何须再重复去造轮子呢?
源码:个人GitHub
<全文完>