signature:
public class SelectiveEnhancedPlugin { /** * upsertSelective xml
 * @ param element
 * @ param columns
 * @ param insertColumnsEle
 * @ param insertValuesEle
 * @ param setsEle
 * @ param introspectedTable
 * @ return */
@ Override public boolean sqlMapUpsertSelectiveElementGenerated ( XmlElement element , List < IntrospectedColumn > columns , XmlElement insertColumnsEle , XmlElement insertValuesEle , XmlElement setsEle , IntrospectedTable introspectedTable ) { } }

implementation:
// parameterType
XmlElementTools . replaceAttribute ( element , new Attribute ( "parameterType" , "map" ) ) ; // mybatis 3.5.0 之后对keyProperty处理有变更
element . getAttributes ( ) . removeIf ( attribute -> { String name = attribute . getName ( ) ; return name . equals ( "useGeneratedKeys" ) || name . equals ( "keyProperty" ) || name . equals ( "keyColumn" ) ; } ) ; XmlElementGeneratorTools . useGeneratedKeys ( element , introspectedTable , "record." ) ; // 替换insert column
XmlElementTools . replaceXmlElement ( insertColumnsEle , this . generateInsertColumnSelective ( columns ) ) ; // 替换insert values
XmlElementTools . replaceXmlElement ( insertValuesEle , this . generateInsertValuesSelective ( columns ) ) ; // 替换update set
XmlElementTools . replaceXmlElement ( setsEle , this . generateSetsSelective ( columns ) ) ; return true ;


signature:
public class SelectiveEnhancedPlugin { /** * upsertByExampleSelective xml
 * @ param element
 * @ param columns
 * @ param insertColumnsEle
 * @ param insertValuesEle
 * @ param setsEle
 * @ param introspectedTable
 * @ return */
@ Override public boolean sqlMapUpsertByExampleSelectiveElementGenerated ( XmlElement element , List < IntrospectedColumn > columns , XmlElement insertColumnsEle , XmlElement insertValuesEle , XmlElement setsEle , IntrospectedTable introspectedTable ) { } }

implementation:
// 替换insert column
XmlElementTools . replaceXmlElement ( insertColumnsEle , this . generateInsertColumnSelective ( columns ) ) ; // 替换insert values
XmlElementTools . replaceXmlElement ( insertValuesEle , this . generateInsertValuesSelective ( columns , false ) ) ; // 替换update set
XmlElementTools . replaceXmlElement ( setsEle , this . generateSetsSelective ( columns ) ) ; return true ;


signature:
public class SelectiveEnhancedPlugin { /** * = = = = = IOptimisticLockerPluginHook = = = = = */
@ Override public boolean clientUpdateWithVersionByExampleSelectiveMethodGenerated ( Method method , Interface interfaze , IntrospectedTable introspectedTable ) { } }

implementation:
// issue # 69 OptimisticLockerPlugin 插件updateWithVersionByExampleSelective方法的生成是基于updateByExampleSelective的 ,
// 这个方法在配置了SelectiveEnhancedPlugin时可能已经被先配置的SelectiveEnhancedPlugin改变了
if ( ! "selective" . equals ( method . getParameters ( ) . get ( method . getParameters ( ) . size ( ) - 1 ) . getName ( ) ) ) { // column枚举 , 找出全字段对应的Model
FullyQualifiedJavaType fullFieldModel = introspectedTable . getRules ( ) . calculateAllFieldsClass ( ) ; FullyQualifiedJavaType selectiveType = new FullyQualifiedJavaType ( fullFieldModel . getShortName ( ) + "." + ModelColumnPlugin . ENUM_NAME ) ; method . addParameter ( new Parameter ( selectiveType , "selective" , "@Param(\"selective\")" , true ) ) ; } return true ;


signature:
public class SelectiveEnhancedPlugin { /** * insert column selective
 * @ param columns
 * @ return */
private XmlElement generateInsertColumnSelective ( List < IntrospectedColumn > columns ) { } }

implementation: XmlElement insertColumnsChooseEle = new XmlElement ( "choose" ) ; XmlElement insertWhenEle = new XmlElement ( "when" ) ; insertWhenEle . addAttribute ( new Attribute ( "test" , "selective != null and selective.length > 0" ) ) ; insertColumnsChooseEle . addElement ( insertWhenEle ) ; XmlElement insertForeachEle = new XmlElement ( "foreach" ) ; insertForeachEle . addAttribute ( new Attribute ( "collection" , "selective" ) ) ; insertForeachEle . addAttribute ( new Attribute ( "item" , "column" ) ) ; insertForeachEle . addAttribute ( new Attribute ( "open" , "(" ) ) ; insertForeachEle . addAttribute ( new Attribute ( "separator" , "," ) ) ; insertForeachEle . addAttribute ( new Attribute ( "close" , ")" ) ) ; insertForeachEle . addElement ( new TextElement ( "${column.escapedColumnName}" ) ) ; insertWhenEle . addElement ( insertForeachEle ) ; XmlElement insertOtherwiseEle = new XmlElement ( "otherwise" ) ; insertOtherwiseEle . addElement ( XmlElementGeneratorTools . generateKeysSelective ( columns , "record." ) ) ; insertColumnsChooseEle . addElement ( insertOtherwiseEle ) ; XmlElement insertTrimElement = new XmlElement ( "trim" ) ; insertTrimElement . addAttribute ( new Attribute ( "prefix" , "(" ) ) ; insertTrimElement . addAttribute ( new Attribute ( "suffix" , ")" ) ) ; insertTrimElement . addAttribute ( new Attribute ( "suffixOverrides" , "," ) ) ; insertOtherwiseEle . addElement ( insertTrimElement ) ; return insertColumnsChooseEle ;


signature:
public class SelectiveEnhancedPlugin { /** * insert column selective
 * @ param columns
 * @ param bracket
 * @ return */
private XmlElement generateInsertValuesSelective ( List < IntrospectedColumn > columns , boolean bracket ) { } }

implementation: XmlElement insertValuesChooseEle = new XmlElement ( "choose" ) ; XmlElement valuesWhenEle = new XmlElement ( "when" ) ; valuesWhenEle . addAttribute ( new Attribute ( "test" , "selective != null and selective.length > 0" ) ) ; insertValuesChooseEle . addElement ( valuesWhenEle ) ; XmlElement valuesForeachEle = new XmlElement ( "foreach" ) ; valuesForeachEle . addAttribute ( new Attribute ( "collection" , "selective" ) ) ; valuesForeachEle . addAttribute ( new Attribute ( "item" , "column" ) ) ; valuesForeachEle . addAttribute ( new Attribute ( "separator" , "," ) ) ; if ( bracket ) { valuesForeachEle . addAttribute ( new Attribute ( "open" , "(" ) ) ; valuesForeachEle . addAttribute ( new Attribute ( "close" , ")" ) ) ; } valuesForeachEle . addElement ( new TextElement ( "#{record.${column.javaProperty},jdbcType=${column.jdbcType}}" ) ) ; valuesWhenEle . addElement ( valuesForeachEle ) ; XmlElement valuesOtherwiseEle = new XmlElement ( "otherwise" ) ; insertValuesChooseEle . addElement ( valuesOtherwiseEle ) ; valuesOtherwiseEle . addElement ( XmlElementGeneratorTools . generateValuesSelective ( columns , "record." , bracket ) ) ; return insertValuesChooseEle ;


signature:
public class SelectiveEnhancedPlugin { /** * sets selective
 * @ param columns
 * @ return */
private XmlElement generateSetsSelective ( List < IntrospectedColumn > columns , IntrospectedColumn versionColumn ) { } }

implementation:
XmlElement setsChooseEle = new XmlElement ( "choose" ) ; XmlElement setWhenEle = new XmlElement ( "when" ) ; setWhenEle . addAttribute ( new Attribute ( "test" , "selective != null and selective.length > 0" ) ) ; setsChooseEle . addElement ( setWhenEle ) ; XmlElement setForeachEle = new XmlElement ( "foreach" ) ; setWhenEle . addElement ( setForeachEle ) ; setForeachEle . addAttribute ( new Attribute ( "collection" , "selective" ) ) ; setForeachEle . addAttribute ( new Attribute ( "item" , "column" ) ) ; setForeachEle . addAttribute ( new Attribute ( "separator" , "," ) ) ; Element incrementEle = PluginTools . getHook ( IIncrementsPluginHook . class ) . incrementSetsWithSelectiveEnhancedPluginElementGenerated ( versionColumn ) ; // 普通情况
if ( incrementEle == null && versionColumn == null ) { setForeachEle . addElement ( new TextElement ( "${column.escapedColumnName} = #{record.${column.javaProperty},jdbcType=${column.jdbcType}}" ) ) ; } else if ( incrementEle != null ) { setForeachEle . addElement ( incrementEle ) ; } else if ( versionColumn != null ) { XmlElement ifEle = new XmlElement ( "if" ) ; ifEle . addAttribute ( new Attribute ( "test" , "column.value != '" + versionColumn . getActualColumnName ( ) + "'.toString()" ) ) ; ifEle . addElement ( new TextElement ( "${column.escapedColumnName} = #{record.${column.javaProperty},jdbcType=${column.jdbcType}}" ) ) ; setForeachEle . addElement ( ifEle ) ; } XmlElement setOtherwiseEle = new XmlElement ( "otherwise" ) ; setOtherwiseEle . addElement ( XmlElementGeneratorTools . generateSetsSelective ( columns , "record." ) ) ; setsChooseEle . addElement ( setOtherwiseEle ) ; return setsChooseEle ;


signature:
public class LogicalDeletePlugin { /** * 初始化阶段
 * 具体执行顺序 http : / / www . mybatis . org / generator / reference / pluggingIn . html
 * @ param introspectedTable
 * @ return */
@ Override public void initialized ( IntrospectedTable introspectedTable ) { } }

implementation:
super . initialized ( introspectedTable ) ; this . logicalUnDeleteEnumIndex = 0 ; this . logicalDeleteEnumIndex = 1 ; // 1 . 获取配置的逻辑删除列
Properties properties = getProperties ( ) ; String logicalDeleteColumn = properties . getProperty ( PRO_LOGICAL_DELETE_COLUMN ) ; if ( introspectedTable . getTableConfigurationProperty ( PRO_LOGICAL_DELETE_COLUMN ) != null ) { logicalDeleteColumn = introspectedTable . getTableConfigurationProperty ( PRO_LOGICAL_DELETE_COLUMN ) ; } this . logicalDeleteColumn = IntrospectedTableTools . safeGetColumn ( introspectedTable , logicalDeleteColumn ) ; // 判断如果表单独配置了逻辑删除列 , 但是却没有找到对应列进行提示
if ( introspectedTable . getTableConfigurationProperty ( PRO_LOGICAL_DELETE_COLUMN ) != null && this . logicalDeleteColumn == null ) { warnings . add ( "itfsw(逻辑删除插件):" + introspectedTable . getFullyQualifiedTable ( ) + "没有找到您配置的逻辑删除列(" + introspectedTable . getTableConfigurationProperty ( PRO_LOGICAL_DELETE_COLUMN ) + ")！" ) ; } // 2 . 获取逻辑删除常量值
this . enableLogicalDeleteConst = properties . getProperty ( PRO_ENABLE_LOGICAL_DELETE_CONST ) == null ? true : StringUtility . isTrue ( properties . getProperty ( PRO_ENABLE_LOGICAL_DELETE_CONST ) ) ; if ( this . enableLogicalDeleteConst ) { if ( properties . getProperty ( PRO_LOGICAL_DELETE_CONST_NAME ) != null ) { this . logicalDeleteConstName = properties . getProperty ( PRO_LOGICAL_DELETE_CONST_NAME ) . toUpperCase ( ) ; } if ( properties . getProperty ( PRO_LOGICAL_UN_DELETE_CONST_NAME ) != null ) { this . logicalUnDeleteConstName = properties . getProperty ( PRO_LOGICAL_UN_DELETE_CONST_NAME ) . toUpperCase ( ) ; } } // 3 . 判断逻辑删除值是否配置了
this . logicalDeleteValue = properties . getProperty ( PRO_LOGICAL_DELETE_VALUE ) ; this . logicalUnDeleteValue = properties . getProperty ( PRO_LOGICAL_UN_DELETE_VALUE ) ; if ( introspectedTable . getTableConfigurationProperty ( PRO_LOGICAL_DELETE_VALUE ) != null ) { this . logicalDeleteValue = introspectedTable . getTableConfigurationProperty ( PRO_LOGICAL_DELETE_VALUE ) ; } if ( introspectedTable . getTableConfigurationProperty ( PRO_LOGICAL_UN_DELETE_VALUE ) != null ) { this . logicalUnDeleteValue = introspectedTable . getTableConfigurationProperty ( PRO_LOGICAL_UN_DELETE_VALUE ) ; } if ( this . logicalDeleteValue == null || this . logicalUnDeleteValue == null ) { this . logicalDeleteColumn = null ; warnings . add ( "itfsw(逻辑删除插件):" + introspectedTable . getFullyQualifiedTable ( ) + "没有找到您配置的逻辑删除值，请全局或者局部配置logicalDeleteValue和logicalUnDeleteValue值！" ) ; } // 4 . 优先借助 EnumTypeStatusPlugin 插件 , 去注解里面解析枚举
if ( this . logicalDeleteColumn != null ) { EnumTypeStatusPlugin . EnumInfo enumInfo = null ; try { enumInfo = new EnumTypeStatusPlugin . EnumInfo ( this . logicalDeleteColumn ) ; // 解析注释
enumInfo . parseRemarks ( this . logicalDeleteColumn . getRemarks ( ) ) ; } catch ( EnumTypeStatusPlugin . EnumInfo . NotSupportTypeException e ) { this . logicalDeleteColumn = null ; warnings . add ( "itfsw(逻辑删除插件):" + introspectedTable . getFullyQualifiedTable ( ) + "逻辑删除列(" + introspectedTable . getTableConfigurationProperty ( PRO_LOGICAL_DELETE_COLUMN ) + ")的类型不在支持范围（请使用数字列，字符串列，布尔列）！" ) ; } catch ( EnumTypeStatusPlugin . EnumInfo . CannotParseException e ) { // 这个异常不管 , 没有配置是正常的
} finally { if ( enumInfo != null ) { // 这个是注释里配置了枚举
if ( enumInfo . hasItems ( ) ) { if ( enumInfo . getItems ( ) . size ( ) < 2 ) { this . logicalDeleteColumn = null ; warnings . add ( "itfsw(逻辑删除插件):" + introspectedTable . getFullyQualifiedTable ( ) + "在配合EnumTypeStatusPlugin插件使用时，枚举数量必须大于等于2！" ) ; } else { this . logicalDeleteEnumIndex = - 1 ; this . logicalUnDeleteEnumIndex = - 1 ; for ( int i = 0 ; i < enumInfo . getItems ( ) . size ( ) ; i ++ ) { EnumTypeStatusPlugin . EnumInfo . EnumItemInfo enumItemInfo = enumInfo . getItems ( ) . get ( i ) ; if ( this . logicalDeleteValue . equals ( enumItemInfo . getOriginalValue ( ) ) ) { this . logicalDeleteEnumIndex = i ; } else if ( this . logicalUnDeleteValue . equals ( enumItemInfo . getOriginalValue ( ) ) ) { this . logicalUnDeleteEnumIndex = i ; } } if ( this . logicalDeleteEnumIndex == - 1 ) { this . logicalDeleteColumn = null ; warnings . add ( "itfsw(逻辑删除插件):" + introspectedTable . getFullyQualifiedTable ( ) + "在配合EnumTypeStatusPlugin插件使用时，逻辑删除值“" + this . logicalDeleteValue + "”未在枚举中找到！" ) ; } else if ( this . logicalDeleteEnumIndex == - 1 ) { this . logicalDeleteColumn = null ; warnings . add ( "itfsw(逻辑删除插件):" + introspectedTable . getFullyQualifiedTable ( ) + "在配合EnumTypeStatusPlugin插件使用时，逻辑未删除值“" + this . logicalUnDeleteValue + "”未在枚举中找到！" ) ; } else { this . logicalDeleteEnum = enumInfo . generateEnum ( commentGenerator , introspectedTable ) ; } } } else { // 兼容处理以前一些老用户配置的Long 和 Float配置问题
if ( this . logicalDeleteColumn . getFullyQualifiedJavaType ( ) . getFullyQualifiedName ( ) . equals ( Long . class . getName ( ) ) ) { this . logicalUnDeleteValue = this . logicalUnDeleteValue . replaceAll ( "L|l" , "" ) ; this . logicalDeleteValue = this . logicalDeleteValue . replaceAll ( "L|l" , "" ) ; } else if ( this . logicalDeleteColumn . getFullyQualifiedJavaType ( ) . getFullyQualifiedName ( ) . equals ( Float . class . getName ( ) ) ) { this . logicalUnDeleteValue = this . logicalUnDeleteValue . replaceAll ( "F|f" , "" ) ; this . logicalDeleteValue = this . logicalDeleteValue . replaceAll ( "F|f" , "" ) ; } enumInfo . addItem ( this . logicalUnDeleteConstName , "未删除" , this . logicalUnDeleteValue ) ; enumInfo . addItem ( this . logicalDeleteConstName , "已删除" , this . logicalDeleteValue ) ; this . logicalDeleteEnum = enumInfo . generateEnum ( commentGenerator , introspectedTable ) ; } } } } // 5 . 防止增强的selectByPrimaryKey中逻辑删除键冲突
if ( this . logicalDeleteColumn != null ) { Field logicalDeleteField = JavaBeansUtil . getJavaBeansField ( this . logicalDeleteColumn , context , introspectedTable ) ; if ( logicalDeleteField . getName ( ) . equals ( PARAMETER_LOGICAL_DELETED ) ) { this . logicalDeleteColumn = null ; warnings . add ( "itfsw(逻辑删除插件):" + introspectedTable . getFullyQualifiedTable ( ) + "配置的逻辑删除列和插件保留关键字(" + PARAMETER_LOGICAL_DELETED + ")冲突！" ) ; } }


