SpringBoot+MyBatis通用Mapper3实践浅析
阿里巴巴长期招聘Java研发工程师p6,p7,p8等上不封顶级别,有意向的可以发简历给我,注明想去的部门和工作地点:1064454834@qq.com
欢迎关注微信公众号:技术原始积累 获取更多技术干货
一、前言
MyBatis通用Mapper3是对mybaits的数据库操作的一层封装,之前使用时候是根据数据库表生成mapper.xml,mapper的接口类,这个mapper.xml和接口类被代理后生成能够操作数据对应表的基础功能,而Mapper3则是对其封装,基础功能不在需要mapper.xml,接口类只需要继承封装好的Mapper<T>接口就具有了操表的基础功能,如果你需要自己的操作则还是需要在mapper.xml中和接口类中写实现。Mapper3项目地址:http://git.oschina.net/free/Mapper
二、如何使用
2.1 引入maven配置
SpringBoot应用只需要引入:
<!--mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<!--mapper-->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>1.1.0</version>
</dependency>
<!--pagehelper-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.1.0</version>
</dependency>
2.2 generator 生成基础文件
在src/main/resources下面
generator.xml文件
<generatorConfiguration>
//属性值,下面的config.properties文件
<properties resource="config.properties"/>
<context id="Mysql" targetRuntime="MyBatis3Simple" defaultModelType="flat">
<property name="beginningDelimiter" value="`"/>
<property name="endingDelimiter" value="`"/>
//插件
<plugin type="${mapper.plugin}">
<property name="mappers" value="${mapper.Mapper}"/>
</plugin>
//数据源
<jdbcConnection driverClass="${jdbc.driverClass}"
connectionURL="${jdbc.url}"
userId="${jdbc.user}"
password="${jdbc.password}">
</jdbcConnection>
//Do生成
<javaModelGenerator targetPackage="${targetModelPackage}" targetProject="${targetJavaProject}"/>
//mapper xml文件
<sqlMapGenerator targetPackage="${targetXMLPackage}" targetProject="${targetResourcesProject}"/>
//mapper接口文件
<javaClientGenerator targetPackage="${targetMapperPackage}" targetProject="${targetJavaProject}" type="XMLMAPPER" />
<table tableName="lassen_swardman" >
<generatedKey column="uid" sqlStatement="Mysql" identity="true"/>
</table>
</context>
</generatorConfiguration>
cofing.properties文件
jdbc.driverClass = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://1270.0.1:3308/db
jdbc.user = ****
jdbc.password =****
jdbc.maxPoolSize=50
jdbc.minPoolSize=10
jdbc.maxStatements=100
jdbc.testConnection=true
# 插件
mapper.plugin = tk.mybatis.mapper.generator.MapperPlugin
mapper.Mapper = tk.mybatis.mapper.common.Mapper
然后在pom.xml配置如下:
<properties>
<!-- MyBatis Generator -->
<!-- Java接口和实体类 -->
<targetJavaProject>${basedir}/src/main/java</targetJavaProject>
<targetMapperPackage>com.zlx.demo.web.speech.mapper</targetMapperPackage>
<targetModelPackage>com.zlx.alin.demo.speech.model</targetModelPackage>
<!-- XML生成路径 -->
<targetResourcesProject>${basedir}/src/main/resources</targetResourcesProject>
<targetXMLPackage>mapper</targetXMLPackage>
<mybatis.version>3.4.2</mybatis.version>
<!-- <mapper.version>3.3.9</mapper.version>
--> <mapper.version>3.4.1.snapshot</mapper.version>
<mysql.version>5.1.30</mysql.version>
<mybatis.spring.version>1.2.4</mybatis.spring.version>
</properties>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.2</version>
<configuration>
<configurationFile>${basedir}/src/main/resources/generator/generatorConfig.xml</configurationFile>
<overwrite>true</overwrite>
<verbose>true</verbose>
</configuration>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper</artifactId>
<version>${mapper.version}</version>
</dependency>
</dependencies>
</plugin>
然后在pom所在目录执行:mvn mybatis-generator:generate 即可
生成的Mapper接口文件:
public interface SwardManMapper extends Mapper<SwardManDo>{
}
生成的Mapper.xml文件(里面没有任何操作):
<mapper namespace="com.zlx.demo.web.speech.mapper.SwardManMapper">
<resultMap id="BaseResultMap" type="com.zlx.demo.web.speech.model.SwardManDo" >
<!--
WARNING - @mbggenerated
-->
<id column="Id" property="id" jdbcType="INTEGER" />
<result column="name" property="name" jdbcType="VARCHAR" />
<result column="status" property="status" jdbcType="VARCHAR" />
</resultMap>
</mapper>
生成的Do文件:
@Table(name="lassen_swardman")
public class SwardManDo {
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Integer guild_id;
private String creator;
private String modifier;
private String name;
private String status;
private Date gmt_create;
private Date gmt_modified;
private String is_deleted;
private Integer power;
public String getCreator() {
return creator;
}
public void setCreator(String creator) {
this.creator = creator;
}
public String getModifier() {
return modifier;
}
public void setModifier(String modifier) {
this.modifier = modifier;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public Date getGmt_create() {
return gmt_create;
}
public void setGmt_create(Date gmt_create) {
this.gmt_create = gmt_create;
}
public Date getGmt_modified() {
return gmt_modified;
}
public void setGmt_modified(Date gmt_modified) {
this.gmt_modified = gmt_modified;
}
public String getIs_deleted() {
return is_deleted;
}
public void setIs_deleted(String is_deleted) {
this.is_deleted = is_deleted;
}
public Integer getPower() {
return power;
}
public void setPower(Integer power) {
this.power = power;
}
public Integer getGuild_id() {
return guild_id;
}
public void setGuild_id(int guild_id) {
this.guild_id = guild_id;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
2.3 测试
@RestController
@RequestMapping(value = "/speech/test")
public class TestRpc {
@Autowired
SwardManMapper swardManMapper;
@RequestMapping(value = "selectAll", method = { RequestMethod.GET, RequestMethod.POST })
public DecorateActionResult selectAll() {
ActionResult result = new ActionResult();
DecorateActionResult resultNew = new DecorateActionResult();
resultNew.setContent(result);
try {
result.setRetValue(swardManMapper.selectAll());
} catch (Exception ee) {
result.setErrorMessage(ee.getLocalizedMessage());
resultNew.setHasError(true);
}
return resultNew;
}
}
三、原理分析
一切的不同在于mapper接口类继承了Mapper<T>,所以分析其原理自然是看看Mapper<T>干了啥:
public interface Mapper<T> extends
BaseMapper<T>,
ExampleMapper<T>,
RowBoundsMapper<T>,
Marker {
}
public interface BaseMapper<T> extends
BaseSelectMapper<T>,
BaseInsertMapper<T>,
BaseUpdateMapper<T>,
BaseDeleteMapper<T> {
}
public interface BaseSelectMapper<T> extends
SelectOneMapper<T>,
SelectMapper<T>,
SelectAllMapper<T>,
SelectCountMapper<T>,
SelectByPrimaryKeyMapper<T>,
ExistsWithPrimaryKeyMapper<T> {
}
public interface SelectAllMapper<T> {
/**
* 查询全部结果
*
* @return
*/
@SelectProvider(type = BaseSelectProvider.class, method = "dynamicSQL")
List<T> selectAll();
}
一层层继承后找到了上面调用的selectAll的定义,原来使用的是SelectProvider注解,再看下selectAll的实现类BaseSelectProvider
public class BaseSelectProvider extends MapperTemplate {
public BaseSelectProvider(Class<?> mapperClass, MapperHelper mapperHelper) {
super(mapperClass, mapperHelper);
}
...........
/**
* 查询
*
* @param ms
* @return
*/
public String selectOne(MappedStatement ms) {
Class<?> entityClass = getEntityClass(ms);
//修改返回值类型为实体类型
setResultType(ms, entityClass);
StringBuilder sql = new StringBuilder();
sql.append(SqlHelper.selectAllColumns(entityClass));
sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass)));
sql.append(SqlHelper.whereAllIfColumns(entityClass, isNotEmpty()));
return sql.toString();
}
/**
* 查询全部结果
*
* @param ms
* @return
*/
public String selectAll(MappedStatement ms) {
final Class<?> entityClass = getEntityClass(ms);
//修改返回值类型为实体类型
setResultType(ms, entityClass);
StringBuilder sql = new StringBuilder();
sql.append(SqlHelper.selectAllColumns(entityClass));
sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass)));
sql.append(SqlHelper.orderByDefault(entityClass));
return sql.toString();
}
}
至此大概知道了是怎么玩的了,这些函数里面是拼接sql语句的。所以如果需要我们可以重写这些SelectProvider实现自己的逻辑,比如查找时候之筛选is_deleted='n'的等等。
欢迎关注微信公众号:技术原始积累 获取更多技术干货
image.png