Ourbatis元数据映射

Ourbatis是一种灵活的ORM框架,利用实体类映射表字段作为元数据基础,支持自定义表名、字段名和Mapper接口包名。通过注解和包装器提供元数据的外部控制入口,增强映射灵活性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Ourbatis系列文章:

Ourbatis的工作原理是用实体类去映射表字段作为模板渲染的基础元数据:

在这里插入图片描述

另一个角度可以将这个过程看成元数据的加工流水线,在这个流水线中还有两个重要的角色在工作:注解Wrapper(包装器),他们会辅助加工。Mapping加工对象是Class<? extends Object>Domain类以及一个String类型的字段mapperLocationsMapper接口所在包名,每次映射都将会产生一个Table对象,它包含着相关的元数据:

字段名类型含义
tableNameString表名
allColumnsList表所有字段结合
normalColumnsList表普通字段集合
primaryColumnsList表主键字段集合
domainClassNameString类全名
domainSimpleClassNameString类名
mapperClassNameStringMapper接口类名

这些元数据可以在ourbatis.xml中作为渲染的参数,之后将会着重讲解。

在Mapping加工的过程中,我们的传入Class的ClassName及FieldName将分别映射为表名和表字段名,当然,这种过程并不是写死的,我们可以通过注解和Wrapper包装器去修改它,这将会为我们的加工过程带来足够的灵活性,例如:

  • 自定义表名
  • 自定义表字段名
  • 自定义Mapper接口包名
  • 自定义转义(也可以在模板中实现)

无论是注解还是Wrapper,最终的目的都是为元数据提供一个外界控制入口,当我们需要根据应用场景去自定义Mapper映射时,注解和Wrapper配置将会变得非常有用!下一节将会逐一介绍他们!

值得一提的是,元数据中有一个数据非常特殊:mapperClassNameMapper接口类名,明确来说它并不属于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的设置是全局通用的,不要因为满足一处而使整个应用设置变得不通用!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值