signature:
public class LogicalDeletePlugin { /** * Java Client Methods 生成
 * 具体执行顺序 http : / / www . mybatis . org / generator / reference / pluggingIn . html
 * @ param interfaze
 * @ param topLevelClass
 * @ param introspectedTable
 * @ return */
@ Override public boolean clientGenerated ( Interface interfaze , TopLevelClass topLevelClass , IntrospectedTable introspectedTable ) { } }

implementation:
if ( this . logicalDeleteColumn != null ) { // 1 . 逻辑删除ByExample
Method mLogicalDeleteByExample = JavaElementGeneratorTools . generateMethod ( METHOD_LOGICAL_DELETE_BY_EXAMPLE , JavaVisibility . DEFAULT , FullyQualifiedJavaType . getIntInstance ( ) , new Parameter ( new FullyQualifiedJavaType ( introspectedTable . getExampleType ( ) ) , "example" , "@Param(\"example\")" ) ) ; // 添加方法说明
commentGenerator . addGeneralMethodComment ( mLogicalDeleteByExample , introspectedTable ) ; // interface 增加方法
FormatTools . addMethodWithBestPosition ( interfaze , mLogicalDeleteByExample ) ; logger . debug ( "itfsw(逻辑删除插件):" + interfaze . getType ( ) . getShortName ( ) + "增加方法logicalDeleteByExample。" ) ; // hook
PluginTools . getHook ( ILogicalDeletePluginHook . class ) . clientLogicalDeleteByExampleMethodGenerated ( mLogicalDeleteByExample , interfaze , introspectedTable ) ; // 2 . 判断是否有主键 , 生成主键删除方法
if ( introspectedTable . hasPrimaryKeyColumns ( ) ) { // 2.1 . 逻辑删除ByExample
Method mLogicalDeleteByPrimaryKey = JavaElementGeneratorTools . generateMethod ( METHOD_LOGICAL_DELETE_BY_PRIMARY_KEY , JavaVisibility . DEFAULT , FullyQualifiedJavaType . getIntInstance ( ) ) ; commentGenerator . addGeneralMethodComment ( mLogicalDeleteByPrimaryKey , introspectedTable ) ; // 2.2 增强selectByPrimaryKey
Method mSelectByPrimaryKey = JavaElementGeneratorTools . generateMethod ( METHOD_SELECT_BY_PRIMARY_KEY_WITH_LOGICAL_DELETE , JavaVisibility . DEFAULT , introspectedTable . getRules ( ) . calculateAllFieldsClass ( ) ) ; // 添加参数
Set < FullyQualifiedJavaType > importedTypes = new TreeSet < > ( ) ; importedTypes . add ( new FullyQualifiedJavaType ( "org.apache.ibatis.annotations.Param" ) ) ; if ( introspectedTable . getRules ( ) . generatePrimaryKeyClass ( ) ) { FullyQualifiedJavaType type1 = new FullyQualifiedJavaType ( introspectedTable . getPrimaryKeyType ( ) ) ; importedTypes . add ( type1 ) ; mLogicalDeleteByPrimaryKey . addParameter ( new Parameter ( type1 , "key" ) ) ; mSelectByPrimaryKey . addParameter ( new Parameter ( type1 , "key" , "@Param(\"key\")" ) ) ; } else { // no primary key class - fields are in the base class
// if more than one PK field , then we need to annotate the
// parameters
// for MyBatis
List < IntrospectedColumn > introspectedColumns = introspectedTable . getPrimaryKeyColumns ( ) ; boolean annotate = introspectedColumns . size ( ) > 1 ; StringBuilder sb = new StringBuilder ( ) ; for ( IntrospectedColumn introspectedColumn : introspectedColumns ) { FullyQualifiedJavaType type1 = introspectedColumn . getFullyQualifiedJavaType ( ) ; importedTypes . add ( type1 ) ; Parameter parameter = new Parameter ( type1 , introspectedColumn . getJavaProperty ( ) ) ; if ( annotate ) { sb . setLength ( 0 ) ; sb . append ( "@Param(\"" ) ; sb . append ( introspectedColumn . getJavaProperty ( ) ) ; sb . append ( "\")" ) ; parameter . addAnnotation ( sb . toString ( ) ) ; } mLogicalDeleteByPrimaryKey . addParameter ( parameter ) ; Parameter parameter1 = new Parameter ( type1 , introspectedColumn . getJavaProperty ( ) ) ; sb . setLength ( 0 ) ; sb . append ( "@Param(\"" ) ; sb . append ( introspectedColumn . getJavaProperty ( ) ) ; sb . append ( "\")" ) ; parameter1 . addAnnotation ( sb . toString ( ) ) ; mSelectByPrimaryKey . addParameter ( parameter1 ) ; } } // interface 增加方法
interfaze . addImportedTypes ( importedTypes ) ; FormatTools . addMethodWithBestPosition ( interfaze , mLogicalDeleteByPrimaryKey ) ; logger . debug ( "itfsw(逻辑删除插件):" + interfaze . getType ( ) . getShortName ( ) + "增加方法logicalDeleteByPrimaryKey。" ) ; // hook
PluginTools . getHook ( ILogicalDeletePluginHook . class ) . clientLogicalDeleteByPrimaryKeyMethodGenerated ( mLogicalDeleteByPrimaryKey , interfaze , introspectedTable ) ; // 增强selectByPrimaryKey
mSelectByPrimaryKey . addParameter ( new Parameter ( FullyQualifiedJavaType . getBooleanPrimitiveInstance ( ) , PARAMETER_LOGICAL_DELETED , "@Param(\"" + PARAMETER_LOGICAL_DELETED + "\")" ) ) ; commentGenerator . addGeneralMethodComment ( mSelectByPrimaryKey , introspectedTable ) ; FormatTools . addMethodWithBestPosition ( interfaze , mSelectByPrimaryKey ) ; } } return true ;


signature:
public class LogicalDeletePlugin { /** * SQL Map Methods 生成
 * 具体执行顺序 http : / / www . mybatis . org / generator / reference / pluggingIn . html
 * @ param document
 * @ param introspectedTable
 * @ return */
@ Override public boolean sqlMapDocumentGenerated ( Document document , IntrospectedTable introspectedTable ) { } }

implementation:
if ( this . logicalDeleteColumn != null ) { // 1 . 逻辑删除ByExample
XmlElement logicalDeleteByExample = new XmlElement ( "update" ) ; logicalDeleteByExample . addAttribute ( new Attribute ( "id" , METHOD_LOGICAL_DELETE_BY_EXAMPLE ) ) ; logicalDeleteByExample . addAttribute ( new Attribute ( "parameterType" , "map" ) ) ; commentGenerator . addComment ( logicalDeleteByExample ) ; StringBuilder sb = new StringBuilder ( ) ; sb . append ( "update " ) ; sb . append ( introspectedTable . getAliasedFullyQualifiedTableNameAtRuntime ( ) ) ; sb . append ( " set " ) ; // 更新逻辑删除字段
sb . append ( this . logicalDeleteColumn . getActualColumnName ( ) ) ; sb . append ( " = " ) ; sb . append ( XmlElementGeneratorTools . generateLogicalDeleteColumnValue ( this . logicalDeleteColumn , this . logicalDeleteValue ) ) ; logicalDeleteByExample . addElement ( new TextElement ( sb . toString ( ) ) ) ; logicalDeleteByExample . addElement ( XmlElementGeneratorTools . getUpdateByExampleIncludeElement ( introspectedTable ) ) ; document . getRootElement ( ) . addElement ( logicalDeleteByExample ) ; logger . debug ( "itfsw(逻辑删除插件):" + introspectedTable . getMyBatis3XmlMapperFileName ( ) + "增加方法logicalDeleteByExample的实现。" ) ; // hook
PluginTools . getHook ( ILogicalDeletePluginHook . class ) . sqlMapLogicalDeleteByExampleElementGenerated ( document , logicalDeleteByExample , this . logicalDeleteColumn , this . logicalDeleteValue , introspectedTable ) ; // 2 . 判断是否有主键 , 生成主键删除方法
if ( introspectedTable . hasPrimaryKeyColumns ( ) ) { XmlElement logicalDeleteByPrimaryKey = new XmlElement ( "update" ) ; logicalDeleteByPrimaryKey . addAttribute ( new Attribute ( "id" , METHOD_LOGICAL_DELETE_BY_PRIMARY_KEY ) ) ; String parameterClass ; if ( introspectedTable . getRules ( ) . generatePrimaryKeyClass ( ) ) { parameterClass = introspectedTable . getPrimaryKeyType ( ) ; } else { // PK fields are in the base class . If more than on PK
// field , then they are coming in a map .
if ( introspectedTable . getPrimaryKeyColumns ( ) . size ( ) > 1 ) { parameterClass = "map" ; } else { parameterClass = introspectedTable . getPrimaryKeyColumns ( ) . get ( 0 ) . getFullyQualifiedJavaType ( ) . toString ( ) ; } } logicalDeleteByPrimaryKey . addAttribute ( new Attribute ( "parameterType" , parameterClass ) ) ; commentGenerator . addComment ( logicalDeleteByPrimaryKey ) ; StringBuilder sb1 = new StringBuilder ( ) ; sb1 . append ( "update " ) ; sb1 . append ( introspectedTable . getAliasedFullyQualifiedTableNameAtRuntime ( ) ) ; sb1 . append ( " set " ) ; // 更新逻辑删除字段
sb1 . append ( this . logicalDeleteColumn . getActualColumnName ( ) ) ; sb1 . append ( " = " ) ; sb1 . append ( XmlElementGeneratorTools . generateLogicalDeleteColumnValue ( this . logicalDeleteColumn , this . logicalDeleteValue ) ) ; logicalDeleteByPrimaryKey . addElement ( new TextElement ( sb1 . toString ( ) ) ) ; XmlElementGeneratorTools . generateWhereByPrimaryKeyTo ( logicalDeleteByPrimaryKey , introspectedTable . getPrimaryKeyColumns ( ) ) ; document . getRootElement ( ) . addElement ( logicalDeleteByPrimaryKey ) ; logger . debug ( "itfsw(逻辑删除插件):" + introspectedTable . getMyBatis3XmlMapperFileName ( ) + "增加方法logicalDeleteByPrimaryKey的实现。" ) ; // hook
PluginTools . getHook ( ILogicalDeletePluginHook . class ) . sqlMapLogicalDeleteByPrimaryKeyElementGenerated ( document , logicalDeleteByPrimaryKey , this . logicalDeleteColumn , this . logicalDeleteValue , introspectedTable ) ; // 3 . 增强selectByPrimaryKey
XmlElement selectByPrimaryKey = new XmlElement ( "select" ) ; commentGenerator . addComment ( selectByPrimaryKey ) ; selectByPrimaryKey . addAttribute ( new Attribute ( "id" , METHOD_SELECT_BY_PRIMARY_KEY_WITH_LOGICAL_DELETE ) ) ; if ( introspectedTable . getRules ( ) . generateResultMapWithBLOBs ( ) ) { selectByPrimaryKey . addAttribute ( new Attribute ( "resultMap" , introspectedTable . getResultMapWithBLOBsId ( ) ) ) ; } else { selectByPrimaryKey . addAttribute ( new Attribute ( "resultMap" , introspectedTable . getBaseResultMapId ( ) ) ) ; } selectByPrimaryKey . addAttribute ( new Attribute ( "parameterType" , "map" ) ) ; sb = new StringBuilder ( ) ; sb . append ( "select " ) ; if ( stringHasValue ( introspectedTable . getSelectByPrimaryKeyQueryId ( ) ) ) { sb . append ( '\'' ) ; sb . append ( introspectedTable . getSelectByPrimaryKeyQueryId ( ) ) ; sb . append ( "' as QUERYID," ) ; } selectByPrimaryKey . addElement ( new TextElement ( sb . toString ( ) ) ) ; selectByPrimaryKey . addElement ( XmlElementGeneratorTools . getBaseColumnListElement ( introspectedTable ) ) ; if ( introspectedTable . hasBLOBColumns ( ) ) { selectByPrimaryKey . addElement ( new TextElement ( "," ) ) ; selectByPrimaryKey . addElement ( XmlElementGeneratorTools . getBlobColumnListElement ( introspectedTable ) ) ; } sb . setLength ( 0 ) ; sb . append ( "from " ) ; sb . append ( introspectedTable . getAliasedFullyQualifiedTableNameAtRuntime ( ) ) ; selectByPrimaryKey . addElement ( new TextElement ( sb . toString ( ) ) ) ; XmlElementGeneratorTools . generateWhereByPrimaryKeyTo ( selectByPrimaryKey , introspectedTable . getPrimaryKeyColumns ( ) ) ; // 逻辑删除的判断
sb . setLength ( 0 ) ; sb . append ( "  and " ) ; sb . append ( MyBatis3FormattingUtilities . getAliasedEscapedColumnName ( this . logicalDeleteColumn ) ) ; sb . append ( " = " ) ; selectByPrimaryKey . addElement ( new TextElement ( sb . toString ( ) ) ) ; XmlElement chooseEle = new XmlElement ( "choose" ) ; XmlElement whenEle = new XmlElement ( "when" ) ; whenEle . addAttribute ( new Attribute ( "test" , PARAMETER_LOGICAL_DELETED ) ) ; whenEle . addElement ( new TextElement ( XmlElementGeneratorTools . generateLogicalDeleteColumnValue ( this . logicalDeleteColumn , this . logicalDeleteValue ) ) ) ; chooseEle . addElement ( whenEle ) ; XmlElement otherwiseEle = new XmlElement ( "otherwise" ) ; otherwiseEle . addElement ( new TextElement ( XmlElementGeneratorTools . generateLogicalDeleteColumnValue ( this . logicalDeleteColumn , this . logicalUnDeleteValue ) ) ) ; chooseEle . addElement ( otherwiseEle ) ; selectByPrimaryKey . addElement ( chooseEle ) ; FormatTools . addElementWithBestPosition ( document . getRootElement ( ) , selectByPrimaryKey ) ; } } return true ;


