Java tutorial
/* * The MIT License (MIT) * * Copyright (c) 2014 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 message.mybatis.common.mapper; import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator; import org.apache.ibatis.executor.keygen.KeyGenerator; import org.apache.ibatis.executor.keygen.NoKeyGenerator; import org.apache.ibatis.executor.keygen.SelectKeyGenerator; import org.apache.ibatis.mapping.*; import org.apache.ibatis.reflection.MetaObject; import org.apache.ibatis.reflection.SystemMetaObject; import org.apache.ibatis.scripting.defaults.RawSqlSource; import org.apache.ibatis.scripting.xmltags.*; import org.apache.ibatis.session.Configuration; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.text.MessageFormat; import java.util.*; /** * Mapper?Mapper?. * * @author sunhao(sunhao.java@gmail.com) * @version V1.0, 15/7/13 ?3:39 */ public abstract class MapperTemplate { private XMLLanguageDriver languageDriver = new XMLLanguageDriver(); private Map<String, Method> methodMap = new HashMap<String, Method>(); private Class<?> mapperClass; private MapperHelper mapperHelper; public MapperTemplate(Class<?> mapperClass, MapperHelper mapperHelper) { this.mapperClass = mapperClass; this.mapperHelper = mapperHelper; } public String dynamicSQL(Object record) { return "dynamicSQL"; } /** * * * @param methodName * @param method */ public void addMethodMap(String methodName, Method method) { methodMap.put(methodName, method); } public String getUUID() { return mapperHelper.getUUID(); } public String getIDENTITY() { return mapperHelper.getIDENTITY(); } public boolean getBEFORE() { return mapperHelper.getBEFORE(); } /** * ?? * * @param msId * @return */ public boolean supportMethod(String msId) { Class<?> mapperClass = getMapperClass(msId); if (mapperClass != null && this.mapperClass.isAssignableFrom(mapperClass)) { String methodName = getMethodName(msId); return methodMap.get(methodName) != null; } return false; } /** * * * @param ms * @param entityClass */ protected void setResultType(MappedStatement ms, Class<?> entityClass) { ResultMap resultMap = ms.getResultMaps().get(0); MetaObject metaObject = SystemMetaObject.forObject(resultMap); metaObject.setValue("type", entityClass); } /** * ?SqlSource?Jdbc3KeyGeneratorMultipleJdbc3KeyGenerator * * @param ms * @param sqlSource */ protected void setSqlSource(MappedStatement ms, SqlSource sqlSource) { MetaObject msObject = SystemMetaObject.forObject(ms); msObject.setValue("sqlSource", sqlSource); //Jdbc3KeyGeneratorMultipleJdbc3KeyGenerator KeyGenerator keyGenerator = ms.getKeyGenerator(); if (keyGenerator instanceof Jdbc3KeyGenerator) { msObject.setValue("keyGenerator", new MultipleJdbc3KeyGenerator()); } } /** * ?SqlSource * * @param ms * @throws InvocationTargetException * @throws IllegalAccessException */ public void setSqlSource(MappedStatement ms) throws Exception { if (this.mapperClass == getMapperClass(ms.getId())) { if (mapperHelper.isSpring4()) { return; } else if (mapperHelper.isSpring()) { throw new RuntimeException("Spring4.x.x ??," + "?Spring" + mapperHelper.getSpringVersion() + ",?," + "?MapperScannerConfigurer,????Mapper?," + "??Mybatisxml?<mappers>Mapper?."); } else { throw new RuntimeException( "??Mybatisxml?<mappers>Mapper?."); } } Method method = methodMap.get(getMethodName(ms)); try { if (method.getReturnType() == Void.TYPE) { method.invoke(this, ms); } else if (SqlNode.class.isAssignableFrom(method.getReturnType())) { SqlNode sqlNode = (SqlNode) method.invoke(this, ms); DynamicSqlSource dynamicSqlSource = new DynamicSqlSource(ms.getConfiguration(), sqlNode); setSqlSource(ms, dynamicSqlSource); } else if (String.class.equals(method.getReturnType())) { String xmlSql = (String) method.invoke(this, ms); SqlSource sqlSource = createSqlSource(ms, xmlSql); //?SqlSource setSqlSource(ms, sqlSource); } else { throw new RuntimeException( "Mapper,?void,SqlNode,String?!"); } } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (InvocationTargetException e) { throw new RuntimeException(e.getTargetException() != null ? e.getTargetException() : e); } } /** * ? - * * @param ms * @return */ public Class<?> getSelectReturnType(MappedStatement ms) { String msId = ms.getId(); Class<?> mapperClass = getMapperClass(msId); Type[] types = mapperClass.getGenericInterfaces(); for (Type type : types) { if (type instanceof ParameterizedType) { ParameterizedType t = (ParameterizedType) type; if (t.getRawType() == this.mapperClass || this.mapperClass.isAssignableFrom((Class<?>) t.getRawType())) { Class<?> returnType = (Class<?>) t.getActualTypeArguments()[0]; return returnType; } } } throw new RuntimeException("?Mapper<T>:" + msId); } /** * ?msId?? * * @param msId * @return * @throws ClassNotFoundException */ public static Class<?> getMapperClass(String msId) { if (msId.indexOf(".") == -1) { throw new RuntimeException( "?MappedStatementid=" + msId + ",??MappedStatement!"); } String mapperClassStr = msId.substring(0, msId.lastIndexOf(".")); try { return Class.forName(mapperClassStr); } catch (ClassNotFoundException e) { return null; } } /** * ??? * * @param ms * @return */ public static String getMethodName(MappedStatement ms) { return getMethodName(ms.getId()); } /** * ??? * * @param msId * @return */ public static String getMethodName(String msId) { return msId.substring(msId.lastIndexOf(".") + 1); } /** * ?? * * @param ms * @return */ protected List<ParameterMapping> getPrimaryKeyParameterMappings(MappedStatement ms) { Class<?> entityClass = getSelectReturnType(ms); Set<EntityHelper.EntityColumn> entityColumns = EntityHelper.getPKColumns(entityClass); List<ParameterMapping> parameterMappings = new LinkedList<ParameterMapping>(); for (EntityHelper.EntityColumn column : entityColumns) { ParameterMapping.Builder builder = new ParameterMapping.Builder(ms.getConfiguration(), column.getProperty(), column.getJavaType()); builder.mode(ParameterMode.IN); parameterMappings.add(builder.build()); } return parameterMappings; } /** * ??? * * @param column * @return */ protected String getSeqNextVal(EntityHelper.EntityColumn column) { return MessageFormat.format(mapperHelper.getSeqFormat(), column.getSequenceName(), column.getColumn(), column.getProperty()); } /** * ??? * * @param entityClass * @return */ protected String tableName(Class<?> entityClass) { return mapperHelper.getTableName(entityClass); } /** * if?sqlNode * <p><code><if test="property!=null">columnNode</if></code></p> * * @param column * @param columnNode * @return */ protected SqlNode getIfNotNull(EntityHelper.EntityColumn column, SqlNode columnNode) { return getIfNotNull(column, columnNode, false); } /** * if?sqlNode * <p><code><if test="property!=null">columnNode</if></code></p> * * @param column * @param columnNode * @param empty ??!=''? * @return */ protected SqlNode getIfNotNull(EntityHelper.EntityColumn column, SqlNode columnNode, boolean empty) { if (empty && column.getJavaType().equals(String.class)) { return new IfSqlNode(columnNode, column.getProperty() + " != null and " + column.getProperty() + " != ''"); } else { return new IfSqlNode(columnNode, column.getProperty() + " != null "); } } /** * if?sqlNode * <p><code><if test="property==null">columnNode</if></code></p> * * @param column * @return */ protected SqlNode getIfIsNull(EntityHelper.EntityColumn column, SqlNode columnNode) { return new IfSqlNode(columnNode, column.getProperty() + " == null "); } /** * if?sqlNode * <p><code><if test="property_cache!=null">columnNode</if></code></p> * * @param column * @return */ protected SqlNode getIfCacheIsNull(EntityHelper.EntityColumn column, SqlNode columnNode) { return new IfSqlNode(columnNode, column.getProperty() + "_cache == null "); } /** * ? <code>[AND] column = #{property}</code> * * @param column * @param first * @return */ protected SqlNode getColumnEqualsProperty(EntityHelper.EntityColumn column, boolean first) { return new StaticTextSqlNode( (first ? "" : " AND ") + column.getColumn() + " = #{" + column.getProperty() + "} "); } /** * ?whereif * * @param entityClass * @return */ protected SqlNode getAllIfColumnNode(Class<?> entityClass) { //? Set<EntityHelper.EntityColumn> columnList = EntityHelper.getColumns(entityClass); List<SqlNode> ifNodes = new LinkedList<SqlNode>(); boolean first = true; //?<if test="property!=null">column = #{property}</if> for (EntityHelper.EntityColumn column : columnList) { ifNodes.add(getIfNotNull(column, getColumnEqualsProperty(column, first), mapperHelper.isNotEmpty())); first = false; } return new MixedSqlNode(ifNodes); } /** * SelectKey - ?mysqlOracle? * * @param ms * @param column */ protected void newSelectKeyMappedStatement(MappedStatement ms, EntityHelper.EntityColumn column) { String keyId = ms.getId() + SelectKeyGenerator.SELECT_KEY_SUFFIX; if (ms.getConfiguration().hasKeyGenerator(keyId)) { return; } Class<?> entityClass = getSelectReturnType(ms); //defaults Configuration configuration = ms.getConfiguration(); KeyGenerator keyGenerator; Boolean executeBefore = getBEFORE(); String IDENTITY = (column.getGenerator() == null || column.getGenerator().equals("")) ? getIDENTITY() : column.getGenerator(); if (IDENTITY.equalsIgnoreCase("JDBC")) { keyGenerator = new Jdbc3KeyGenerator(); } else { SqlSource sqlSource = new RawSqlSource(configuration, IDENTITY, entityClass); MappedStatement.Builder statementBuilder = new MappedStatement.Builder(configuration, keyId, sqlSource, SqlCommandType.SELECT); statementBuilder.resource(ms.getResource()); statementBuilder.fetchSize(null); statementBuilder.statementType(StatementType.STATEMENT); statementBuilder.keyGenerator(new NoKeyGenerator()); statementBuilder.keyProperty(column.getProperty()); statementBuilder.keyColumn(null); statementBuilder.databaseId(null); statementBuilder.lang(configuration.getDefaultScriptingLanuageInstance()); statementBuilder.resultOrdered(false); statementBuilder.resulSets(null); statementBuilder.timeout(configuration.getDefaultStatementTimeout()); List<ParameterMapping> parameterMappings = new LinkedList<ParameterMapping>(); ParameterMap.Builder inlineParameterMapBuilder = new ParameterMap.Builder(configuration, statementBuilder.id() + "-Inline", entityClass, parameterMappings); statementBuilder.parameterMap(inlineParameterMapBuilder.build()); List<ResultMap> resultMaps = new LinkedList<ResultMap>(); ResultMap.Builder inlineResultMapBuilder = new ResultMap.Builder(configuration, statementBuilder.id() + "-Inline", column.getJavaType(), new LinkedList<ResultMapping>(), null); resultMaps.add(inlineResultMapBuilder.build()); statementBuilder.resultMaps(resultMaps); statementBuilder.resultSetType(null); statementBuilder.flushCacheRequired(false); statementBuilder.useCache(false); statementBuilder.cache(null); MappedStatement statement = statementBuilder.build(); try { configuration.addMappedStatement(statement); } catch (Exception e) { //ignore } MappedStatement keyStatement = configuration.getMappedStatement(keyId, false); keyGenerator = new SelectKeyGenerator(keyStatement, executeBefore); try { configuration.addKeyGenerator(keyId, keyGenerator); } catch (Exception e) { //ignore } } //keyGenerator try { MetaObject msObject = SystemMetaObject.forObject(ms); msObject.setValue("keyGenerator", keyGenerator); msObject.setValue("keyProperties", column.getTable().getKeyProperties()); msObject.setValue("keyColumns", column.getTable().getKeyColumns()); } catch (Exception e) { //ignore } } public SqlSource createSqlSource(MappedStatement ms, String xmlSql) { return languageDriver.createSqlSource(ms.getConfiguration(), "<script>\n\t" + xmlSql + "</script>", null); } }