在SpringBoot中定制自己的BeetlSql BaseMapper

原创
2019/01/14 22:34
阅读数 6.9K

在SpringBoot中定制自己的BeetlSql BaseMapper

前言

在项目中一直使用到了BeetlSql,并且项目是基于SpringBoot的,最近有些需求,需要定制自己的BaseMapper,Beetl官网的高级部分有说有如何定制BaseMapper,不过并没有涉及到SpringBoot中如何装载这个BaseMapper。下面就是记录下如何在SpringBoot中开启定制属于我们自己的BaseMapper之旅。

官网的文档其实已经写得挺清楚如何定制BaseMapper的了,但是在使用的时候,官网是使用SQLManager配置MyBaseMapper,然后通过sqlManager.getMapper(XXXDao.class)这种形式进行引用Dao;在Springboot中,我们希望通过继承定制的MyBaseMapper,直接注入Dao就可以使用,而不需要在使用定制的MyBaseMapper的时候,需要先通过SQLManager进行setBaseMapper,然后再sqlManager.getMapper()的形式调用。

开始定制

环境

首先我假定读者已经会使用Springboot,并且对BeetlSql的使用是有一定了解的。我环境中使用的是beetl-framework-starter,下面给出maven坐标。

<dependency>
	<groupId>com.ibeetl</groupId>
	<artifactId>beetl-framework-starter</artifactId>
	<version>1.1.70.RELEASE</version>
</dependency>

准备自己的MyBaseMapper

这一步其实就是定制自己的BaseMapper,针对于java8用户,其实这个过程就显得比较简单了,主要就是利用java8的接口默认实现,这里不会重点讲述这个,只是简单给出一些代码供参考,主要是想讲另外一种方式。

Java8接口默认实现方式

public interface MyBaseMapper<T> extends BaseMapper<T> {
	// 定义一个默认的实现
	default int fun() {
		// 拿到sqlManager和BaseMapper所有的方法,可以为所欲为了
		// 不过还是有些时候不是那么方便的。
		SQLManager sqlManager = getSQLManager();
		// ……
	}
}

上面大致表达了一下java8的接口默认实现方式来拓展自己的BaseMapper,不过可能也会存在一定的局限性,比如说……如果我想获取泛型T实际上对应的Entity类型(sqlManager有些方法用到)的时候,就不是那么方便了,不过也不是不可以,通过反射也是可以得到的。这里不展开了。下面重点说下BeetlSQL官方提供的那种方式。

BeetlSQL官网的拓展方式

首先还是要先来一个自己的BaseMapper的

public interface MyBaseMapper<T> extends BaseMapper<T> {

	Object fun(Object param);
}

紧接着定义一个Ami的实现类,实现MapperInvoke接口,目的是为了告诉beetlsql, 遇见这个方法名, 用对应的实现类来处理。

public class FunAmi implements MapperInvoke {
    @Override
    public Object call(SQLManager sm, Class entityClass, String sqlId, Method m, Object[] args) {
        // 在此处实现对应的逻辑即可,参数中已经传递够多信息的了,基本上可以为所欲为了
    }
}

好了,到了这里,根据官网的描述,其实就是将MyMapper中的fun和FunAmi对应上,也就是

MapperConfigBuilder builder = this.sqlManager.setBaseMapper(MyBaseMapper.class).getBuilder();

builder.addAmi("fun", new FunAmi());

不过在Springboot中,我们可不想随时随地都先获取sqlManager然后重复如此操作,而是想一劳永逸,最好是在初始化SqlManager的时候就给它设置进去!如何做到呢?

实现BeetlSqlCustomize接口

在查阅了beetl-framework-starter源代码后,发现在配置SqlManagerFactoryBean时,会注入BeetlSqlCustomize接口的实现,如果有的话,则会调用其customize方法。

beetl-faramework-starter中BeetlSqlSingleConfig.java的源码

@Configuration
@ConditionalOnBean(DataSource.class)
@Conditional(BeetlSqlSingleCondition.class)
@Import(BeetlMapperScannerRegister.class)
public class BeetlSqlSingleConfig {
	// 在此处有注入BeetlSqlCustomize接口的实现,但不是必须的
	@Autowired(required=false)
	BeetlSqlCustomize cust;
	@Autowired(required=false)
	ApplicationContext context;
	
	@Bean(name = "sqlManagerFactoryBean")
	@ConditionalOnMissingBean(SqlManagerFactoryBean.class)
	public SqlManagerFactoryBean getSqlManagerFactoryBean(BeetlSqlDataSource source,Environment env ) throws Exception {
		
		ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
		if(classLoader==null) {
			classLoader = this.getClass().getClassLoader();
		}
		
		BeetlSqlProperties beetlSqlProperties = new BeetlSqlProperties(env);
		SqlManagerFactoryBean factory = new SqlManagerFactoryBean();
		
		factory.setCs(source);
		factory.setDbStyle((DBStyle)ObjectUtil.tryInstance(beetlSqlProperties.getDbStyle(),classLoader));
		factory.setInterceptors(beetlSqlProperties.dev ? new Interceptor[] { new DebugInterceptor() } : new Interceptor[0]);
		factory.setNc((NameConversion)ObjectUtil.tryInstance(beetlSqlProperties.getNameConversion(),classLoader));
		ClasspathLoader loader = new ClasspathLoader(beetlSqlProperties.getSqlPath());
		//不能直接设置通过loader的autocheck
		Properties ps = new Properties();
		ps.put("PRODUCT_MODE", beetlSqlProperties.dev?"false":"true");
		factory.setExtProperties(ps);
		factory.setSqlLoader(loader);
		// 如果cust存在的话,则执行其自定义的方法
		if(cust != null) {
			cust.customize(factory);
		}
		return factory;
	}
	
	@Bean
	@ConditionalOnMissingBean(BeetlSqlDataSource.class)
	public BeetlSqlDataSource beetlSqlDataSource(DataSource dataSources){
		BeetlSqlDataSource source = new BeetlSqlDataSource();
		source.setMasterSource(dataSources);
		return source;
	}
}

源码里面早就给我们安排好了一切……那么到了这里,也已经柳暗花明了,接下来就是实现一个Customize就可以啦。

@Configuration
public class MyConfig {
    @Bean
    public BeetlSqlCustomize getBeetlSqlCustomize() {
        return sqlManager -> {
	        try {
			    SQLManager sqlManager = factoryBean.getObject();
			    MapperConfigBuilder builder = sqlManager.setBaseMapper(MyBaseMapper.class).getBuilder();
			    builder.addAmi("fun", new FunAmi());

			} catch (Exception e) {
				e.printStackTrace();
			}
		};
    }
}

通过上面这种方式,就可以在IOC容器初始化的时候加载自定义的BaseMapper啦。

总结

上面给出当定制自己的BaseMapper的时候,怎么跟SpringBoot进行整合注入,其实在这之前,主要也都是依靠官方文档,本文也算是对其做一点小小的补充吧,有时候官方文档可能写得不是很完善,但是可以通过阅读源码去分析是否给我们提供有一些接口可以对其进行拓展的。

展开阅读全文
加载中
点击加入讨论🔥(1) 发布并加入讨论🔥
打赏
1 评论
0 收藏
1
分享
返回顶部
顶部