signature:
public class LogicalDeletePlugin { /** * 具体执行顺序 http : / / www . mybatis . org / generator / reference / pluggingIn . html
 * @ param field
 * @ param topLevelClass
 * @ param introspectedColumn
 * @ param introspectedTable
 * @ param modelClassType
 * @ return */
@ Override public boolean modelFieldGenerated ( Field field , TopLevelClass topLevelClass , IntrospectedColumn introspectedColumn , IntrospectedTable introspectedTable , ModelClassType modelClassType ) { } }

implementation:
if ( this . logicalDeleteColumn != null ) { // 常量 、 枚举和逻辑删除方法跟随 逻辑删除列走
if ( this . logicalDeleteColumn . getJavaProperty ( ) . equals ( field . getName ( ) ) ) { // 1 . 添加枚举
if ( PluginTools . getHook ( ILogicalDeletePluginHook . class ) . logicalDeleteEnumGenerated ( this . logicalDeleteColumn ) == false ) { topLevelClass . addInnerEnum ( this . logicalDeleteEnum ) ; } // 2 . andLogicalDeleted 方法
Method mAndLogicalDeleted = JavaElementGeneratorTools . generateMethod ( METHOD_LOGICAL_DELETED , JavaVisibility . PUBLIC , null , new Parameter ( FullyQualifiedJavaType . getBooleanPrimitiveInstance ( ) , "deleted" ) ) ; commentGenerator . addGeneralMethodComment ( mAndLogicalDeleted , introspectedTable ) ; Method logicalDeleteSetter = JavaBeansUtil . getJavaBeansSetter ( this . logicalDeleteColumn , context , introspectedTable ) ; mAndLogicalDeleted . addBodyLine ( logicalDeleteSetter . getName ( ) + "(deleted ? " + this . getEnumConstantValue ( true ) + " : " + this . getEnumConstantValue ( false ) + ");" ) ; FormatTools . addMethodWithBestPosition ( topLevelClass , mAndLogicalDeleted ) ; // 3 . 添加逻辑删除常量
if ( this . enableLogicalDeleteConst ) { Field logicalUnDeleteConstField = JavaElementGeneratorTools . generateStaticFinalField ( this . logicalUnDeleteConstName , this . logicalDeleteColumn . getFullyQualifiedJavaType ( ) , this . getEnumConstantValue ( false ) ) ; commentGenerator . addFieldComment ( logicalUnDeleteConstField , introspectedTable ) ; Field logicalDeleteConstField = JavaElementGeneratorTools . generateStaticFinalField ( this . logicalDeleteConstName , this . logicalDeleteColumn . getFullyQualifiedJavaType ( ) , this . getEnumConstantValue ( true ) ) ; commentGenerator . addFieldComment ( logicalDeleteConstField , introspectedTable ) ; // 常量放在字段开头
ArrayList < Field > fields = ( ArrayList < Field > ) topLevelClass . getFields ( ) ; fields . add ( 0 , logicalUnDeleteConstField ) ; fields . add ( 0 , logicalDeleteConstField ) ; } } } return super . modelFieldGenerated ( field , topLevelClass , introspectedColumn , introspectedTable , modelClassType ) ;


signature:
public class LogicalDeletePlugin { /** * ModelExample Methods 生成
 * 具体执行顺序 http : / / www . mybatis . org / generator / reference / pluggingIn . html
 * @ param topLevelClass
 * @ param introspectedTable
 * @ return */
@ Override public boolean modelExampleClassGenerated ( TopLevelClass topLevelClass , IntrospectedTable introspectedTable ) { } }

implementation:
if ( this . logicalDeleteColumn != null ) { // 引入 Model类
topLevelClass . addImportedType ( this . getColumnInModelType ( ) ) ; List < InnerClass > innerClasses = topLevelClass . getInnerClasses ( ) ; for ( InnerClass innerClass : innerClasses ) { if ( "Criteria" . equals ( innerClass . getType ( ) . getShortName ( ) ) ) { // 增加逻辑删除条件
Method method = new Method ( METHOD_LOGICAL_DELETED ) ; commentGenerator . addGeneralMethodComment ( method , introspectedTable ) ; method . setVisibility ( JavaVisibility . PUBLIC ) ; method . setReturnType ( innerClass . getType ( ) ) ; method . addParameter ( new Parameter ( FullyQualifiedJavaType . getBooleanPrimitiveInstance ( ) , "deleted" ) ) ; StringBuffer sb = new StringBuffer ( ) ; sb . append ( "return deleted ? " ) ; String modelName = this . getColumnInModelType ( ) . getShortName ( ) ; // 调用EqualTo方法
StringBuilder equalToMethodName = new StringBuilder ( ) ; equalToMethodName . append ( this . logicalDeleteColumn . getJavaProperty ( ) ) ; equalToMethodName . setCharAt ( 0 , Character . toUpperCase ( equalToMethodName . charAt ( 0 ) ) ) ; equalToMethodName . insert ( 0 , "and" ) ; equalToMethodName . append ( "EqualTo" ) ; sb . append ( equalToMethodName ) ; sb . append ( "(" + modelName + "." + this . getEnumConstantValue ( true ) + ")" ) ; sb . append ( " : " ) ; // 调用NotEqualTo 方法
StringBuilder notEqualToMethodName = new StringBuilder ( ) ; notEqualToMethodName . append ( this . logicalDeleteColumn . getJavaProperty ( ) ) ; notEqualToMethodName . setCharAt ( 0 , Character . toUpperCase ( notEqualToMethodName . charAt ( 0 ) ) ) ; notEqualToMethodName . insert ( 0 , "and" ) ; notEqualToMethodName . append ( "NotEqualTo" ) ; sb . append ( notEqualToMethodName ) ; sb . append ( "(" + modelName + "." + this . getEnumConstantValue ( true ) + ")" ) ; sb . append ( ";" ) ; method . addBodyLine ( sb . toString ( ) ) ; FormatTools . addMethodWithBestPosition ( innerClass , method ) ; } } } return super . modelExampleClassGenerated ( topLevelClass , introspectedTable ) ;


signature:
public class LogicalDeletePlugin { /** * 获取逻辑删除枚举
 * @ param delete
 * @ return */
private String getEnumConstantValue ( boolean delete ) { } }

implementation: if ( this . logicalDeleteEnum != null ) { String enumConstant = this . logicalDeleteEnum . getEnumConstants ( ) . get ( delete ? this . logicalDeleteEnumIndex : this . logicalUnDeleteEnumIndex ) ; enumConstant = enumConstant . split ( "\\(" ) [ 0 ] ; return this . logicalDeleteEnum . getType ( ) . getShortName ( ) + "." + enumConstant + ".value()" ; } return null ;


signature:
public class LogicalDeletePlugin { /** * 获取逻辑删除列所在model ( modelExampleClassGenerated执行顺序在前面 ! ! ! ! ! 和官网上不一样 , 没办法只有自己去找 )
 * @ return */
private FullyQualifiedJavaType getColumnInModelType ( ) { } }

implementation:
if ( this . logicalDeleteColumn != null ) { IntrospectedTable introspectedTable = this . logicalDeleteColumn . getIntrospectedTable ( ) ; // primaryKey
for ( IntrospectedColumn column : introspectedTable . getPrimaryKeyColumns ( ) ) { if ( column . getActualColumnName ( ) . equals ( this . logicalDeleteColumn . getActualColumnName ( ) ) ) { if ( introspectedTable . getRules ( ) . generatePrimaryKeyClass ( ) ) { return new FullyQualifiedJavaType ( introspectedTable . getPrimaryKeyType ( ) ) ; } else { return new FullyQualifiedJavaType ( introspectedTable . getBaseRecordType ( ) ) ; } } } // base record
for ( IntrospectedColumn column : introspectedTable . getBaseColumns ( ) ) { if ( column . getActualColumnName ( ) . equals ( this . logicalDeleteColumn . getActualColumnName ( ) ) ) { if ( introspectedTable . getRules ( ) . generateBaseRecordClass ( ) ) { return new FullyQualifiedJavaType ( introspectedTable . getBaseRecordType ( ) ) ; } } } // blob record
for ( IntrospectedColumn column : introspectedTable . getBLOBColumns ( ) ) { if ( column . getActualColumnName ( ) . equals ( this . logicalDeleteColumn . getActualColumnName ( ) ) ) { if ( introspectedTable . getRules ( ) . generateRecordWithBLOBsClass ( ) ) { return new FullyQualifiedJavaType ( introspectedTable . getRecordWithBLOBsType ( ) ) ; } else { return new FullyQualifiedJavaType ( introspectedTable . getBaseRecordType ( ) ) ; } } } } return null ;


signature:
public class OptimisticLockerPlugin { /** * 使用用户自定义nextVersion */
@ Override public void initialized ( IntrospectedTable introspectedTable ) { } }

implementation:
super . initialized ( introspectedTable ) ; sqlMaps . put ( introspectedTable , new ArrayList < > ( ) ) ; // 读取并验证版本列
String versionColumn = introspectedTable . getTableConfigurationProperty ( PRO_VERSION_COLUMN ) ; if ( versionColumn != null ) { this . versionColumn = introspectedTable . getColumn ( versionColumn ) ; if ( this . versionColumn == null ) { warnings . add ( "itfsw(乐观锁插件):表" + introspectedTable . getFullyQualifiedTable ( ) + "配置的版本列(" + introspectedTable . getTableConfigurationProperty ( PRO_VERSION_COLUMN ) + ")没有找到！" ) ; } } else { this . versionColumn = null ; } // 自定义nextVersion
// 首先获取全局配置
Properties properties = getProperties ( ) ; String customizedNextVersion = properties . getProperty ( PRO_CUSTOMIZED_NEXT_VERSION ) ; // 获取表单独配置 , 如果有则覆盖全局配置
if ( introspectedTable . getTableConfigurationProperty ( PRO_CUSTOMIZED_NEXT_VERSION ) != null ) { customizedNextVersion = introspectedTable . getTableConfigurationProperty ( PRO_CUSTOMIZED_NEXT_VERSION ) ; } if ( StringUtility . stringHasValue ( customizedNextVersion ) && StringUtility . isTrue ( customizedNextVersion ) ) { this . customizedNextVersion = true ; } else { this . customizedNextVersion = false ; } super . initialized ( introspectedTable ) ;


signature:
public class OptimisticLockerPlugin { /** * = = = = = method 生成 = = = = = */
@ Override public boolean clientDeleteByExampleMethodGenerated ( Method method , Interface interfaze , IntrospectedTable introspectedTable ) { } }

implementation: if ( this . versionColumn != null ) { FormatTools . addMethodWithBestPosition ( interfaze , this . replaceDeleteExampleMethod ( introspectedTable , method , interfaze , METHOD_DELETE_WITH_VERSION_BY_EXAMPLE ) ) ; } return super . clientDeleteByExampleMethodGenerated ( method , interfaze , introspectedTable ) ;


signature:
public class OptimisticLockerPlugin { /** * = = = = = model 生成 = = = = = */
@ Override public boolean modelSetterMethodGenerated ( Method method , TopLevelClass topLevelClass , IntrospectedColumn introspectedColumn , IntrospectedTable introspectedTable , ModelClassType modelClassType ) { } }

implementation:
if ( this . versionColumn != null && this . customizedNextVersion && introspectedColumn . getActualColumnName ( ) . equals ( this . versionColumn . getActualColumnName ( ) ) ) { // nextVersion 方法
Method nextVersion = JavaElementGeneratorTools . generateMethod ( METHOD_NEXT_VERSION , JavaVisibility . PUBLIC , null , new Parameter ( this . versionColumn . getFullyQualifiedJavaType ( ) , "version" ) ) ; commentGenerator . addSetterComment ( nextVersion , introspectedTable , this . versionColumn ) ; JavaElementGeneratorTools . generateMethodBody ( nextVersion , "this." + this . versionColumn . getJavaProperty ( ) + " = version;" ) ; FormatTools . addMethodWithBestPosition ( topLevelClass , nextVersion ) ; } return super . modelSetterMethodGenerated ( method , topLevelClass , introspectedColumn , introspectedTable , modelClassType ) ;


