Ourbatis系列文章:
Ourbatis的工作原理是用实体类去映射表字段作为模板渲染的基础元数据:
另一个角度可以将这个过程看成元数据的加工流水线,在这个流水线中还有两个重要的角色在工作:注解
和Wrapper(包装器)
,他们会辅助加工。Mapping加工对象是Class<? extends Object>
Domain类以及一个String类型的字段mapperLocations
Mapper接口所在包名,每次映射都将会产生一个Table对象,它包含着相关的元数据:
字段名 | 类型 | 含义 |
---|---|---|
tableName | String | 表名 |
allColumns | List | 表所有字段结合 |
normalColumns | List | 表普通字段集合 |
primaryColumns | List | 表主键字段集合 |
domainClassName | String | 类全名 |
domainSimpleClassName | String | 类名 |
mapperClassName | String | Mapper接口类名 |
这些元数据可以在ourbatis.xml
中作为渲染的参数,之后将会着重讲解。
在Mapping加工的过程中,我们的传入Class的ClassName及FieldName将分别映射为表名和表字段名,当然,这种过程并不是写死的,我们可以通过注解和Wrapper包装器去修改它,这将会为我们的加工过程带来足够的灵活性,例如:
- 自定义表名
- 自定义表字段名
- 自定义Mapper接口包名
- 自定义转义(也可以在模板中实现)
无论是注解还是Wrapper,最终的目的都是为元数据提供一个外界控制入口,当我们需要根据应用场景去自定义Mapper映射时,注解和Wrapper配置将会变得非常有用!下一节将会逐一介绍他们!
值得一提的是,元数据中有一个数据非常特殊:mapperClassName
Mapper接口类名,明确来说它并不属于Domain的范畴,但是Ourbatis是通过Domain的类名及mapperLocations
配合注解和Wrapper去装配Mapper接口类名。
注解
Ourbatis的注解目前全部作用这Domain类中,这就意味着所有的注解都是为Mapper映射Domain到元数据而服务,另一方面,也和Wrapper相辅相成,下一章节将也会紧跟着介绍Wrapper,下面来看一下Ourbatis提供哪些注解:
@MapperBy
作用在Class上,指定Mapper映射接口类所在的包@RenderIgnore
作用在Field上,标注字段被Ourbatis映射时忽略@RenderName
可作用在Class和Field上,可以定义要映射的表名或者字段名RenderPrimary
作用在Field上,标注字段为主键
MapperBy
Mybatis是基于Mapper接口映射XML内定义的标签来实现SQL执行事件绑定的,大多数情况下,我们的Mapper接口会放在一个包下,然后使用Mybatis去扫描绑定。
但是如果我们的系统足够的复杂,例如多数据源,又或者根据不同的业务去放在不同的包下,这时就需要细节到Domain类上的Mapper类定义,MapperBy的作用就是如此!
@MapperBy("org.nico.ourbatis.mapper.user.UserMapper")
public class User{}
RenderIgnore
这个主键的作用很简单,将标注的Field在映射元数据的过程中忽略掉。
RenderName
RenderName是自定义映射名称,它的内部有两个属性:
public @interface RenderName {
String value();
boolean render() default false;
}
value
代表着映射的名称render
代表着是否继续参与渲染,也就是之后的包装器的渲染
value参数没什么好讲的,render要着重讲一下,在元数据映射的过程中我们有两种方式可以修饰元数据:注解和Wrapper,Ourbaits会优先处理注解,然后再使用Wrapper进行修饰渲染,如果我们两种方式同时使用,就会有叠加的效果,要控制效果是否叠加,就要设定render
这个参数来控制!
如果render为true,表示在注解自定的基础上仍然使用Wrapper去渲染,为false则反之。
RenderPrimary
标注在主键字段上,渲染的字段将会被添加到primaryColumns
集合中,不标注该注解的字段则会被添加到normalColumns
集合中。
紧跟着来看一下包装器Wrapper!
Wrapper包装器
注解的作用域细化到了Domain类上,而Wrapper则是起着对元数据全局修饰的作用,我们可以在org.nico.ourbatis.Ourbatis
类中看到配置入口:
/**
//Java Field -> Sql Column 过程的包装
public static final List<Wrapper<String>> JDBC_NAME_WRAPPERS = new ArrayList<Wrapper<String>>();
//Java Class -> Sql Table 过程的包装
public static final List<Wrapper<String>> TABLE_NAME_WRAPPERS = new ArrayList<Wrapper<String>>();
//Java Class -> Mapper映射几口名称的包装
public static final List<Wrapper<String>> MAPPER_NAME_WRAPPERS = new ArrayList<Wrapper<String>>();
如果您只使用Ourbatis,可以去直接获取到上面三个集合并添加自定义的包装器。如果您的应用使用Spring Boot开发,我们在其中定制了一套默认的包装器:
public class OurbatisDefaultConfigue implements OurbatisConfigure{
protected SlideBarJointWrapper slideBarJointWrapper = new SlideBarJointWrapper();
protected FieldEscapeWrapper fieldEscapeWrapper = new FieldEscapeWrapper();
@Override
public void configWrapper(List<Wrapper<String>> JDBC_NAME_WRAPPERS, List<Wrapper<String>> TABLE_NAME_WRAPPERS,
List<Wrapper<String>> MAPPER_NAME_WRAPPERS, Map<Class<?>, String> JAVA_TYPE_WRAPPERS) {
TABLE_NAME_WRAPPERS.add(slideBarJointWrapper);
JDBC_NAME_WRAPPERS.add(slideBarJointWrapper);
MAPPER_NAME_WRAPPERS.add(value -> {return value + "Mapper";});
}
@Override
public void configAdapter(Map<String, AssistAdapter> ASSIST_ADAPTERS) {
}
}
当然您也可以通过继承的方式自定义,而一个包装器的定义方式也及其的简单:
MAPPER_NAME_WRAPPERS.add(value -> {return value + "Mapper";});
这个包装器的应用是在对Domain类名做包装,在尾部增加Mapper,来拼装为Mapper接口的地址,如User实体类映射的Mapper接口名称为UserMapper,当然也有实现接口的方式定制Wrapper:
//驼峰式转下滑杠
public class SlideBarJointWrapper implements Wrapper<String>{
public static final char UNDERLINE='_';
@Override
public String wrapping(String value) {
if (value == null || StringUtils.BLANK.equals(value.trim())){
return StringUtils.BLANK;
}
int len = value.length();
StringBuilder sb = new StringBuilder(len);
for (int i = 0; i < len; i++) {
char c = value.charAt(i);
if (Character.isUpperCase(c)){
if(i > 0) {
sb.append(UNDERLINE);
}
sb.append(Character.toLowerCase(c));
}else{
sb.append(c);
}
}
return sb.toString();
}
}
在Wrapper的使用过程中要注意的一点是,Wrapper的设置是全局通用的,不要因为满足一处而使整个应用设置变得不通用!