什么是通用 Mapper?
它是一个可以方便的使用 Mybatis 进行单表的增删改查优秀开源产品。它使用拦截器来实现具体的执行 Sql,完全使用原生的 Mybatis 进行操作。在 Github 上标星 9.6K!
为什么要用 Mapper?
它提供了所有单表的基本增删改查方法,大大节省了我们书写基本 mapper.xml 的时间。尤其对于新工程和新表来说,极大的提高...
不客气的说,使用这个通用 Mapper 甚至能改变你对 Mybatis 单表基础操作不方便的想法,使用它你能简单的使用单表的增删改查,包含动态的增删改查。
同时,在代码结构合理的前提下,更换 RDBMS 也无须修改 sql,只需修改部分配置即可实现。
如何使用 Mapper?
先通过 maven 引入 jar 包:
<dependency><groupId>tk.mybatis</groupId><artifactId>mapper</artifactId><version>x.x.x</version>
</dependency>
添加配置文件:
配置方式分为 Java 编码方式和 spring 集成方式。
Java 编码方式
MapperHelper mapperHelper = new MapperHelper();
//特殊配置
Config config = new Config();//具体支持的参数看后面的文档
config.setXXX(XXX);//设置配置
mapperHelper.setConfig(config);// 注册自己项目中使用的通用Mapper接口,这里没有默认值,必须手动注册
mapperHelper.registerMapper(Mapper.class);
//配置完成后,执行下面的操作
mapperHelper.processConfiguration(session.getConfiguration());
2). 纯Spring配置方式
<bean ><property name="basePackage" value="com.isea533.mybatis.mapper"/><property name="properties"><value>mappers=tk.mybatis.mapper.common.Mapper </value></property>
</bean>
你没看错,就是这么配置的,注意这里是 tk.mybatis.xxx, 和 MyBatis 的唯一区别就是 org. 改成了 tk.,方便修改和记忆。
通用 Mapper 的各项属性通过 properties 属性进行配置,如果默认配置就是一行 mappers=tk.mybatis.mapper.common.Mapper 时,可以不写,就会变成:
<bean ><property name="basePackage" value="com.isea533.mybatis.mapper"/>
</bean>
继承通用 Mapper 接口(注意必须要加泛型):
@Repository
public interface MaterialDao extends Mapper<MaterialMeta>,
InsertUseGeneratedKeysMapperr<MaterialMeta> {}
上图示例继承了Mapper和InsertUseGeneratedKeysMapper,则直接拥有了这2个接口的所有方法。
上图中实体类的写法示例:
@Table(name = "tb_helpcenter_material")
public class MaterialMeta {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String title;private String tags;private Long classificationId;private String platform;private String lecturerName;// Setters&Getters
}
实体类的规则:
1. 表名默认使用类名, 驼峰转下划线 (只对大写字母进行处理), 如 UserInfo 默认对应的表名为 user_info。
2. 表名可以使用 @Table(name = "tableName") 进行指定, 对不符合第一条默认规则的可以通过这种方式指定表名.
3. 字段默认和 @Column 一样, 都会作为表字段, 表字段默认为 Java 对象的 Field 名字驼峰转下划线形式.
4. 可以使用 @Column(name = "fieldName") 指定不符合第 3 条规则的字段名
5. 使用 @Transient 注解可以忽略字段, 添加该注解的字段不会作为表字段使用.
6. 建议一定是有一个 @Id 注解作为主键的字段, 可以有多个 @Id 注解的字段作为联合主键.
7. 默认情况下, 实体类中如果不存在包含 @Id 注解的字段, 所有的字段都会作为主键字段进行使用 (这种效率极低).
8. 实体类可以继承使用, 可以参考测试代码中的 tk.mybatis.mapper.model.UserLogin2 类.
9. 由于基本类型, 如 int 作为实体类字段时会有默认值 0, 而且无法消除, 所以实体类中建议不要使用基本类型.
10.@NameStyle 注解,用来配置对象名 / 字段和表名 / 字段之间的转换方式,该注解优先于全局配置 style,可选值:
另外,建议实体类的所有 Field 全部使用装箱类,不要使用基本类型。
id 字段上的 @GeneratedValue 注解用来表示该表使用的主键策略类型。
使用 Mybatis-Generator 来生成实体类:
关于主键策略
主键策略主要用于 insert 场景。通常情况下,可以不用设置表对象的主键策略。不设置时,默认会使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键。
你也可以以 @GeneratedValue(generator = “”) 的形式来指定主键策略命令。如:@GeneratedValue(strategy = GenerationType.IDENTITY
,generator = “select last_insert_id()”) 等。
同时,可以根据实际需要,在全局配置中指定主键策略的执行 ORDER。
用 Mybatis-Generator 生成实体类,并创建一个继承了 Mapper 接口的 dao 以后,还要写什么呢?
答案是不用了,可以直接用了
就像这样:
MaterialMeta materialMeta = ReflectUtil.convertObj(MaterialMeta.class, material, false);
materialMeta.setPlatform(platformStr);
materialDao.insertSelective(materialMeta);
还有这样:
Example example = new Example(MaterialMeta.class);
example.createCriteria().andEqualTo("classificationId", material.getClassificationId()).andEqualTo("deleted",false);example.orderBy("sort").desc();
PageHelper.startPage(1, 1);
List<MaterialMeta> materialMetas = materialDao.selectByExample(example);
或者这样:
materialMeta.setStatus(MaterialStatus.online);
materialMeta.setPublishDate(new Date());
materialDao.updateByPrimaryKeySelective(materialMeta);
如此一来,一行 sql 都不需要写,mapper.xml 文件也不需要了(特殊 sql 仍然需要手写)。
只是引入了原生的 Mapper 吗?有没有什么缺陷?我们做了什么改动?
fork 的 Mapper 版本是 3.4.2 的,最新 3.4.3 还没有 release。
像这样的通用框架,几乎支持了市面上所有主流的 rdbms,但是大网易的 DDB 就呵呵哒了。
肿么办呢,当然是改啦。主要的问题是主键策略不支持。于是题主就给她新增了一种逐渐策略,名字就叫 “DDB”。同样是通过拦截器修改 mybatis 的 Configuration 实现的。
同时新增了一个支持 DDB 批量 Insert 的 Mapper,使用全局替换符的形式实现。
在对原生的 Mapper 做了这 2 个增强以后,就可以愉快的支持 DDB 的增删改查了。
使用时,请引入以下 jar 包:
<dependency>
<groupId>com.netease.pop.mybatis</groupId>
<artifactId>mapper</artifactId>
<version>4.0.0</version>
</dependency>
同时,在配置文件中增加如下 2 行:
INDENTITY=DDB 表示使用名称为 DDB 的主键策略 (或者也可以在实体类的 GeneratedValue 注解中指定 generator 命令)
ORDER=BEFORE 表示在 insert 命令前执行该主键策略 (这是为了在 insert 前获取主键 id 值来使用)
其他
除了节省书写 sql 的时间外,配合另一个分页的开源插件 PageHelper 使用,可以事半功倍。使用上简单到可怕。
用法示例如下:
PageHelper.offsetPage(offset, limit);
Page<MaterialMeta> metas = (Page<MaterialMeta>) materialDao.selectByExample(example);
没错,就只有这么一行。。。