signature:
public class OptimisticLockerPlugin { /** * Model builder set 方法生成
 * @ param method
 * @ param topLevelClass
 * @ param builderClass
 * @ param introspectedColumn
 * @ param introspectedTable
 * @ return */
@ Override public boolean modelBuilderSetterMethodGenerated ( Method method , TopLevelClass topLevelClass , InnerClass builderClass , IntrospectedColumn introspectedColumn , IntrospectedTable introspectedTable ) { } }

implementation:
if ( this . versionColumn != null && this . customizedNextVersion && introspectedColumn . getActualColumnName ( ) . equals ( this . versionColumn . getActualColumnName ( ) ) ) { // nextVersion 方法
Method nextVersion = JavaElementGeneratorTools . generateMethod ( METHOD_NEXT_VERSION , JavaVisibility . PUBLIC , builderClass . getType ( ) , new Parameter ( this . versionColumn . getFullyQualifiedJavaType ( ) , "version" ) ) ; commentGenerator . addSetterComment ( nextVersion , introspectedTable , this . versionColumn ) ; Method setterMethod = JavaBeansUtil . getJavaBeansSetter ( this . versionColumn , context , introspectedTable ) ; JavaElementGeneratorTools . generateMethodBody ( nextVersion , "obj." + setterMethod . getName ( ) + "(version);" , "return this;" ) ; FormatTools . addMethodWithBestPosition ( builderClass , nextVersion ) ; } return true ;


signature:
public class OptimisticLockerPlugin { /** * Model builder class 生成
 * @ param topLevelClass
 * @ param builderClass
 * @ param columns
 * @ param introspectedTable
 * @ return */
@ Override public boolean modelBuilderClassGenerated ( TopLevelClass topLevelClass , InnerClass builderClass , List < IntrospectedColumn > columns , IntrospectedTable introspectedTable ) { } }

implementation: return true ;


signature:
public class OptimisticLockerPlugin { /** * = = = = = sqlMap 生成 = = = = = */
@ Override public boolean sqlMapDeleteByExampleElementGenerated ( XmlElement element , IntrospectedTable introspectedTable ) { } }

implementation: if ( this . versionColumn != null ) { this . sqlMaps . get ( introspectedTable ) . add ( this . replaceExampleXmlElement ( introspectedTable , element , METHOD_DELETE_WITH_VERSION_BY_EXAMPLE ) ) ; } return super . sqlMapDeleteByExampleElementGenerated ( element , introspectedTable ) ;


signature:
public class OptimisticLockerPlugin { /** * 生成版本判断节点
 * @ return */
private String generateVersionEleStr ( ) { } }

implementation: StringBuilder sb = new StringBuilder ( ) ; sb . append ( MyBatis3FormattingUtilities . getEscapedColumnName ( this . versionColumn ) ) ; sb . append ( " = " ) ; sb . append ( "#{version,jdbcType=" ) ; sb . append ( this . versionColumn . getJdbcTypeName ( ) ) ; if ( StringUtility . stringHasValue ( this . versionColumn . getTypeHandler ( ) ) ) { sb . append ( ",typeHandler=" ) ; sb . append ( this . versionColumn . getTypeHandler ( ) ) ; } sb . append ( "}" ) ; return sb . toString ( ) ;


signature:
public class OptimisticLockerPlugin { /** * 替换Example 方法
 * @ param introspectedTable
 * @ param method
 * @ param interfaze
 * @ param methodName
 * @ return */
private Method replaceUpdateExampleMethod ( IntrospectedTable introspectedTable , Method method , Interface interfaze , String methodName ) { } }

implementation:
Method withVersionMethod = new Method ( method ) ; // 替换方法名
withVersionMethod . setName ( methodName ) ; FormatTools . replaceGeneralMethodComment ( commentGenerator , withVersionMethod , introspectedTable ) ; Parameter versionParam = new Parameter ( this . versionColumn . getFullyQualifiedJavaType ( ) , "version" , "@Param(\"version\")" ) ; withVersionMethod . addParameter ( 0 , versionParam ) ; return withVersionMethod ;


signature:
public class OptimisticLockerPlugin { /** * 替换Example 方法
 * @ param introspectedTable
 * @ param method
 * @ param interfaze
 * @ param methodName
 * @ return */
private Method replaceDeleteExampleMethod ( IntrospectedTable introspectedTable , Method method , Interface interfaze , String methodName ) { } }

implementation:
Method withVersionMethod = new Method ( method ) ; // 替换方法名
withVersionMethod . setName ( methodName ) ; FormatTools . replaceGeneralMethodComment ( commentGenerator , withVersionMethod , introspectedTable ) ; Parameter versionParam = new Parameter ( this . versionColumn . getFullyQualifiedJavaType ( ) , "version" , "@Param(\"version\")" ) ; Parameter exampleParam = new Parameter ( new FullyQualifiedJavaType ( introspectedTable . getExampleType ( ) ) , "example" , "@Param(\"example\")" ) ; withVersionMethod . getParameters ( ) . clear ( ) ; withVersionMethod . addParameter ( versionParam ) ; withVersionMethod . addParameter ( exampleParam ) ; return withVersionMethod ;


signature:
public class OptimisticLockerPlugin { /** * 替换主键 方法
 * @ param introspectedTable
 * @ param method
 * @ param interfaze
 * @ param methodName
 * @ return */
private Method replaceUpdatePrimaryKeyMethod ( IntrospectedTable introspectedTable , Method method , Interface interfaze , String methodName ) { } }

implementation:
Method withVersionMethod = new Method ( method ) ; // 替换方法名
withVersionMethod . setName ( methodName ) ; FormatTools . replaceGeneralMethodComment ( commentGenerator , withVersionMethod , introspectedTable ) ; Parameter versionParam = new Parameter ( this . versionColumn . getFullyQualifiedJavaType ( ) , "version" , "@Param(\"version\")" ) ; Parameter recordParam = new Parameter ( method . getParameters ( ) . get ( 0 ) . getType ( ) , "record" , "@Param(\"record\")" ) ; withVersionMethod . getParameters ( ) . clear ( ) ; withVersionMethod . addParameter ( versionParam ) ; withVersionMethod . addParameter ( recordParam ) ; return withVersionMethod ;


signature:
public class OptimisticLockerPlugin { /** * 替换Example
 * @ param introspectedTable
 * @ param element
 * @ param id
 * @ return */
private XmlElement replaceExampleXmlElement ( IntrospectedTable introspectedTable , XmlElement element , String id ) { } }

implementation:
XmlElement withVersionEle = XmlElementTools . clone ( element ) ; XmlElementTools . replaceAttribute ( withVersionEle , new Attribute ( "id" , id ) ) ; XmlElementTools . replaceAttribute ( withVersionEle , new Attribute ( "parameterType" , "map" ) ) ; FormatTools . replaceComment ( commentGenerator , withVersionEle ) ; // 替换查询语句
List < XmlElement > ifEles = XmlElementTools . findXmlElements ( withVersionEle , "if" ) ; for ( XmlElement ifEle : ifEles ) { List < XmlElement > includeEles = XmlElementTools . findXmlElements ( ifEle , "include" ) ; for ( XmlElement includeEle : includeEles ) { if ( XmlElementTools . getAttribute ( includeEle , "refid" ) != null ) { XmlElementTools . replaceAttribute ( includeEle , new Attribute ( "refid" , SQL_UPDATE_BY_EXAMPLE_WITH_VERSION_WHERE_CLAUSE ) ) ; } } } return withVersionEle ;


signature:
public class OptimisticLockerPlugin { /** * 替换 主键查询
 * @ param introspectedTable
 * @ param element
 * @ param id
 * @ param update
 * @ return */
private XmlElement replacePrimaryKeyXmlElement ( IntrospectedTable introspectedTable , XmlElement element , String id , boolean update ) { } }

implementation:
XmlElement withVersionEle = XmlElementTools . clone ( element ) ; XmlElementTools . replaceAttribute ( withVersionEle , new Attribute ( "id" , id ) ) ; XmlElementTools . replaceAttribute ( withVersionEle , new Attribute ( "parameterType" , "map" ) ) ; FormatTools . replaceComment ( commentGenerator , withVersionEle ) ; // 替换查询语句
Iterator < Element > elementIterator = withVersionEle . getElements ( ) . iterator ( ) ; boolean flag = false ; while ( elementIterator . hasNext ( ) ) { Element ele = elementIterator . next ( ) ; if ( ele instanceof TextElement && ( ( TextElement ) ele ) . getContent ( ) . matches ( ".*where.*" ) ) { flag = true ; } if ( flag ) { elementIterator . remove ( ) ; } } // where 语句
withVersionEle . addElement ( new TextElement ( "where " + this . generateVersionEleStr ( ) ) ) ; if ( introspectedTable . getPrimaryKeyColumns ( ) . size ( ) == 1 ) { IntrospectedColumn introspectedColumn = introspectedTable . getPrimaryKeyColumns ( ) . get ( 0 ) ; StringBuilder sb = new StringBuilder ( ) ; sb . append ( "  and " ) ; sb . append ( MyBatis3FormattingUtilities . getEscapedColumnName ( introspectedColumn ) ) ; sb . append ( " = " ) ; if ( update ) { sb . append ( MyBatis3FormattingUtilities . getParameterClause ( introspectedColumn , "record." ) ) ; } else { sb . append ( "#{key,jdbcType=" ) ; sb . append ( introspectedColumn . getJdbcTypeName ( ) ) ; if ( StringUtility . stringHasValue ( introspectedColumn . getTypeHandler ( ) ) ) { sb . append ( ",typeHandler=" ) ; sb . append ( introspectedColumn . getTypeHandler ( ) ) ; } sb . append ( "}" ) ; } withVersionEle . addElement ( new TextElement ( sb . toString ( ) ) ) ; } else { for ( IntrospectedColumn introspectedColumn : introspectedTable . getPrimaryKeyColumns ( ) ) { StringBuilder sb = new StringBuilder ( ) ; sb . append ( "  and " ) ; sb . append ( MyBatis3FormattingUtilities . getEscapedColumnName ( introspectedColumn ) ) ; sb . append ( " = " ) ; sb . append ( MyBatis3FormattingUtilities . getParameterClause ( introspectedColumn , update ? "record." : "key." ) ) ; withVersionEle . addElement ( new TextElement ( sb . toString ( ) ) ) ; } } return withVersionEle ;


signature:
public class OptimisticLockerPlugin { /** * 生成update sql map
 * @ param introspectedTable
 * @ param columns
 * @ param id
 * @ param selective
 * @ param byExample
 * @ return */
private XmlElement generateSqlMapUpdate ( IntrospectedTable introspectedTable , List < IntrospectedColumn > columns , String id , boolean selective , boolean byExample ) { } }

implementation:
// 移除版本列
Iterator < IntrospectedColumn > columnIterator = columns . iterator ( ) ; while ( columnIterator . hasNext ( ) ) { IntrospectedColumn introspectedColumn = columnIterator . next ( ) ; if ( introspectedColumn . getActualColumnName ( ) . equals ( this . versionColumn . getActualColumnName ( ) ) ) { columnIterator . remove ( ) ; } } XmlElement updateEle = new XmlElement ( "update" ) ; updateEle . addAttribute ( new Attribute ( "id" , id ) ) ; updateEle . addAttribute ( new Attribute ( "parameterType" , "map" ) ) ; commentGenerator . addComment ( updateEle ) ; updateEle . addElement ( new TextElement ( "update " + introspectedTable . getAliasedFullyQualifiedTableNameAtRuntime ( ) ) ) ; if ( selective ) { XmlElement setEle = new XmlElement ( "set" ) ; updateEle . addElement ( setEle ) ; // set 节点
XmlElement setsEle = XmlElementGeneratorTools . generateSetsSelective ( columns , "record." ) ; setEle . addElement ( setsEle ) ; XmlElement needVersionEle ; if ( PluginTools . getHook ( IOptimisticLockerPluginHook . class ) . generateSetsSelectiveElement ( columns , this . versionColumn , setsEle ) ) { needVersionEle = setEle ; } else { needVersionEle = setsEle ; } // 版本自增
needVersionEle . addElement ( 0 , this . generateVersionSetEle ( selective ) ) ; } else { // 版本自增
updateEle . addElement ( this . generateVersionSetEle ( selective ) ) ; // set 节点
List < Element > setsEles = XmlElementGeneratorTools . generateSets ( columns , "record." ) ; // XmlElementGeneratorTools . generateSets , 因为传入参数不可能带IdentityAndGeneratedAlwaysColumn所以返回的是set列表而不可能是trim 元素
for ( Element ele : setsEles ) { updateEle . addElement ( ele ) ; } } // 更新条件
if ( byExample ) { XmlElement ifElement = new XmlElement ( "if" ) ; ifElement . addAttribute ( new Attribute ( "test" , "_parameter != null" ) ) ; XmlElement includeElement = new XmlElement ( "include" ) ; includeElement . addAttribute ( new Attribute ( "refid" , SQL_UPDATE_BY_EXAMPLE_WITH_VERSION_WHERE_CLAUSE ) ) ; ifElement . addElement ( includeElement ) ; updateEle . addElement ( ifElement ) ; } else { updateEle = this . replacePrimaryKeyXmlElement ( introspectedTable , updateEle , id , true ) ; } return updateEle ;


signature:
public class OptimisticLockerPlugin { /** * 生成LogicalDelete sql map
 * @ param introspectedTable
 * @ param id
 * @ param logicalDeleteColumn
 * @ param logicalDeleteValue
 * @ param byExample
 * @ return */
private XmlElement generateSqlMapLogicalDelete ( IntrospectedTable introspectedTable , String id , IntrospectedColumn logicalDeleteColumn , String logicalDeleteValue , boolean byExample ) { } }

