17、通用枚举类型处理(二)
来源:互联网 发布:网络优化塔工2017招聘 编辑:程序博客网 时间:2024/06/10 04:18
问题
要是我们一个项目特别大,有几十个甚至是上百个枚举呢,那怎么办,难道我要一个个在typeHandler里面去加,加一百几十行?!个人觉得非常麻烦,影响我们的开发速度,so,能不能实现我们想要的像扫描下枚举的所在的包目录就可以注册的枚举做自动转换呢?具体怎么实现?
typeHandler的注册流程
具体过程参考15
切入点
由Cosnfiguration
对象得到typeHandlerRegistry管理器,入手的方法就是typeHandlerElement方法,在里面我们添加多一个包扫描功能,为万能转换处理器注册所指定的包下面所有的枚举
方案一
SqlSessionFactoryBean
由于我们项目使用了Spring, 是用Spring集成的Mybatis(废话,大家都是这么干的)。Spring通过SqlSessionFactoryBean来初始化启动Mybatis。 因此,我们应该在它身上下手,然而,一切并不是那么顺利。
查看了一下SqlSessionFactoryBean的源码,发现SqlSessionFactoryBean并没有任何地方可以让我们切入, 进而来调用TypeHandlerRegistry进行注册我们的枚举。 更令人蛋疼的是其所有属性全是private, 这下不仅AOP切入不行,连通过继承偷懒都不行了。
只有老老实实的重写一遍SqlSessionFactoryBean的代码了
DefaultSqlSessionFactoryBean
- DefaultSqlSessionFactoryBean继承SqlSessionFactoryBean。
- 将SqlSessionFactoryBean中的代码全部copy到DefaultSqlSessionFactoryBean。
- 调用以下方法。
package com.lf.sqlSessionFactoryBean;import com.lf.BaseEnum;import com.lf.typehandle.BaseEnumTypeHandle;import org.apache.ibatis.builder.xml.XMLConfigBuilder;import org.apache.ibatis.builder.xml.XMLMapperBuilder;import org.apache.ibatis.executor.ErrorContext;import org.apache.ibatis.io.ResolverUtil;import org.apache.ibatis.mapping.Environment;import org.apache.ibatis.plugin.Interceptor;import org.apache.ibatis.session.Configuration;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.type.TypeHandler;import org.apache.ibatis.type.TypeHandlerRegistry;import org.mybatis.spring.SqlSessionFactoryBean;import org.mybatis.spring.transaction.SpringManagedTransactionFactory;import java.io.IOException;import java.sql.SQLException;import java.util.Set;/** * Created by LF on 2017/6/12. */public class DefaultSqlSessionFactoryBean extends SqlSessionFactoryBean { protected SqlSessionFactory buildSqlSessionFactory() throws IOException { Configuration configuration; XMLConfigBuilder xmlConfigBuilder = null; if (this.configuration != null) { configuration = this.configuration; if (configuration.getVariables() == null) { configuration.setVariables(this.configurationProperties); } else if (this.configurationProperties != null) { configuration.getVariables().putAll(this.configurationProperties); } } else if (this.configLocation != null) { xmlConfigBuilder = new XMLConfigBuilder(this.configLocation.getInputStream(), null, this.configurationProperties); configuration = xmlConfigBuilder.getConfiguration(); } else { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Property 'configuration' or 'configLocation' not specified, using default MyBatis Configuration"); } configuration = new Configuration(); if (this.configurationProperties != null) { configuration.setVariables(this.configurationProperties); } } if (this.objectFactory != null) { configuration.setObjectFactory(this.objectFactory); } if (this.objectWrapperFactory != null) { configuration.setObjectWrapperFactory(this.objectWrapperFactory); } if (this.vfs != null) { configuration.setVfsImpl(this.vfs); } if (hasLength(this.typeAliasesPackage)) { String[] typeAliasPackageArray = tokenizeToStringArray(this.typeAliasesPackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); for (String packageToScan : typeAliasPackageArray) { configuration.getTypeAliasRegistry().registerAliases(packageToScan, typeAliasesSuperType == null ? Object.class : typeAliasesSuperType); if (LOGGER.isDebugEnabled()) { LOGGER.debug("Scanned package: '" + packageToScan + "' for aliases"); } } } if (!isEmpty(this.typeAliases)) { for (Class<?> typeAlias : this.typeAliases) { configuration.getTypeAliasRegistry().registerAlias(typeAlias); if (LOGGER.isDebugEnabled()) { LOGGER.debug("Registered type alias: '" + typeAlias + "'"); } } } if (!isEmpty(this.plugins)) { for (Interceptor plugin : this.plugins) { configuration.addInterceptor(plugin); if (LOGGER.isDebugEnabled()) { LOGGER.debug("Registered plugin: '" + plugin + "'"); } } } if (hasLength(this.typeHandlersPackage)) { String[] typeHandlersPackageArray = tokenizeToStringArray(this.typeHandlersPackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); for (String packageToScan : typeHandlersPackageArray) { configuration.getTypeHandlerRegistry().register(packageToScan); if (LOGGER.isDebugEnabled()) { LOGGER.debug("Scanned package: '" + packageToScan + "' for type handlers"); } } } if (!isEmpty(this.typeHandlers)) { for (TypeHandler<?> typeHandler : this.typeHandlers) { configuration.getTypeHandlerRegistry().register(typeHandler); if (LOGGER.isDebugEnabled()) { LOGGER.debug("Registered type handler: '" + typeHandler + "'"); } } } if (this.databaseIdProvider != null) {//fix #64 set databaseId before parse mapper xmls try { configuration.setDatabaseId(this.databaseIdProvider.getDatabaseId(this.dataSource)); } catch (SQLException e) { throw new NestedIOException("Failed getting a databaseId", e); } } if (this.cache != null) { configuration.addCache(this.cache); } if (xmlConfigBuilder != null) { try { xmlConfigBuilder.parse(); if (LOGGER.isDebugEnabled()) { LOGGER.debug("Parsed configuration file: '" + this.configLocation + "'"); } } catch (Exception ex) { throw new NestedIOException("Failed to parse config resource: " + this.configLocation, ex); } finally { ErrorContext.instance().reset(); } } if (this.transactionFactory == null) { this.transactionFactory = new SpringManagedTransactionFactory(); } configuration.setEnvironment(new Environment(this.environment, this.transactionFactory, this.dataSource)); if (!isEmpty(this.mapperLocations)) { for (Resource mapperLocation : this.mapperLocations) { if (mapperLocation == null) { continue; } try { XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(mapperLocation.getInputStream(), configuration, mapperLocation.toString(), configuration.getSqlFragments()); TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry(); //重点 regist(typeHandlerRegistry, BaseEnumTypeHandle.class, "com.lf,dist"); xmlMapperBuilder.parse(); } catch (Exception e) { throw new NestedIOException("Failed to parse mapping resource: '" + mapperLocation + "'", e); } finally { ErrorContext.instance().reset(); } if (LOGGER.isDebugEnabled()) { LOGGER.debug("Parsed mapper file: '" + mapperLocation + "'"); } } } else { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Property 'mapperLocations' was not specified or no matching resources found"); } } return this.sqlSessionFactoryBuilder.build(configuration); } private void regist(TypeHandlerRegistry typeHandlerRegistry, Class<?> typeHandlerClass, String... packageNames) { ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<Class<?>>(); resolverUtil.findImplementations(BaseEnum.class, packageNames); Set<Class<? extends Class<?>>> mTypes = resolverUtil.getClasses(); for (Class<?> javaTypeClass : mTypes) { typeHandlerRegistry.register(javaTypeClass, typeHandlerClass); } }}
方案二
没有使用spring的时候
其他的配置和正常使用的时候一样
package com.lf;import com.lf.typehandle.BaseEnumTypeHandle;import org.apache.ibatis.io.ResolverUtil;import org.apache.ibatis.io.Resources;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSessionFactoryBuilder;import org.apache.ibatis.type.TypeHandlerRegistry;import java.io.IOException;import java.io.InputStream;import java.util.Set;public class App { public static void main(String[] args) throws IOException { String resouce = "mybatis-config.xml"; InputStream is = Resources.getResourceAsStream(resouce); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is); TypeHandlerRegistry typeHandlerRegistry = sqlSessionFactory.getConfiguration().getTypeHandlerRegistry(); regist(typeHandlerRegistry, BaseEnumTypeHandle.class,"com.lf.dist"); SqlSession sqlSession = sqlSessionFactory.openSession(); Object one = sqlSession.selectOne("com.lf.dao.BlogPostMapper.selectByPrimaryKey", "1"); System.err.println(one); sqlSession.commit(); } private static void regist(TypeHandlerRegistry typeHandlerRegistry, Class<?> typeHandlerClass, String... packageNames) { ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<Class<?>>(); resolverUtil.findImplementations(BaseEnum.class, packageNames); Set<Class<? extends Class<?>>> mTypes = resolverUtil.getClasses(); for (Class<?> javaTypeClass : mTypes) { typeHandlerRegistry.register(javaTypeClass, typeHandlerClass); } }}
方案三
修改mybatis的源码
修改注解MappedTypes,添加扫描包的功能
package org.apache.ibatis.type;import java.lang.annotation.*;/** * @author Eduardo Macarron */@Documented@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)public @interface MappedTypes { Class<?>[] value() default {}; String[] basePackage() default {};}
修改register源码
// Only handler type public void register(Class<?> typeHandlerClass) { boolean mappedTypeFound = false; MappedTypes mappedTypes = typeHandlerClass.getAnnotation(MappedTypes.class); if (mappedTypes != null) { for(String basePackage:mappedTypes.basePackage()){ ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<Class<?>>(); resolverUtil.find(new ResolverUtil.IsA(BaseEnum.class), basePackage); Set<Class<? extends Class<?>>> mTypes = resolverUtil.getClasses(); for (Class<?> javaTypeClass : mTypes) { register(javaTypeClass, typeHandlerClass); mappedTypeFound = true; } } for (Class<?> javaTypeClass : mappedTypes.value()) { register(javaTypeClass, typeHandlerClass); mappedTypeFound = true; } } if (!mappedTypeFound) { register(getInstance(null, typeHandlerClass)); } }
配置
<typeAliases> <package name="com.lf.entity"/> </typeAliases>
阅读全文
0 0
- 17、通用枚举类型处理(二)
- 16、通用枚举类型处理(一)
- 通用的枚举类型
- 15、处理枚举类型
- mybatis处理枚举类型
- Mybatis处理枚举类型
- 【枚举二】理解java枚举类型
- 对枚举类型的处理
- Java-枚举类型处理判断
- Java枚举类型(二)
- spring boot集成mybatis,枚举类型字段注册通用
- Python--枚举类型和异常处理
- mybatis TypeHandler处理自定义枚举类型
- 黑马训练营--枚举类型(二)
- UPMS通用用户权限系统——添加枚举类型的用户属性,获取枚举值
- 枚举类型
- 枚举类型
- 枚举类型
- 15、处理枚举类型
- SSH框架学习笔记(1)
- 16、通用枚举类型处理(一)
- zookeeper原理详解
- MySQL的多表联合查询
- 17、通用枚举类型处理(二)
- C头文件包含
- JAVA面向对象2:构造方法和this关键字
- 什么是信用利差
- Java简介
- hamming distance
- 基本线性数据结构的Python实现
- thrift简单入门
- hamming distance