Java tutorial
/* * The MIT License (MIT) * * Copyright (c) 2014-2016 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.hand.hap.mybatis.mapperhelper; import com.hand.hap.mybatis.entity.Config; import com.hand.hap.mybatis.util.StringUtil; import org.apache.ibatis.annotations.DeleteProvider; import org.apache.ibatis.annotations.InsertProvider; import org.apache.ibatis.annotations.SelectProvider; import org.apache.ibatis.annotations.UpdateProvider; import org.apache.ibatis.builder.annotation.ProviderSqlSource; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.session.Configuration; import com.hand.hap.mybatis.provider.EmptyProvider; import java.lang.reflect.Method; import java.util.*; import java.util.concurrent.ConcurrentHashMap; /** * ?? * <p/> * <p>? : <a href="https://github.com/abel533/Mapper" target="_blank">https://github.com/abel533/Mapper</a></p> * * @author liuzh */ public class MapperHelper { /** * skip */ private final Map<String, Boolean> msIdSkip = new HashMap<String, Boolean>(); /** * ? */ private List<Class<?>> registerClass = new ArrayList<Class<?>>(); /** * Mapper? */ private Map<Class<?>, MapperTemplate> registerMapper = new ConcurrentHashMap<Class<?>, MapperTemplate>(); /** * msidMapperTemplate */ private Map<String, MapperTemplate> msIdCache = new HashMap<String, MapperTemplate>(); /** * Mapper? */ private Config config = new Config(); /** * */ public MapperHelper() { } /** * ? * * @param properties */ public MapperHelper(Properties properties) { this(); setProperties(properties); } /** * ?Mapper? * * @return */ public Config getConfig() { return config; } /** * Mapper? * * @param config */ public void setConfig(Config config) { this.config = config; } /** * Mapper??MapperTemplate * * @param mapperClass * @return * @throws Exception */ private MapperTemplate fromMapperClass(Class<?> mapperClass) { Method[] methods = mapperClass.getDeclaredMethods(); Class<?> templateClass = null; Class<?> tempClass = null; Set<String> methodSet = new HashSet<String>(); for (Method method : methods) { if (method.isAnnotationPresent(SelectProvider.class)) { SelectProvider provider = method.getAnnotation(SelectProvider.class); tempClass = provider.type(); methodSet.add(method.getName()); } else if (method.isAnnotationPresent(InsertProvider.class)) { InsertProvider provider = method.getAnnotation(InsertProvider.class); tempClass = provider.type(); methodSet.add(method.getName()); } else if (method.isAnnotationPresent(DeleteProvider.class)) { DeleteProvider provider = method.getAnnotation(DeleteProvider.class); tempClass = provider.type(); methodSet.add(method.getName()); } else if (method.isAnnotationPresent(UpdateProvider.class)) { UpdateProvider provider = method.getAnnotation(UpdateProvider.class); tempClass = provider.type(); methodSet.add(method.getName()); } if (templateClass == null) { templateClass = tempClass; } else if (templateClass != tempClass) { throw new RuntimeException("Mapper??MapperTemplate?!"); } } if (templateClass == null || !MapperTemplate.class.isAssignableFrom(templateClass)) { templateClass = EmptyProvider.class; } MapperTemplate mapperTemplate = null; try { mapperTemplate = (MapperTemplate) templateClass.getConstructor(Class.class, MapperHelper.class) .newInstance(mapperClass, this); } catch (Exception e) { throw new RuntimeException("MapperTemplate:" + e.getMessage()); } // for (String methodName : methodSet) { try { mapperTemplate.addMethodMap(methodName, templateClass.getMethod(methodName, MappedStatement.class)); } catch (NoSuchMethodException e) { throw new RuntimeException(templateClass.getCanonicalName() + "" + methodName + "!"); } } return mapperTemplate; } /** * Mapper? * * @param mapperClass */ public void registerMapper(Class<?> mapperClass) { if (!registerMapper.containsKey(mapperClass)) { registerClass.add(mapperClass); registerMapper.put(mapperClass, fromMapperClass(mapperClass)); } //? Class<?>[] interfaces = mapperClass.getInterfaces(); if (interfaces != null && interfaces.length > 0) { for (Class<?> anInterface : interfaces) { registerMapper(anInterface); } } } /** * Mapper? * * @param mapperClass */ public void registerMapper(String mapperClass) { try { registerMapper(Class.forName(mapperClass)); } catch (ClassNotFoundException e) { throw new RuntimeException("Mapper[" + mapperClass + "]?Mapper!"); } } /** * ???? * * @param msId * @return */ public boolean isMapperMethod(String msId) { if (msIdSkip.get(msId) != null) { return msIdSkip.get(msId); } for (Map.Entry<Class<?>, MapperTemplate> entry : registerMapper.entrySet()) { if (entry.getValue().supportMethod(msId)) { msIdSkip.put(msId, true); msIdCache.put(msId, entry.getValue()); return true; } } msIdSkip.put(msId, false); return false; } /** * ???? * * @param mapperInterface * @return */ public boolean isExtendCommonMapper(Class<?> mapperInterface) { for (Class<?> mapperClass : registerClass) { if (mapperClass.isAssignableFrom(mapperInterface)) { return true; } } return false; } /** * ?SqlSource * <p/> * ?isMapperMethod?msIdCache * * @param ms */ public void setSqlSource(MappedStatement ms) { MapperTemplate mapperTemplate = msIdCache.get(ms.getId()); try { if (mapperTemplate != null) { mapperTemplate.setSqlSource(ms); } } catch (Exception e) { throw new RuntimeException(e); } } /** * ? * * @param properties */ public void setProperties(Properties properties) { config.setProperties(properties); //? String mapper = null; if (properties != null) { mapper = properties.getProperty("mappers"); } if (StringUtil.isNotEmpty(mapper)) { String[] mappers = mapper.split(","); for (String mapperClass : mappers) { if (mapperClass.length() > 0) { registerMapper(mapperClass); } } } } /** * ??? */ public void ifEmptyRegisterDefaultInterface() { if (registerClass.size() == 0) { registerMapper("Mapper"); } } /** * ????? * <br>?configurationMappedStatement * * @param configuration */ public void processConfiguration(Configuration configuration) { processConfiguration(configuration, null); } /** * ?? * * @param configuration * @param mapperInterface */ public void processConfiguration(Configuration configuration, Class<?> mapperInterface) { String prefix; if (mapperInterface != null) { prefix = mapperInterface.getCanonicalName(); } else { prefix = ""; } for (Object object : new ArrayList<Object>(configuration.getMappedStatements())) { if (object instanceof MappedStatement) { MappedStatement ms = (MappedStatement) object; if (ms.getId().startsWith(prefix) && isMapperMethod(ms.getId())) { if (ms.getSqlSource() instanceof ProviderSqlSource) { setSqlSource(ms); } } } } } }