implementation:
XmlElement updateEle = new XmlElement ( "update" ) ; updateEle . addAttribute ( new Attribute ( "id" , id ) ) ; updateEle . addAttribute ( new Attribute ( "parameterType" , "map" ) ) ; commentGenerator . addComment ( updateEle ) ; updateEle . addElement ( new TextElement ( "update " + introspectedTable . getAliasedFullyQualifiedTableNameAtRuntime ( ) ) ) ; StringBuilder sb = new StringBuilder ( "set " ) ; // 版本自增
if ( this . customizedNextVersion ) { sb . append ( MyBatis3FormattingUtilities . getEscapedColumnName ( this . versionColumn ) ) ; sb . append ( " = " ) ; sb . append ( "#{nextVersion,jdbcType=" ) ; sb . append ( this . versionColumn . getJdbcTypeName ( ) ) ; if ( StringUtility . stringHasValue ( this . versionColumn . getTypeHandler ( ) ) ) { sb . append ( ",typeHandler=" ) ; sb . append ( this . versionColumn . getTypeHandler ( ) ) ; } sb . append ( "}" ) ; } else { sb . append ( MyBatis3FormattingUtilities . getEscapedColumnName ( this . versionColumn ) ) ; sb . append ( " = " ) ; sb . append ( MyBatis3FormattingUtilities . getEscapedColumnName ( this . versionColumn ) ) ; sb . append ( " + 1" ) ; } sb . append ( "," ) ; // 逻辑删除 set
sb . append ( logicalDeleteColumn . getActualColumnName ( ) ) ; sb . append ( " = " ) ; sb . append ( XmlElementGeneratorTools . generateLogicalDeleteColumnValue ( logicalDeleteColumn , logicalDeleteValue ) ) ; updateEle . addElement ( new TextElement ( sb . toString ( ) ) ) ; // 更新条件
if ( byExample ) { XmlElement ifElement = new XmlElement ( "if" ) ; ifElement . addAttribute ( new Attribute ( "test" , "_parameter != null" ) ) ; XmlElement includeElement = new XmlElement ( "include" ) ; includeElement . addAttribute ( new Attribute ( "refid" , SQL_UPDATE_BY_EXAMPLE_WITH_VERSION_WHERE_CLAUSE ) ) ; ifElement . addElement ( includeElement ) ; updateEle . addElement ( ifElement ) ; } else { updateEle = this . replacePrimaryKeyXmlElement ( introspectedTable , updateEle , id , false ) ; } return updateEle ;


signature:
public class OptimisticLockerPlugin { /** * 生成版本号set节点
 * @ param selective
 * @ return */
private TextElement generateVersionSetEle ( boolean selective ) { } }

implementation: if ( this . customizedNextVersion ) { return new TextElement ( ( selective ? "" : "set " ) + MyBatis3FormattingUtilities . getEscapedColumnName ( this . versionColumn ) + " = " + MyBatis3FormattingUtilities . getParameterClause ( this . versionColumn , "record." ) + "," ) ; } else { return new TextElement ( ( selective ? "" : "set " ) + MyBatis3FormattingUtilities . getEscapedColumnName ( this . versionColumn ) + " = " + MyBatis3FormattingUtilities . getEscapedColumnName ( this . versionColumn ) + " + 1," ) ; }


signature:
public class IncrementsPlugin { /** * 具体执行顺序 http : / / www . mybatis . org / generator / reference / pluggingIn . html
 * @ param warnings
 * @ return */
@ Override public boolean validate ( List < String > warnings ) { } }

implementation:
// 插件使用前提是使用了ModelBuilderPlugin插件
if ( ! ( PluginTools . checkDependencyPlugin ( getContext ( ) , ModelBuilderPlugin . class ) || PluginTools . checkDependencyPlugin ( getContext ( ) , LombokPlugin . class ) ) ) { warnings . add ( "itfsw:插件" + this . getClass ( ) . getTypeName ( ) + "插件需配合" + ModelBuilderPlugin . class . getTypeName ( ) + "或者" + LombokPlugin . class . getTypeName ( ) + "插件使用！" ) ; return false ; } return super . validate ( warnings ) ;


signature:
public class IncrementsPlugin { /** * 具体执行顺序 http : / / www . mybatis . org / generator / reference / pluggingIn . html
 * @ param introspectedTable */
@ Override public void initialized ( IntrospectedTable introspectedTable ) { } }

implementation:
super . initialized ( introspectedTable ) ; this . incColumns = new ArrayList < > ( ) ; this . incEnum = null ; this . incEnumBuilder = null ; String incrementsColumns = introspectedTable . getTableConfigurationProperty ( IncrementsPlugin . PRO_INCREMENTS_COLUMNS ) ; if ( StringUtility . stringHasValue ( incrementsColumns ) ) { // 切分
String [ ] incrementsColumnsStrs = incrementsColumns . split ( "," ) ; for ( String incrementsColumnsStr : incrementsColumnsStrs ) { IntrospectedColumn column = IntrospectedTableTools . safeGetColumn ( introspectedTable , incrementsColumnsStr ) ; if ( column == null ) { warnings . add ( "itfsw:插件" + IncrementsPlugin . class . getTypeName ( ) + "插件没有找到column为" + incrementsColumnsStr . trim ( ) + "的字段！" ) ; } else { incColumns . add ( column ) ; } } }


signature:
public class IncrementsPlugin { /** * 具体执行顺序 http : / / www . mybatis . org / generator / reference / pluggingIn . html
 * @ param element
 * @ param introspectedTable
 * @ return */
@ Override public boolean sqlMapUpdateByExampleSelectiveElementGenerated ( XmlElement element , IntrospectedTable introspectedTable ) { } }

implementation: generatedWithSelective ( element , introspectedTable , true ) ; return super . sqlMapUpdateByExampleSelectiveElementGenerated ( element , introspectedTable ) ;


signature:
public class IncrementsPlugin { /** * 具体执行顺序 http : / / www . mybatis . org / generator / reference / pluggingIn . html
 * @ param element
 * @ param introspectedTable
 * @ return */
@ Override public boolean sqlMapUpdateByExampleWithBLOBsElementGenerated ( XmlElement element , IntrospectedTable introspectedTable ) { } }

implementation: generatedWithoutSelective ( element , introspectedTable , true ) ; return super . sqlMapUpdateByExampleWithBLOBsElementGenerated ( element , introspectedTable ) ;


signature:
public class IncrementsPlugin { /** * 具体执行顺序 http : / / www . mybatis . org / generator / reference / pluggingIn . html
 * @ param element
 * @ param introspectedTable
 * @ return */
@ Override public boolean sqlMapUpdateByExampleWithoutBLOBsElementGenerated ( XmlElement element , IntrospectedTable introspectedTable ) { } }

implementation: generatedWithoutSelective ( element , introspectedTable , true ) ; return super . sqlMapUpdateByExampleWithoutBLOBsElementGenerated ( element , introspectedTable ) ;


signature:
public class IncrementsPlugin { /** * 具体执行顺序 http : / / www . mybatis . org / generator / reference / pluggingIn . html
 * @ param element
 * @ param introspectedTable
 * @ return */
@ Override public boolean sqlMapUpdateByPrimaryKeySelectiveElementGenerated ( XmlElement element , IntrospectedTable introspectedTable ) { } }

implementation: generatedWithSelective ( element , introspectedTable , false ) ; return super . sqlMapUpdateByPrimaryKeySelectiveElementGenerated ( element , introspectedTable ) ;


signature:
public class IncrementsPlugin { /** * 具体执行顺序 http : / / www . mybatis . org / generator / reference / pluggingIn . html
 * @ param element
 * @ param introspectedTable
 * @ return */
@ Override public boolean sqlMapUpdateByPrimaryKeyWithBLOBsElementGenerated ( XmlElement element , IntrospectedTable introspectedTable ) { } }

implementation: generatedWithoutSelective ( element , introspectedTable , false ) ; return super . sqlMapUpdateByPrimaryKeyWithBLOBsElementGenerated ( element , introspectedTable ) ;


signature:
public class IncrementsPlugin { /** * 具体执行顺序 http : / / www . mybatis . org / generator / reference / pluggingIn . html
 * @ param element
 * @ param introspectedTable
 * @ return */
@ Override public boolean sqlMapUpdateByPrimaryKeyWithoutBLOBsElementGenerated ( XmlElement element , IntrospectedTable introspectedTable ) { } }

implementation: generatedWithoutSelective ( element , introspectedTable , false ) ; return super . sqlMapUpdateByPrimaryKeyWithoutBLOBsElementGenerated ( element , introspectedTable ) ;


signature:
public class IncrementsPlugin { /** * = = = = = ILombokPluginHook = = = = = */
@ Override public boolean modelBaseRecordBuilderClassGenerated ( TopLevelClass topLevelClass , List < IntrospectedColumn > columns , IntrospectedTable introspectedTable ) { } }

implementation: return this . lombokBuilderClassGenerated ( topLevelClass , columns , introspectedTable ) ;


signature:
public class IncrementsPlugin { /** * Lombok Builder 生成
 * @ param topLevelClass
 * @ param columns
 * @ param introspectedTable
 * @ return */
private boolean lombokBuilderClassGenerated ( TopLevelClass topLevelClass , List < IntrospectedColumn > columns , IntrospectedTable introspectedTable ) { } }

implementation:
if ( this . support ( ) ) { boolean find = false ; for ( IntrospectedColumn column : columns ) { if ( this . supportColumn ( column ) ) { find = true ; break ; } } if ( find ) { // - - - - - topLevelClass 方法 - - - - -
FullyQualifiedJavaType builderType = new FullyQualifiedJavaType ( topLevelClass . getType ( ) . getShortName ( ) + "." + topLevelClass . getType ( ) . getShortName ( ) + "Builder" ) ; builderType . addTypeArgument ( new SpecTypeArgumentsFullyQualifiedJavaType ( "<?, ?>" ) ) ; // 增加构造函数
Method constructor = new Method ( topLevelClass . getType ( ) . getShortName ( ) ) ; commentGenerator . addGeneralMethodComment ( constructor , introspectedTable ) ; constructor . setVisibility ( JavaVisibility . PROTECTED ) ; constructor . setConstructor ( true ) ; constructor . addParameter ( new Parameter ( builderType , "builder" ) ) ; // 是否调用父类构造函数
if ( topLevelClass . getSuperClass ( ) != null ) { constructor . addBodyLine ( "super(builder);" ) ; } for ( IntrospectedColumn column : columns ) { Field field = JavaBeansUtil . getJavaBeansField ( column , context , introspectedTable ) ; constructor . addBodyLine ( "this." + field . getName ( ) + " = builder." + field . getName ( ) + ";" ) ; } FormatTools . addMethodWithBestPosition ( topLevelClass , constructor ) ; // 增加静态builder方法实现和lombok一样
Method builderMethod = JavaElementGeneratorTools . generateMethod ( "builder" , JavaVisibility . PUBLIC , builderType ) ; commentGenerator . addGeneralMethodComment ( builderMethod , introspectedTable ) ; builderMethod . setStatic ( true ) ; builderMethod . addBodyLine ( "return new " + topLevelClass . getType ( ) . getShortName ( ) + "." + topLevelClass . getType ( ) . getShortName ( ) + "BuilderImpl();" ) ; FormatTools . addMethodWithBestPosition ( topLevelClass , builderMethod ) ; // - - - - - builder Class - - - - -
InnerClass builderCls = new InnerClass ( topLevelClass . getType ( ) . getShortName ( ) + "Builder" ) ; commentGenerator . addClassComment ( builderCls , introspectedTable ) ; builderCls . setVisibility ( JavaVisibility . PUBLIC ) ; builderCls . setStatic ( true ) ; builderCls . setAbstract ( true ) ; builderCls . getType ( ) . addTypeArgument ( new SpecTypeArgumentsFullyQualifiedJavaType ( "<C extends " + topLevelClass . getType ( ) . getShortName ( ) + ", B extends " + topLevelClass . getType ( ) . getShortName ( ) + "." + topLevelClass . getType ( ) . getShortName ( ) + "Builder<C, B>>" ) ) ; if ( topLevelClass . getSuperClass ( ) != null ) { FullyQualifiedJavaType superBuilderCls = new FullyQualifiedJavaType ( topLevelClass . getSuperClass ( ) . getShortName ( ) + "Builder" ) ; superBuilderCls . addTypeArgument ( new SpecTypeArgumentsFullyQualifiedJavaType ( "<C, B>" ) ) ; builderCls . setSuperClass ( superBuilderCls ) ; } // 类注解
topLevelClass . addImportedType ( LombokPlugin . EnumLombokAnnotations . SETTER . getClazz ( ) ) ; builderCls . addAnnotation ( LombokPlugin . EnumLombokAnnotations . SETTER . getAnnotation ( ) ) ; topLevelClass . addImportedType ( LombokPlugin . EnumLombokAnnotations . ACCESSORS_FLUENT_TRUE . getClazz ( ) ) ; builderCls . addAnnotation ( LombokPlugin . EnumLombokAnnotations . ACCESSORS_FLUENT_TRUE . getAnnotation ( ) ) ; if ( topLevelClass . getSuperClass ( ) != null ) { topLevelClass . addImportedType ( LombokPlugin . EnumLombokAnnotations . TO_STRING_CALL_SUPER . getClazz ( ) ) ; builderCls . addAnnotation ( LombokPlugin . EnumLombokAnnotations . TO_STRING_CALL_SUPER . getAnnotation ( ) ) ; } else { topLevelClass . addImportedType ( LombokPlugin . EnumLombokAnnotations . TO_STRING . getClazz ( ) ) ; builderCls . addAnnotation ( LombokPlugin . EnumLombokAnnotations . TO_STRING . getAnnotation ( ) ) ; } for ( IntrospectedColumn introspectedColumn : columns ) { Field field = JavaBeansUtil . getJavaBeansField ( introspectedColumn , context , introspectedTable ) ; field . getJavaDocLines ( ) . clear ( ) ; commentGenerator . addFieldComment ( field , introspectedTable ) ; builderCls . addField ( field ) ; } // self 方法
Method selfMethod1 = JavaElementGeneratorTools . generateMethod ( "self" , JavaVisibility . PROTECTED , new FullyQualifiedJavaType ( "B" ) ) ; commentGenerator . addGeneralMethodComment ( selfMethod1 , introspectedTable ) ; FormatTools . addMethodWithBestPosition ( builderCls , selfMethod1 ) ; // build 方法
Method buildMethod1 = JavaElementGeneratorTools . generateMethod ( "build" , JavaVisibility . PUBLIC , new FullyQualifiedJavaType ( "C" ) ) ; commentGenerator . addGeneralMethodComment ( buildMethod1 , introspectedTable ) ; FormatTools . addMethodWithBestPosition ( builderCls , buildMethod1 ) ; topLevelClass . addInnerClass ( builderCls ) ; // - - - - - 生成自增插件需要的方法 - - - - -
// 增加枚举
if ( this . incEnum == null ) { this . incEnum = this . generatedIncEnum ( introspectedTable ) ; this . incEnumBuilder = builderCls ; builderCls . addInnerEnum ( this . incEnum ) ; // topLevel class 添加必要的操作方法
this . addIncMethodToTopLevelClass ( topLevelClass , builderCls , introspectedTable , true ) ; // Builder 中 添加字段支持
Field fIncrements = JavaElementGeneratorTools . generateField ( IncrementsPlugin . FIELD_INC_MAP , JavaVisibility . PROTECTED , new FullyQualifiedJavaType ( "Map<String, " + this . getIncEnum ( builderCls , introspectedTable ) . getFullyQualifiedName ( ) + ">" ) , "new HashMap<String, " + this . getIncEnum ( builderCls , introspectedTable ) . getFullyQualifiedName ( ) + ">()" ) ; commentGenerator . addFieldComment ( fIncrements , introspectedTable ) ; builderCls . addField ( fIncrements ) ; // Builder 构造函数增加 自增Map
constructor . addBodyLine ( "this." + IncrementsPlugin . FIELD_INC_MAP + ".putAll(builder." + IncrementsPlugin . FIELD_INC_MAP + ");" ) ; } FullyQualifiedJavaType builderType2 = new FullyQualifiedJavaType ( topLevelClass . getType ( ) . getShortName ( ) + "." + topLevelClass . getType ( ) . getShortName ( ) + "Builder" ) ; builderType2 . addTypeArgument ( new SpecTypeArgumentsFullyQualifiedJavaType ( "<C, B>" ) ) ; for ( IntrospectedColumn column : columns ) { if ( this . supportColumn ( column ) ) { Field field = JavaBeansUtil . getJavaBeansField ( column , context , introspectedTable ) ; // 增加方法
Method mIncrements = JavaElementGeneratorTools . generateMethod ( field . getName ( ) , JavaVisibility . PUBLIC , builderType2 , new Parameter ( field . getType ( ) , field . getName ( ) ) , new Parameter ( this . getIncEnum ( builderCls , introspectedTable ) , "inc" ) ) ; commentGenerator . addSetterComment ( mIncrements , introspectedTable , column ) ; mIncrements . addBodyLine ( "this." + IncrementsPlugin . FIELD_INC_MAP + ".put(\"" + column . getActualColumnName ( ) + "\", inc);" ) ; mIncrements . addBodyLine ( "return this." + field . getName ( ) + "(" + field . getName ( ) + ");" ) ; FormatTools . addMethodWithBestPosition ( builderCls , mIncrements ) ; } } // - - - - - builderImpl Class - - - - -
InnerClass builderImplCls = new InnerClass ( topLevelClass . getType ( ) . getShortName ( ) + "BuilderImpl" ) ; commentGenerator . addClassComment ( builderImplCls , introspectedTable ) ; FullyQualifiedJavaType builderType1 = new FullyQualifiedJavaType ( topLevelClass . getType ( ) . getShortName ( ) + "." + topLevelClass . getType ( ) . getShortName ( ) + "Builder" ) ; builderType1 . addTypeArgument ( new SpecTypeArgumentsFullyQualifiedJavaType ( "<" + topLevelClass . getType ( ) . getShortName ( ) + ", " + topLevelClass . getType ( ) . getShortName ( ) + "." + topLevelClass . getType ( ) . getShortName ( ) + "BuilderImpl" + ">" ) ) ; builderImplCls . setSuperClass ( builderType1 ) ; builderImplCls . setVisibility ( JavaVisibility . PRIVATE ) ; builderImplCls . setFinal ( true ) ; builderImplCls . setStatic ( true ) ; topLevelClass . addInnerClass ( builderImplCls ) ; // self 方法
Method selfMethod = JavaElementGeneratorTools . generateMethod ( "self" , JavaVisibility . PROTECTED , new FullyQualifiedJavaType ( topLevelClass . getType ( ) . getShortName ( ) + "." + topLevelClass . getType ( ) . getShortName ( ) + "BuilderImpl" ) ) ; commentGenerator . addGeneralMethodComment ( selfMethod , introspectedTable ) ; selfMethod . addBodyLine ( "return this;" ) ; FormatTools . addMethodWithBestPosition ( builderImplCls , selfMethod ) ; // build 方法
Method buildMethod = JavaElementGeneratorTools . generateMethod ( "build" , JavaVisibility . PUBLIC , topLevelClass . getType ( ) ) ; commentGenerator . addGeneralMethodComment ( buildMethod , introspectedTable ) ; buildMethod . addBodyLine ( "return new " + topLevelClass . getType ( ) . getShortName ( ) + "(this);" ) ; FormatTools . addMethodWithBestPosition ( builderImplCls , buildMethod ) ; return false ; } } return true ;


