3,通用mapper
通用mapper有很多集成形式
https://github.com/abel533/Mapper/wiki/1.3-spring-boot
1,java 编码方式集成
java编码方式集成是最少见的一种情况,但是通过你这种集成可以让大家看到通用mapper集成的入口,这里会提供2种形式
1,最直接的形式
2,使用 configuration 作为入口集成
1.1.1 添加依赖
在开始写代码前,先把依赖添加进来
在java 编码集成方式中,首先你肯定已经引入了mybatis的依赖
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>版本号</version>
</dependency>
最新版本号 http://mvnrepository.com/artifact/tk.mybatis/mapper-spring-boot-starter
通用 Mapper 支持 MyBatis 3.2.4+
在mybatis依赖的基础上, 添加通用的mapper 的依赖即可
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper</artifactId>
<version>最新版本</version>
</dependency>
最新版本看这里:http://mvnrepository.com/artifact/tk.mybatis/mapper
如果你使用的 Jar 包,你可以通过上面提供的链接下载 Jar。
1.2编写代码集成
在使用java编码方式时,正常情况下你都会有构建sqlsessionFactory的代码
在创建sqlSessionFactory 对象前或者后对应俩种配置通用Mapper 的方法,由于没有提供mybatis-config.xml 文件的解析类,这里推荐使用创建后的方式来创建。
1.1.2.1创建后
在创建后SqlSessionFactory 后,在任何其他调用发生前,使用下面的方式配置通用Mapper。
//从刚刚创建的sqlSessionFactory 中获取 session
session =SqlSessionFactory.openSession();
//创建一个MapperHelper
MapperHelper mapperHelper =new MapperHelper();
//特殊配置
Config config =new Config();
//主键自增回写方法,默认值为MYSQL
config.setIDENITY("mysql");
//支持getter和setter方法上的注解
config.setEnableMethodAnnotation(true);
//启动简单类型
config.setUseSimpleType(true);
//自动处理关键字 -mysql
config.setWrapKeyword(" '{0}' ");
//设置配置
mapperHelper.setConfig(config);
//注册通用接口,和其他集成方式中的mappers 参数作用相同
//4.0之后的版本,如果类似Mapper.class这样的基础接口带有 @RegisterMapper注解,就不必在这里注册了
mapperHelper.pocessConfiguration(session.getConfiguration());
如果省略config的配置 ,上述代码简化为:
从刚刚创建的 sqlSessionFactory 中 获取 session
session =sqlSessionFactory.openSession();
//创建一个MapperHelper
MapperHelper mapperHelper =new MapperHelper();
mapperHelper.processConfiguration(session.getFiguration());
通用Mapper 默认就是-通过 session.getConfiguration()获取所有的Mybatis方法,然后对其中属于通用通用方法的方法进行处理。
1.2.2创建前
创建前就是通过使用 tk.mybatis.mapper.session.Configuration 替换MyBatis中的org.apache.ibatis.session.Configuration 来实现。配置代码如下
Configuration configuration =new Configuration();
//这里可以参考上面的方式进行配置 MapperHelper
configuration.setMapperHelper(new MapperHelper());
sqlSessionFactory =new SqlSessionFactoryBuilder().build(configuration);
实现原理
这种配置方式是通过重写原 Configuration 中的 addMappedStatement 方法来实现的:
@Override
public void addMappedStatement(MappedStatement ms){
try{
supper.addMappedStatement (ms);
//没有任何配置时,使用默认配置
if(this.mapperHelper == null){
this.mapperHelper =new MapperHelper();
}
this.mapperHelper.processMappedStatement(ms);
}catch(Excetion e){
//这里的异常是导致Spring 启动死循环的关键位置。为了后续被吞异常,这里直接输出
e.printStackTrace(e);
throw new RuntimeException(e);
}
}
通过上述其中一种方式配置后,通用方法都会生效。
接下来抢看下一章内容:
细化以来的方法
2.1简单的实例、
实例针对mysql数据库(数据库对主键影响大,和insert 关系密切)。
数据库有如下表:
CREATE TABLE `country` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
`countryname` varchar(255) DEFAULT NULL COMMENT '名称',
`countrycode` varchar(255) DEFAULT NULL COMMENT '代码',
PRIMARY KEY (`Id`)
) ENGINE=InnoDB AUTO_INCREMENT=10011 DEFAULT CHARSET=utf8 COMMENT='国家信息';
对应的 java 实体类型如下:
public class Country{
@Id
private Integer id;
private String countryname;
private String countrycode;
//省略 getter 和setter
}
最简单的情况下,只需要一个@Id 标记字段为主键即可。数据库的字段名和实体类的字段名是完全相同的,这种情况下尸体和表可以直接映射。
提醒: 如果实体类中没有一个标记@id 的字段,当你使用带有 ByPrimaryKey 的方法时,所有的字段会作为年联合主键来使用,也就会出现类似 wher id =? and countryname =? and countrycode =? 的情况
通用Mapper 提供了大量的通用接口,这里以最常用的Mapper 接口为例子
该实体类对应的数据库操作接口如下:
import tk.mybatis.mapper.common.Mapper;
public interface CountryMapper extends Mapper<Country> {
}
只要配置MyBatis 时能注册或者扫描到该接口,该接口提供的方法就都可以使用。
该接口默认继承的方法如下:
selectOne
select
selectAll
selectCount
selectByPrimaryKey
方法太多,省略其他
从 mybatis中 获取该接口后就可以直接使用
//从mybatis 或者 Spring 中获取 countryMapper,然后调用selectAll 方法
List<Country> countries =countryMappr.selectAll();
//根据主键查询
Country country =countryMapper.selectByPrimaryKey(1);
//或者使用对象传参,适用于一个字段或者多个字段联合主键使用
Country query =new Country();
query.setId(1);
country =countryMapper.selectByPrimaryKey(query);
如果想要增加自己写的方法,可以直接在CountryMapper中增加
1,使用纯接口注解方式时
import org.apache.ibatis.annotations.Select;
import tk.mybatis.mapper.common.Mapper;
public interface CountryMapper extends Mapper<Country>{
@Select(" select * from country where countryname = #{countryname}")
Country selectByCountryName(String countryname)
}
这里只是举了个简单的例子,可以时很复杂的查询
2,如果使用 xml 方式,需要提供接口对应的xml 文件
例如提供了CountryMapper.xml 文件 ,内容如下:
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="tk.mybatis.sample.mapper.CountryMapper">
<select id="selectByCountryName" resultType="tk.mybatis.model.Country">
select * from country where countryname = #{countryname}
</select>
</mapper>
在接口中添加对应的方法:
import tk.mybatis.mapper.common.Mapper;
public interface CountryMapper extends Mapper<Country>{
Country selectByCountryName(String countryname);
}
在接口中添加其他方法的时候 和只用Mybatis 是完全一样的,但是需要注意,在对应的XML中,不能出现和继承接口中同名的方法!。
多态~
在接口中,只要不是通过注解来是实现接口的方法,接口是允许重名的,真正调用会使用通用Mapper 提供的方法。
例如在上面 CountryMapper中提供一个 带分页的selectAll方法
public interface CountryMapper extends Mapper<Country>{
List<Country> selectAll(RowBounds rowbounds);
}
在java 8的接口中 通过默认方法还能增加一些简单的间接调用方法,例如:
public interface CountryMapper extends Mapper<Country>{
//这个势力适合参考实现对乐观锁方法的封装
default void updateSuccess(Country country){
Assert.assertEquals(1,updateByPrimarykey(country));
}
}
2.2 数据库映射 mapping
在2.1中 看到的最简单的情况,实际使用过程中也不会更复杂,下面是更详细的映射配置。
在通用Mapper中,默认情况下是将实体类字段按照驼峰转下划线形式的标明,列名进行转换
例如:实体类的username 可以映射到表的 user_name 上。
如果 想要修改默认的转换方式,可以在后续的配置中,修改style 全局配置。
数据库映射主要涉及得到一些注解和全局配置,这一节中会介绍所有的注解,后面章节中会有配置的介绍。
通用Mapper 默认使用了 几个简单的注解,其他JPA 的注解默认并不支持。但是如果你开发自己的通用方法,你可以使用jap 注解 或引入自己的注解。
2..2.1@NameStyle 注解(Mapper)
这个注解可以在类上进行配置,优先级高于对应的 style 全局配置。
注解支持以下几个选项:
normal, //原值
camelhump, //驼峰转下划线
uppercase, //转换为大写
lowercase, //转换为小写
camelhumpAndUppercase, //驼峰转下划线大写形式
camelhumpAndLowercase, //驼峰转下划线小写形式
使用时,直接在类上配置即可,例如:
@NameStyle(Style.camelhumpAndUppercase)
public class Country
配置该注解后,对该类和其中的字段进行转换时,会将形如 userName 的字段转换为表中的 USER_NAME 字段。
2.2.2 @table 注解(JPA)
@table 注解可以配置name,catalog 和schema 三个属性,配置name 属性后,直接使用提供的表名不再根据实体类名进行转换。其他2个属性中,同时配置时,catalog 优先高于 schema, 也就是只有 catalog 会生效。
配置实例如下:
@Table(name ="sys_user")
public class User{}
将user 实体映射到 sys_user 表。
2.2.3 @Colum 注解(JPA)
@Column 注解支持nam, insertable 和updateable 三个属性
name 配置映射的列名
insertable 对提供的insert 方法 有效,如果设置false 就不会出现在sql中
updateable 对提供的update 方法有效 ,设置为 false 后 不会出现在sql中。
配置实例如下:
@Column(name =" user_name")
private String name;
除了直接映射 name 到 user_name 这种用法外,在使用关键字的情况,还会有下面的用法:
@Column(name =" 'orer' ")
private String order;
对于关键字这种情况,通用mapper 支持自动转换,可以查看后续配置文档中的wrapKeyword配置。
2.2.4 @ColumnType 注解(mapper)
这个注解提供的 column属性 和 @Colum 中的那么作用相同。但是@column 的优先级更高,除了name属性外,这个注解主要提供了jdbcType 属性和typeHandler属性。
jdbcTYpe 用于设置特殊数据库类型时制定数据库中的jdbcType。
typeHandler 用于设置特殊类型处理器,常见的是枚举。
用法实例如下:
@ColumnType(column =" countryname",jdbcType =JdbcType.VARCHAR,
typeHandler =StringTypeHandler.class)
pivate Sring countryname;
2.2.5 @Transient 注解(JPA)
一般情况下 ,实体中的字段和数据库中的字段是一一对应的,但是也有很多情况我们也会在实体中增加一些额外的属性,这种情况下,就需要使用 @Transient 注解来告诉通用Mapper这不是表中的字段。
默认情况下,只有简单类型会自动认为是表中的字段(可以通过配置中的useSimpleType)
这里简单的类型不包括java 中的八种基本类型;
byte,short,int,Long, float, double,char,boolean
这是因为在类中,基本类型会有默认值,而mybatis 中经常会需要判断属性值是否为空,所以不要在类中使用基本类型。否则会遇到莫名其妙 错误。
对于类中复杂的参数,以及Map, Lit 等属性不需要配置该注解。
对于枚举类型作为数据库字段的情况,需要看配置中的enumAsSimpleType 参数。
配置实例:
@Transient
private String otherThings; // 非数据库表中字段
2.2.6 @Id 注解(JPA)
上面结果注解都涉及到映射,@Id 注解和映射无关,他是一个特殊的标记,用于标识数据库中的主键字段。
正常情况下,一个实体类中至少需要标记一个 @Id 注解的字段,存在来奶和主键时候可以标记多个,如果表中没有主键,类中可以不用标记,
当类中没有存在标记@Id 注解字段时候,你可以了解为类中的所有字段是联合主键,使用所有的ByPrimaryKey 相关方法时 ,有 where 条件的地方,会将所有的列作为条件。
配置实例:
@Id
private Integer id;
或者联合主键
@id
private Integer userId;
@Id
private Integer roleid;
2.2.7 @KeySql 注解
主键策略注解,用于配置如何生成主键
这是通用mapper的自定义注解,改注解的目的就是替换@GeneratedValue 注解
2.2.8 @GeneratedValue 注解(JPA)
主键策略注解,用于配置如何生成
2.2.9 @version 注解(Mapper)
@Version 时实现乐观锁的一个注解,大多数人不需要
‘’2.2.10 @RegisterMapper 注解、
为了解决通用Mapper 中最常见的的一个错误而增加的标记注解,该注解仅用于开发通用接口,不是实体类上使用的
3,配置
由于数据库存在各种各样的差异,因此有时候要做一些必要的配置。
此外通用Mapper还提供了一些控置参数和一些和主键策略相关的参数。
通用mapper 提供了下面这些参数
1mappers
2,IDENTITY
3,ORDER(别名: order,before)
4,catalog
5,schema
6,notEmpty
7,style
8, enableMethodAnnotation
9.useSimpleTypes
10,usePrimitiveType;
11,simpleTypes;
12,enumAsSimpleType;
13,wrapKeyword
14,checkExampleEntityClass
15,safeDelete
16,safeUpdate
17,useJavaType
下面分别对这些参数进行介绍
3.1 mappers
3.2 IDENTITY
取回主键的形式,
配置时写为 , IDENTITY =MYSQL
3.3 ORDER(别名: order,before)
<selcetKey>中的order 属性,可以选值为 BEFORE 和AFTER
后面为了方便在springboot 中配置参数,符合boot规范,增加了order和 before 2个别名
在支持主键递增,配置如下
properties 方式配置时
order =after
//还可以
order =after
//或
before =false
//spring boot 中 ,比上面多了个前缀,并且order 不能使用
mapper.order =after
//或者 spring boot
mapper.before=false
在类似 Oracle 序列或者通用的UUID时,配置如下:
//properties 方式配置时
order =before
//还可以
order =before
//或
before =true;
//spring boot 中,比上面多了个前缀,并且order 不能使用
mapper.order =before
//或者
mapper.before =true
上面写的实例中有多种写法,根据需要选取一种就可以,切勿同时配置
3.4 catalog
数据库的catalog,如果设置该值,查询时候表名湖带catalog设置的前缀
35, shcema
同 catalog,catalog优先级高于 schema
36,notEmpty
insertSelective 和 updateByPrimarykeySelective 中, 是否判断 字段类型 !=' '.
配置方式:
notEmpty =true
3.7style
实体和表转换时的默认规则,可选值如下
normal: 原值
camelhump: 驼峰转下划线
uppercase: 转化为大写
lowercase: 转换为小写
camelhumpAndUppercase: 驼峰转下划线大写形式
camelhumpAndLowercase: 驼峰转下划线小写形式
配置方式如下:
style =camelhumpAndUppercase
3.8 enableMethodAnnotation
可以控制是否支持(getter和 setter) 在方法上使用注解,默认 false.
配置方式如下
enableMethodAnnotation =true
启动后,可以按照夏敏
如果你需要对通用mapper进行配置。你可以在spring boot 的配置文件中配置mapper.前缀的配置
例如在yml 格式中配置:
mapper:
mappers:
- tk.mybatis.mapper.common.Mapper
- tk.mybatis.mapper.common.Mapper2
notEmpty: true
在 properties 配置中:
mapper.mappers=tk.mybatis.mapper.common.Mapper,tk.mybatis.mapper.common.Mapper2
mapper.notEmpty=true
基于Springboot 支持 Relax方式的参数,因此您的配置在notEmpty 时更多的是用not-empty, n也只有在spring boot中使用的时候参数名不必和配置中的完全一致
1.3.2@MapperScan 注解配置
你可以给带有 @Configuration 的类配合该注解,或者知己而配置到spring boot的启动类上,如下:
@tk.mybatis.spring.annotation.MapperScan(basePackages = "扫描包")
@SpringBootApplication
public class SampleMapperApplication implements CommandLineRunner {
}
注意:这里使用的 tk.mybatis.spring.annotation.MapperScan !
你可以直接在 Spring Boot 的配置文件中直接配置通用 Mapper(参考1.3.1中的配置),还可以使用注解中提供的两个属性进行配置:
/**
通用mapper 的配置,一行一个配置
/
String [] properties() defaulr{};
/
*还可以直接配置一个 mapperHelper bean
*/
String mapperHelperRef() default "";
使用这种放肆进行配置时