signature:
public class IncrementsPlugin { /** * Model builder class 生成
 * @ param topLevelClass
 * @ param builderClass
 * @ param columns
 * @ param introspectedTable
 * @ return */
@ Override public boolean modelBuilderClassGenerated ( TopLevelClass topLevelClass , InnerClass builderClass , List < IntrospectedColumn > columns , IntrospectedTable introspectedTable ) { } }

implementation:
if ( this . support ( ) ) { if ( this . incEnum == null ) { this . incEnum = this . generatedIncEnum ( introspectedTable ) ; this . incEnumBuilder = builderClass ; // 增加枚举
builderClass . addInnerEnum ( this . incEnum ) ; // topLevel class 添加必要的操作方法
this . addIncMethodToTopLevelClass ( topLevelClass , builderClass , introspectedTable , false ) ; } // Builder 中 添加字段支持
for ( IntrospectedColumn column : columns ) { if ( this . supportColumn ( column ) ) { Field field = JavaBeansUtil . getJavaBeansField ( column , context , introspectedTable ) ; // 增加方法
Method mIncrements = JavaElementGeneratorTools . generateMethod ( field . getName ( ) , JavaVisibility . PUBLIC , builderClass . getType ( ) , new Parameter ( field . getType ( ) , field . getName ( ) ) , new Parameter ( this . getIncEnum ( builderClass , introspectedTable ) , "inc" ) ) ; commentGenerator . addSetterComment ( mIncrements , introspectedTable , column ) ; Method setterMethod = JavaBeansUtil . getJavaBeansSetter ( column , context , introspectedTable ) ; mIncrements . addBodyLine ( "obj." + IncrementsPlugin . FIELD_INC_MAP + ".put(\"" + column . getActualColumnName ( ) + "\", inc);" ) ; mIncrements . addBodyLine ( "obj." + setterMethod . getName ( ) + "(" + field . getName ( ) + ");" ) ; mIncrements . addBodyLine ( "return this;" ) ; FormatTools . addMethodWithBestPosition ( builderClass , mIncrements ) ; } } } return true ;


signature:
public class IncrementsPlugin { /** * Model builder set 方法生成
 * @ param method
 * @ param topLevelClass
 * @ param builderClass
 * @ param introspectedColumn
 * @ param introspectedTable
 * @ return */
@ Override public boolean modelBuilderSetterMethodGenerated ( Method method , TopLevelClass topLevelClass , InnerClass builderClass , IntrospectedColumn introspectedColumn , IntrospectedTable introspectedTable ) { } }

implementation: return true ;


signature:
public class IncrementsPlugin { /** * 生成增量操作节点
 * @ param introspectedColumn
 * @ param prefix
 * @ param hasComma
 * @ return */
@ Override public List < Element > incrementSetElementGenerated ( IntrospectedColumn introspectedColumn , String prefix , boolean hasComma ) { } }

implementation:
List < Element > list = new ArrayList < > ( ) ; if ( this . supportColumn ( introspectedColumn ) ) { // 1 . column = 节点
list . add ( new TextElement ( MyBatis3FormattingUtilities . getEscapedColumnName ( introspectedColumn ) + " = " ) ) ; // 2 . 选择节点
// 条件
XmlElement choose = new XmlElement ( "choose" ) ; // 没有启用增量操作
XmlElement when = new XmlElement ( "when" ) ; when . addAttribute ( new Attribute ( "test" , ( prefix != null ? prefix : "_parameter." ) + IncrementsPlugin . METHOD_INC_CHECK + "('" + MyBatis3FormattingUtilities . escapeStringForMyBatis3 ( introspectedColumn . getActualColumnName ( ) ) + "')" ) ) ; TextElement spec = new TextElement ( MyBatis3FormattingUtilities . getEscapedColumnName ( introspectedColumn ) + " ${" + ( prefix != null ? prefix : "_parameter." ) + IncrementsPlugin . METHOD_GET_INC_MAP + "()." + MyBatis3FormattingUtilities . escapeStringForMyBatis3 ( introspectedColumn . getActualColumnName ( ) ) + ".value} " + MyBatis3FormattingUtilities . getParameterClause ( introspectedColumn , prefix ) ) ; when . addElement ( spec ) ; choose . addElement ( when ) ; // 启用了增量操作
XmlElement otherwise = new XmlElement ( "otherwise" ) ; TextElement normal = new TextElement ( MyBatis3FormattingUtilities . getParameterClause ( introspectedColumn , prefix ) ) ; otherwise . addElement ( normal ) ; choose . addElement ( otherwise ) ; list . add ( choose ) ; // 3 . 结尾逗号
if ( hasComma ) { list . add ( new TextElement ( "," ) ) ; } } return list ;


signature:
public class IncrementsPlugin { /** * 生成增量操作节点 ( SelectiveEnhancedPlugin )
 * @ param versionColumn 需要排除的column ( 主要是和乐观锁插件整合时要把版本列排除掉 )
 * @ return */
@ Override public Element incrementSetsWithSelectiveEnhancedPluginElementGenerated ( IntrospectedColumn versionColumn ) { } }

implementation:
if ( this . support ( ) ) { XmlElement choose = new XmlElement ( "choose" ) ; for ( IntrospectedColumn introspectedColumn : this . incColumns ) { if ( versionColumn == null || ! introspectedColumn . getActualColumnName ( ) . equals ( versionColumn . getActualColumnName ( ) ) ) { XmlElement when = new XmlElement ( "when" ) ; // 需要 inc 的列
StringBuilder sb = new StringBuilder ( ) ; sb . append ( "'" ) ; sb . append ( introspectedColumn . getActualColumnName ( ) ) ; sb . append ( "'.toString()" ) ; sb . append ( " == " ) ; sb . append ( "column.value" ) ; when . addAttribute ( new Attribute ( "test" , sb . toString ( ) ) ) ; when . addElement ( new TextElement ( "${column.escapedColumnName} = ${column.escapedColumnName} ${record." + METHOD_GET_INC_MAP + "()." + introspectedColumn . getActualColumnName ( ) + ".value} #{record.${column.javaProperty},jdbcType=${column.jdbcType}}" ) ) ; choose . addElement ( when ) ; } } if ( versionColumn == null ) { XmlElement otherwise = new XmlElement ( "otherwise" ) ; otherwise . addElement ( new TextElement ( "${column.escapedColumnName} = #{record.${column.javaProperty},jdbcType=${column.jdbcType}}" ) ) ; choose . addElement ( otherwise ) ; } else { XmlElement when = new XmlElement ( "when" ) ; when . addAttribute ( new Attribute ( "test" , "column.value != '" + versionColumn . getActualColumnName ( ) + "'.toString()" ) ) ; when . addElement ( new TextElement ( "${column.escapedColumnName} = #{record.${column.javaProperty},jdbcType=${column.jdbcType}}" ) ) ; choose . addElement ( when ) ; } return choose ; } return null ;


signature:
public class IncrementsPlugin { /** * 向topLevelClass 添加必要的操作函数
 * @ param topLevelClass
 * @ param builderCls
 * @ param introspectedTable
 * @ param withLombok */
private void addIncMethodToTopLevelClass ( TopLevelClass topLevelClass , InnerClass builderCls , IntrospectedTable introspectedTable , boolean withLombok ) { } }

implementation:
// 增加field
Field fIncrements = JavaElementGeneratorTools . generateField ( IncrementsPlugin . FIELD_INC_MAP , JavaVisibility . PROTECTED , new FullyQualifiedJavaType ( "Map<String, " + this . getIncEnum ( builderCls , introspectedTable ) . getFullyQualifiedName ( ) + ">" ) , "new HashMap<String, " + this . getIncEnum ( builderCls , introspectedTable ) . getFullyQualifiedName ( ) + ">()" ) ; fIncrements . setFinal ( true ) ; commentGenerator . addFieldComment ( fIncrements , introspectedTable ) ; topLevelClass . addField ( fIncrements ) ; topLevelClass . addImportedType ( "java.util.Map" ) ; topLevelClass . addImportedType ( "java.util.HashMap" ) ; // inc map 获取方法
if ( withLombok ) { topLevelClass . addImportedType ( LombokPlugin . EnumLombokAnnotations . ACCESSORS_FLUENT_TRUE . getClazz ( ) ) ; fIncrements . addAnnotation ( LombokPlugin . EnumLombokAnnotations . ACCESSORS_FLUENT_TRUE . getAnnotation ( ) ) ; } else { Method getIncMapMethod = JavaElementGeneratorTools . generateMethod ( METHOD_GET_INC_MAP , JavaVisibility . PUBLIC , fIncrements . getType ( ) ) ; commentGenerator . addGeneralMethodComment ( getIncMapMethod , introspectedTable ) ; getIncMapMethod . addBodyLine ( "return this." + FIELD_INC_MAP + ";" ) ; FormatTools . addMethodWithBestPosition ( topLevelClass , getIncMapMethod ) ; } // 增加判断方法
Method mHasIncsForColumn = JavaElementGeneratorTools . generateMethod ( IncrementsPlugin . METHOD_INC_CHECK , JavaVisibility . PUBLIC , FullyQualifiedJavaType . getBooleanPrimitiveInstance ( ) , new Parameter ( FullyQualifiedJavaType . getStringInstance ( ) , "column" ) ) ; commentGenerator . addGeneralMethodComment ( mHasIncsForColumn , introspectedTable ) ; mHasIncsForColumn . addBodyLine ( "return " + IncrementsPlugin . FIELD_INC_MAP + ".get(column) != null;" ) ; FormatTools . addMethodWithBestPosition ( topLevelClass , mHasIncsForColumn ) ;


signature:
public class IncrementsPlugin { /** * 生成Inc enum
 * @ param introspectedTable
 * @ return */
private InnerEnum generatedIncEnum ( IntrospectedTable introspectedTable ) { } }

implementation:
// 增加枚举
InnerEnum eIncrements = new InnerEnum ( new FullyQualifiedJavaType ( "Inc" ) ) ; eIncrements . setVisibility ( JavaVisibility . PUBLIC ) ; eIncrements . setStatic ( true ) ; eIncrements . addEnumConstant ( "INC(\"+\")" ) ; eIncrements . addEnumConstant ( "DEC(\"-\")" ) ; commentGenerator . addEnumComment ( eIncrements , introspectedTable ) ; // 生成属性和构造函数
Field fValue = new Field ( "value" , FullyQualifiedJavaType . getStringInstance ( ) ) ; fValue . setVisibility ( JavaVisibility . PRIVATE ) ; fValue . setFinal ( true ) ; commentGenerator . addFieldComment ( fValue , introspectedTable ) ; eIncrements . addField ( fValue ) ; Method mInc = new Method ( "Inc" ) ; mInc . setConstructor ( true ) ; mInc . addBodyLine ( "this.value = value;" ) ; mInc . addParameter ( new Parameter ( FullyQualifiedJavaType . getStringInstance ( ) , "value" ) ) ; commentGenerator . addGeneralMethodComment ( mInc , introspectedTable ) ; FormatTools . addMethodWithBestPosition ( eIncrements , mInc ) ; Method mValue = JavaElementGeneratorTools . generateGetterMethod ( fValue ) ; commentGenerator . addGeneralMethodComment ( mValue , introspectedTable ) ; FormatTools . addMethodWithBestPosition ( eIncrements , mValue ) ; return eIncrements ;


signature:
public class IncrementsPlugin { /** * 有Selective代码生成
 * @ param element */
private void generatedWithSelective ( XmlElement element , IntrospectedTable introspectedTable , boolean hasPrefix ) { } }

implementation:
if ( this . support ( ) ) { // 查找 set - > if - > text
List < XmlElement > sets = XmlElementTools . findXmlElements ( element , "set" ) ; if ( sets . size ( ) > 0 ) { List < XmlElement > ifs = XmlElementTools . findXmlElements ( sets . get ( 0 ) , "if" ) ; if ( ifs . size ( ) > 0 ) { for ( XmlElement xmlElement : ifs ) { // 下面为if的text节点
List < Element > textEles = xmlElement . getElements ( ) ; TextElement textEle = ( TextElement ) textEles . get ( 0 ) ; String [ ] strs = textEle . getContent ( ) . split ( "=" ) ; String columnName = strs [ 0 ] . trim ( ) ; IntrospectedColumn introspectedColumn = IntrospectedTableTools . safeGetColumn ( introspectedTable , columnName ) ; // 查找是否需要进行增量操作
List < Element > incrementEles = PluginTools . getHook ( IIncrementsPluginHook . class ) . incrementSetElementGenerated ( introspectedColumn , hasPrefix ? "record." : null , true ) ; if ( ! incrementEles . isEmpty ( ) ) { xmlElement . getElements ( ) . clear ( ) ; xmlElement . getElements ( ) . addAll ( incrementEles ) ; } } } } }


signature:
public class IncrementsPlugin { /** * 无Selective代码生成
 * @ param xmlElement
 * @ param introspectedTable
 * @ param hasPrefix */
private void generatedWithoutSelective ( XmlElement xmlElement , IntrospectedTable introspectedTable , boolean hasPrefix ) { } }

implementation:
if ( this . support ( ) ) { List < Element > newEles = new ArrayList < > ( ) ; for ( Element ele : xmlElement . getElements ( ) ) { // 找到text节点且格式为 set xx = xx 或者 xx = xx
if ( ele instanceof TextElement ) { String text = ( ( TextElement ) ele ) . getContent ( ) . trim ( ) ; if ( text . matches ( "(^set\\s)?\\S+\\s?=.*" ) ) { // 清理 set 操作
text = text . replaceFirst ( "^set\\s" , "" ) . trim ( ) ; String columnName = text . split ( "=" ) [ 0 ] . trim ( ) ; IntrospectedColumn introspectedColumn = IntrospectedTableTools . safeGetColumn ( introspectedTable , columnName ) ; // 查找判断是否需要进行节点替换
List < Element > incrementEles = PluginTools . getHook ( IIncrementsPluginHook . class ) . incrementSetElementGenerated ( introspectedColumn , hasPrefix ? "record." : null , text . endsWith ( "," ) ) ; if ( ! incrementEles . isEmpty ( ) ) { newEles . addAll ( incrementEles ) ; continue ; } } } newEles . add ( ele ) ; } // 替换节点
xmlElement . getElements ( ) . clear ( ) ; xmlElement . getElements ( ) . addAll ( newEles ) ; }


signature:
public class IncrementsPlugin { /** * 获取INC Enum
 * @ param builderCls
 * @ return */
private FullyQualifiedJavaType getIncEnum ( InnerClass builderCls , IntrospectedTable introspectedTable ) { } }

implementation: try { return new FullyQualifiedJavaType ( BeanUtils . getProperty ( this . incEnumBuilder . getType ( ) , "baseShortName" ) . toString ( ) + "." + this . incEnum . getType ( ) . getShortName ( ) ) ; } catch ( Exception e ) { logger . error ( "获取Inc enum 失败！" , e ) ; } return null ;


signature:
public class IncrementsPlugin { /** * 判断是否为需要进行增量操作的column
 * @ param searchColumn
 * @ return */
private boolean supportColumn ( IntrospectedColumn searchColumn ) { } }

implementation: for ( IntrospectedColumn column : this . incColumns ) { if ( column . getActualColumnName ( ) . equals ( searchColumn . getActualColumnName ( ) ) ) { return true ; } } return false ;


signature:
public class SelectOneByExamplePlugin { /** * Java Client Methods 生成
 * 具体执行顺序 http : / / www . mybatis . org / generator / reference / pluggingIn . html
 * @ param method
 * @ param interfaze
 * @ param introspectedTable
 * @ return */
@ Override public boolean clientSelectByExampleWithBLOBsMethodGenerated ( Method method , Interface interfaze , IntrospectedTable introspectedTable ) { } }

implementation:
// 方法生成 selectOneByExample
Method selectOneMethod = JavaElementGeneratorTools . generateMethod ( METHOD_SELECT_ONE_BY_EXAMPLE_WITH_BLOBS , JavaVisibility . DEFAULT , JavaElementGeneratorTools . getModelTypeWithBLOBs ( introspectedTable ) , new Parameter ( new FullyQualifiedJavaType ( introspectedTable . getExampleType ( ) ) , "example" ) ) ; commentGenerator . addGeneralMethodComment ( selectOneMethod , introspectedTable ) ; // hook
if ( PluginTools . getHook ( ISelectOneByExamplePluginHook . class ) . clientSelectOneByExampleWithBLOBsMethodGenerated ( selectOneMethod , interfaze , introspectedTable ) ) { // interface 增加方法
FormatTools . addMethodWithBestPosition ( interfaze , selectOneMethod ) ; logger . debug ( "itfsw(查询单条数据插件):" + interfaze . getType ( ) . getShortName ( ) + "增加selectOneByExampleWithBLOBs方法。" ) ; } return super . clientSelectByExampleWithBLOBsMethodGenerated ( method , interfaze , introspectedTable ) ;


signature:
public class SelectOneByExamplePlugin { /** * Java Client Methods 生成
 * 具体执行顺序 http : / / www . mybatis . org / generator / reference / pluggingIn . html
 * @ param method
 * @ param interfaze
 * @ param introspectedTable
 * @ return */
@ Override public boolean clientSelectByExampleWithoutBLOBsMethodGenerated ( Method method , Interface interfaze , IntrospectedTable introspectedTable ) { } }

implementation:
// 方法生成 selectOneByExample
Method selectOneMethod = JavaElementGeneratorTools . generateMethod ( METHOD_SELECT_ONE_BY_EXAMPLE , JavaVisibility . DEFAULT , JavaElementGeneratorTools . getModelTypeWithoutBLOBs ( introspectedTable ) , new Parameter ( new FullyQualifiedJavaType ( introspectedTable . getExampleType ( ) ) , "example" ) ) ; commentGenerator . addGeneralMethodComment ( selectOneMethod , introspectedTable ) ; // hook
if ( PluginTools . getHook ( ISelectOneByExamplePluginHook . class ) . clientSelectOneByExampleWithoutBLOBsMethodGenerated ( selectOneMethod , interfaze , introspectedTable ) ) { // interface 增加方法
FormatTools . addMethodWithBestPosition ( interfaze , selectOneMethod ) ; logger . debug ( "itfsw(查询单条数据插件):" + interfaze . getType ( ) . getShortName ( ) + "增加selectOneByExample方法。" ) ; } return super . clientSelectByExampleWithoutBLOBsMethodGenerated ( selectOneMethod , interfaze , introspectedTable ) ;


signature:
public class SelectOneByExamplePlugin { /** * 具体执行顺序 http : / / www . mybatis . org / generator / reference / pluggingIn . html
 * @ param element
 * @ param introspectedTable
 * @ return */
@ Override public boolean sqlMapSelectByExampleWithoutBLOBsElementGenerated ( XmlElement element , IntrospectedTable introspectedTable ) { } }

implementation:
// - - - - - selectOneByExample - - - - -
// 生成查询语句
XmlElement selectOneElement = new XmlElement ( "select" ) ; // 添加注释 ( ! ! ! 必须添加注释 , overwrite覆盖生成时 , @ see XmlFileMergerJaxp . isGeneratedNode会去判断注释中是否存在OLD _ ELEMENT _ TAGS中的一点 , 例子 : @ mbg . generated )
commentGenerator . addComment ( selectOneElement ) ; // 添加ID
selectOneElement . addAttribute ( new Attribute ( "id" , METHOD_SELECT_ONE_BY_EXAMPLE ) ) ; // 添加返回类型
selectOneElement . addAttribute ( new Attribute ( "resultMap" , introspectedTable . getBaseResultMapId ( ) ) ) ; // 添加参数类型
selectOneElement . addAttribute ( new Attribute ( "parameterType" , introspectedTable . getExampleType ( ) ) ) ; selectOneElement . addElement ( new TextElement ( "select" ) ) ; StringBuilder sb = new StringBuilder ( ) ; if ( stringHasValue ( introspectedTable . getSelectByExampleQueryId ( ) ) ) { sb . append ( '\'' ) ; sb . append ( introspectedTable . getSelectByExampleQueryId ( ) ) ; sb . append ( "' as QUERYID," ) ; selectOneElement . addElement ( new TextElement ( sb . toString ( ) ) ) ; } selectOneElement . addElement ( XmlElementGeneratorTools . getBaseColumnListElement ( introspectedTable ) ) ; sb . setLength ( 0 ) ; sb . append ( "from " ) ; sb . append ( introspectedTable . getAliasedFullyQualifiedTableNameAtRuntime ( ) ) ; selectOneElement . addElement ( new TextElement ( sb . toString ( ) ) ) ; selectOneElement . addElement ( XmlElementGeneratorTools . getExampleIncludeElement ( introspectedTable ) ) ; XmlElement ifElement = new XmlElement ( "if" ) ; ifElement . addAttribute ( new Attribute ( "test" , "orderByClause != null" ) ) ; // $ NON - NLS - 2 $
ifElement . addElement ( new TextElement ( "order by ${orderByClause}" ) ) ; selectOneElement . addElement ( ifElement ) ; // 只查询一条
selectOneElement . addElement ( new TextElement ( "limit 1" ) ) ; this . selectOneByExampleEle = selectOneElement ; return super . sqlMapSelectByExampleWithoutBLOBsElementGenerated ( element , introspectedTable ) ;


signature:
public class SelectOneByExamplePlugin { /** * 具体执行顺序 http : / / www . mybatis . org / generator / reference / pluggingIn . html
 * @ param element
 * @ param introspectedTable
 * @ return */
@ Override public boolean sqlMapSelectByExampleWithBLOBsElementGenerated ( XmlElement element , IntrospectedTable introspectedTable ) { } }

implementation:
// 生成查询语句
XmlElement selectOneWithBLOBsElement = new XmlElement ( "select" ) ; // 添加注释 ( ! ! ! 必须添加注释 , overwrite覆盖生成时 , @ see XmlFileMergerJaxp . isGeneratedNode会去判断注释中是否存在OLD _ ELEMENT _ TAGS中的一点 , 例子 : @ mbg . generated )
commentGenerator . addComment ( selectOneWithBLOBsElement ) ; // 添加ID
selectOneWithBLOBsElement . addAttribute ( new Attribute ( "id" , METHOD_SELECT_ONE_BY_EXAMPLE_WITH_BLOBS ) ) ; // 添加返回类型
selectOneWithBLOBsElement . addAttribute ( new Attribute ( "resultMap" , introspectedTable . getResultMapWithBLOBsId ( ) ) ) ; // 添加参数类型
selectOneWithBLOBsElement . addAttribute ( new Attribute ( "parameterType" , introspectedTable . getExampleType ( ) ) ) ; // 添加查询SQL
selectOneWithBLOBsElement . addElement ( new TextElement ( "select" ) ) ; StringBuilder sb = new StringBuilder ( ) ; if ( stringHasValue ( introspectedTable . getSelectByExampleQueryId ( ) ) ) { sb . append ( '\'' ) ; sb . append ( introspectedTable . getSelectByExampleQueryId ( ) ) ; sb . append ( "' as QUERYID," ) ; selectOneWithBLOBsElement . addElement ( new TextElement ( sb . toString ( ) ) ) ; } selectOneWithBLOBsElement . addElement ( XmlElementGeneratorTools . getBaseColumnListElement ( introspectedTable ) ) ; selectOneWithBLOBsElement . addElement ( new TextElement ( "," ) ) ; selectOneWithBLOBsElement . addElement ( XmlElementGeneratorTools . getBlobColumnListElement ( introspectedTable ) ) ; sb . setLength ( 0 ) ; sb . append ( "from " ) ; sb . append ( introspectedTable . getAliasedFullyQualifiedTableNameAtRuntime ( ) ) ; selectOneWithBLOBsElement . addElement ( new TextElement ( sb . toString ( ) ) ) ; selectOneWithBLOBsElement . addElement ( XmlElementGeneratorTools . getExampleIncludeElement ( introspectedTable ) ) ; XmlElement ifElement1 = new XmlElement ( "if" ) ; ifElement1 . addAttribute ( new Attribute ( "test" , "orderByClause != null" ) ) ; // $ NON - NLS - 2 $
ifElement1 . addElement ( new TextElement ( "order by ${orderByClause}" ) ) ; selectOneWithBLOBsElement . addElement ( ifElement1 ) ; // 只查询一条
selectOneWithBLOBsElement . addElement ( new TextElement ( "limit 1" ) ) ; this . selectOneByExampleWithBLOBsEle = selectOneWithBLOBsElement ; return super . sqlMapSelectByExampleWithBLOBsElementGenerated ( element , introspectedTable ) ;


signature:
public class SelectOneByExamplePlugin { /** * SQL Map Methods 生成
 * 具体执行顺序 http : / / www . mybatis . org / generator / reference / pluggingIn . html
 * @ param document
 * @ param introspectedTable
 * @ return */
@ Override public boolean sqlMapDocumentGenerated ( Document document , IntrospectedTable introspectedTable ) { } }

implementation:
if ( selectOneByExampleEle != null ) { // hook
if ( PluginTools . getHook ( ISelectOneByExamplePluginHook . class ) . sqlMapSelectOneByExampleWithoutBLOBsElementGenerated ( document , selectOneByExampleEle , introspectedTable ) ) { // 添加到根节点
FormatTools . addElementWithBestPosition ( document . getRootElement ( ) , selectOneByExampleEle ) ; logger . debug ( "itfsw(查询单条数据插件):" + introspectedTable . getMyBatis3XmlMapperFileName ( ) + "增加selectOneByExample方法。" ) ; } } if ( selectOneByExampleWithBLOBsEle != null ) { // hook
if ( PluginTools . getHook ( ISelectOneByExamplePluginHook . class ) . sqlMapSelectOneByExampleWithBLOBsElementGenerated ( document , selectOneByExampleWithBLOBsEle , introspectedTable ) ) { // 添加到根节点
FormatTools . addElementWithBestPosition ( document . getRootElement ( ) , selectOneByExampleWithBLOBsEle ) ; logger . debug ( "itfsw(查询单条数据插件):" + introspectedTable . getMyBatis3XmlMapperFileName ( ) + "增加selectOneByExampleWithBLOBs方法。" ) ; } } return true ;


signature:
public class BeanUtils { /** * 设置属性
 * @ param bean
 * @ param name
 * @ param value
 * @ throws NoSuchFieldException
 * @ throws IllegalAccessException */
public static void setProperty ( final Object bean , final String name , final Object value ) throws NoSuchFieldException , IllegalAccessException { } }

implementation: Field field = bean . getClass ( ) . getDeclaredField ( name ) ; field . setAccessible ( true ) ; field . set ( bean , value ) ;


signature:
public class BeanUtils { /** * 获取属性
 * @ param bean
 * @ param name
 * @ return */
public static Object getProperty ( final Object bean , final String name ) throws NoSuchFieldException , IllegalAccessException { } }

implementation: Field field = bean . getClass ( ) . getDeclaredField ( name ) ; field . setAccessible ( true ) ; return field . get ( bean ) ;


signature:
public class BeanUtils { /** * 执行无参方法
 * @ param bean
 * @ param clazz
 * @ param name
 * @ return
 * @ throws NoSuchMethodException
 * @ throws InvocationTargetException
 * @ throws IllegalAccessException */
public static Object invoke ( final Object bean , Class clazz , final String name ) throws NoSuchMethodException , InvocationTargetException , IllegalAccessException { } }

implementation: Method method = clazz . getDeclaredMethod ( name ) ; method . setAccessible ( true ) ; return method . invoke ( bean ) ;


signature:
public class TemplateCommentGenerator { /** * 获取评论
 * @ param map 模板参数
 * @ param node 节点ID
 * @ return */
private String [ ] getComments ( Map < String , Object > map , EnumNode node ) { } }

implementation:
// 1 . 模板引擎解析
try { StringWriter stringWriter = new StringWriter ( ) ; Template template = templates . get ( node ) ; if ( template != null ) { template . process ( map , stringWriter ) ; String comment = stringWriter . toString ( ) ; stringWriter . close ( ) ; // 需要先清理字符串
return comment . replaceFirst ( "^[\\s\\t\\r\\n]*" , "" ) . replaceFirst ( "[\\s\\t\\r\\n]*$" , "" ) . split ( "\n" ) ; } } catch ( Exception e ) { logger . error ( "freemarker 解析失败！" , e ) ; } return null ;


signature:
public class TemplateCommentGenerator { /** * 添加评论
 * @ param javaElement
 * @ param map
 * @ param node */
private void addJavaElementComment ( JavaElement javaElement , Map < String , Object > map , EnumNode node ) { } }

implementation:
// 获取评论
String [ ] comments = getComments ( map , node ) ; if ( comments != null ) { // 去除空评论
if ( comments . length == 1 && ! StringUtility . stringHasValue ( comments [ 0 ] ) ) { return ; } // 添加评论
for ( String comment : comments ) { javaElement . addJavaDocLine ( comment ) ; } }


signature:
public class TemplateCommentGenerator { /** * 添加评论
 * @ param compilationUnit
 * @ param map
 * @ param node */
private void addCompilationUnitComment ( CompilationUnit compilationUnit , Map < String , Object > map , EnumNode node ) { } }

implementation:
// 获取评论
String [ ] comments = getComments ( map , node ) ; if ( comments != null ) { // 去除空评论
if ( comments . length == 1 && ! StringUtility . stringHasValue ( comments [ 0 ] ) ) { return ; } // 添加评论
for ( String comment : comments ) { compilationUnit . addFileCommentLine ( comment ) ; } }


signature:
public class TemplateCommentGenerator { /** * 添加评论
 * @ param xmlElement
 * @ param map
 * @ param node */
private void addXmlElementComment ( XmlElement xmlElement , Map < String , Object > map , EnumNode node ) { } }

implementation:
// 获取评论
String [ ] comments = getComments ( map , node ) ; if ( comments != null ) { // 去除空评论
if ( comments . length == 1 && ! StringUtility . stringHasValue ( comments [ 0 ] ) ) { return ; } // 添加评论
for ( String comment : comments ) { xmlElement . addElement ( new TextElement ( comment ) ) ; } }


signature:
public class TemplateCommentGenerator { /** * Adds properties for this instance from any properties configured in the
 * CommentGenerator configuration .
 * This method will be called before any of the other methods .
 * @ param properties
 * All properties from the configuration */
@ Override public void addConfigurationProperties ( Properties properties ) { } }

implementation: suppressDate = isTrue ( properties . getProperty ( PropertyRegistry . COMMENT_GENERATOR_SUPPRESS_DATE ) ) ; suppressAllComments = isTrue ( properties . getProperty ( PropertyRegistry . COMMENT_GENERATOR_SUPPRESS_ALL_COMMENTS ) ) ;


signature:
public class TemplateCommentGenerator { /** * This method should add a Javadoc comment to the specified field . The field is related to the specified table and
 * is used to hold the value of the specified column .
 * < b > Important : < / b > This method should add a the nonstandard JavaDoc tag " @ mbg . generated " to the comment . Without
 * this tag , the Eclipse based Java merge feature will fail .
 * @ param field
 * the field
 * @ param introspectedTable
 * the introspected table
 * @ param introspectedColumn
 * the introspected column */
@ Override public void addFieldComment ( Field field , IntrospectedTable introspectedTable , IntrospectedColumn introspectedColumn ) { } }

implementation:
Map < String , Object > map = new HashMap < > ( ) ; map . put ( "mgb" , MergeConstants . NEW_ELEMENT_TAG ) ; map . put ( "field" , field ) ; map . put ( "introspectedTable" , introspectedTable ) ; map . put ( "introspectedColumn" , introspectedColumn ) ; // 添加评论
addJavaElementComment ( field , map , EnumNode . ADD_FIELD_COMMENT ) ;


signature:
public class TemplateCommentGenerator { /** * Adds a comment for a model class . The Java code merger should
 * be notified not to delete the entire class in case any manual
 * changes have been made . So this method will always use the
 * " do not delete " annotation .
 * Because of difficulties with the Java file merger , the default implementation
 * of this method should NOT add comments . Comments should only be added if
 * specifically requested by the user ( for example , by enabling table remark comments ) .
 * @ param topLevelClass
 * the top level class
 * @ param introspectedTable
 * the introspected table */
@ Override public void addModelClassComment ( TopLevelClass topLevelClass , IntrospectedTable introspectedTable ) { } }

implementation:
Map < String , Object > map = new HashMap < > ( ) ; map . put ( "mgb" , MergeConstants . NEW_ELEMENT_TAG ) ; map . put ( "topLevelClass" , topLevelClass ) ; map . put ( "introspectedTable" , introspectedTable ) ; // 添加评论
addJavaElementComment ( topLevelClass , map , EnumNode . ADD_MODEL_CLASS_COMMENT ) ;


signature:
public class TemplateCommentGenerator { /** * Adds the inner class comment .
 * @ param innerClass
 * the inner class
 * @ param introspectedTable
 * the introspected table */
@ Override public void addClassComment ( InnerClass innerClass , IntrospectedTable introspectedTable ) { } }

implementation:
if ( innerClass instanceof InnerInterfaceWrapperToInnerClass ) { InnerInterface innerInterface = ( ( InnerInterfaceWrapperToInnerClass ) innerClass ) . getInnerInterface ( ) ; Map < String , Object > map = new HashMap < > ( ) ; map . put ( "mgb" , MergeConstants . NEW_ELEMENT_TAG ) ; map . put ( "innerInterface" , innerInterface ) ; map . put ( "introspectedTable" , introspectedTable ) ; // 添加评论
addJavaElementComment ( innerInterface , map , EnumNode . ADD_INTERFACE_COMMENT ) ; } else { Map < String , Object > map = new HashMap < > ( ) ; map . put ( "mgb" , MergeConstants . NEW_ELEMENT_TAG ) ; map . put ( "innerClass" , innerClass ) ; map . put ( "introspectedTable" , introspectedTable ) ; // 添加评论
addJavaElementComment ( innerClass , map , EnumNode . ADD_CLASS_COMMENT ) ; }


signature:
public class TemplateCommentGenerator { /** * Adds the inner class comment .
 * @ param innerClass
 * the inner class
 * @ param introspectedTable
 * the introspected table
 * @ param markAsDoNotDelete
 * the mark as do not delete */
@ Override public void addClassComment ( InnerClass innerClass , IntrospectedTable introspectedTable , boolean markAsDoNotDelete ) { } }

implementation:
Map < String , Object > map = new HashMap < > ( ) ; map . put ( "mgb" , MergeConstants . NEW_ELEMENT_TAG ) ; map . put ( "innerClass" , innerClass ) ; map . put ( "introspectedTable" , introspectedTable ) ; map . put ( "markAsDoNotDelete" , markAsDoNotDelete ) ; // 添加评论
addJavaElementComment ( innerClass , map , EnumNode . ADD_CLASS_COMMENT ) ;


signature:
public class TemplateCommentGenerator { /** * Adds the enum comment .
 * @ param innerEnum
 * the inner enum
 * @ param introspectedTable
 * the introspected table */
@ Override public void addEnumComment ( InnerEnum innerEnum , IntrospectedTable introspectedTable ) { } }

implementation:
Map < String , Object > map = new HashMap < > ( ) ; map . put ( "mgb" , MergeConstants . NEW_ELEMENT_TAG ) ; map . put ( "innerEnum" , innerEnum ) ; map . put ( "introspectedTable" , introspectedTable ) ; // 添加评论
addJavaElementComment ( innerEnum , map , EnumNode . ADD_ENUM_COMMENT ) ;


signature:
public class TemplateCommentGenerator { /** * Adds the getter comment .
 * @ param method
 * the method
 * @ param introspectedTable
 * the introspected table
 * @ param introspectedColumn
 * the introspected column */
@ Override public void addGetterComment ( Method method , IntrospectedTable introspectedTable , IntrospectedColumn introspectedColumn ) { } }

implementation:
Map < String , Object > map = new HashMap < > ( ) ; map . put ( "mgb" , MergeConstants . NEW_ELEMENT_TAG ) ; map . put ( "method" , method ) ; map . put ( "introspectedTable" , introspectedTable ) ; map . put ( "introspectedColumn" , introspectedColumn ) ; // 添加评论
addJavaElementComment ( method , map , EnumNode . ADD_GETTER_COMMENT ) ;


signature:
public class TemplateCommentGenerator { /** * Adds the general method comment .
 * @ param method
 * the method
 * @ param introspectedTable
 * the introspected table */
@ Override public void addGeneralMethodComment ( Method method , IntrospectedTable introspectedTable ) { } }

implementation:
Map < String , Object > map = new HashMap < > ( ) ; map . put ( "mgb" , MergeConstants . NEW_ELEMENT_TAG ) ; map . put ( "method" , method ) ; map . put ( "introspectedTable" , introspectedTable ) ; // 添加评论
addJavaElementComment ( method , map , EnumNode . ADD_GENERAL_METHOD_COMMENT ) ;


signature:
public class TemplateCommentGenerator { /** * This method is called to add a file level comment to a generated java file . This method could be used to add a
 * general file comment ( such as a copyright notice ) . However , note that the Java file merge function in Eclipse
 * does not deal with this comment . If you run the generator repeatedly , you will only retain the comment from the
 * initial run .
 * The default implementation does nothing .
 * @ param compilationUnit
 * the compilation unit */
@ Override public void addJavaFileComment ( CompilationUnit compilationUnit ) { } }

implementation:
Map < String , Object > map = new HashMap < > ( ) ; map . put ( "mgb" , MergeConstants . NEW_ELEMENT_TAG ) ; map . put ( "compilationUnit" , compilationUnit ) ; // 添加评论
addCompilationUnitComment ( compilationUnit , map , EnumNode . ADD_JAVA_FILE_COMMENT ) ;


signature:
public class TemplateCommentGenerator { /** * This method should add a suitable comment as a child element of the specified xmlElement to warn users that the
 * element was generated and is subject to regeneration .
 * @ param xmlElement
 * the xml element */
@ Override public void addComment ( XmlElement xmlElement ) { } }

implementation:
Map < String , Object > map = new HashMap < > ( ) ; map . put ( "mgb" , MergeConstants . NEW_ELEMENT_TAG ) ; map . put ( "xmlElement" , xmlElement ) ; // 添加评论
addXmlElementComment ( xmlElement , map , EnumNode . ADD_COMMENT ) ;


signature:
public class TemplateCommentGenerator { /** * This method is called to add a comment as the first child of the root element . This method could be used to add a
 * general file comment ( such as a copyright notice ) . However , note that the XML file merge function does not deal
 * with this comment . If you run the generator repeatedly , you will only retain the comment from the initial run .
 * The default implementation does nothing .
 * @ param rootElement
 * the root element */
@ Override public void addRootComment ( XmlElement rootElement ) { } }

implementation:
Map < String , Object > map = new HashMap < > ( ) ; map . put ( "mgb" , MergeConstants . NEW_ELEMENT_TAG ) ; map . put ( "rootElement" , rootElement ) ; // 添加评论
addXmlElementComment ( rootElement , map , EnumNode . ADD_ROOT_COMMENT ) ;