MyBatis-Generator源码学习及修改

MyBatis-Generator源码学习及修改

所需jar包:generator-mybatis-generator-1.3.2.jar

背景:

公司数据库的做了分库,查询时候,必须修改customerId,否则查询效率会变低,数据库表60+,新工程每个表几乎都加了新的字段,需要生成新的mybatis的mapper文件。

方案:

打算采用MyBatis-Generator插件的方式生成实体类,接口以及xml。

需求:

生成的sql和接口,对于改查来说,不仅要生成主键的查询,还有携带有customerId字段,提升查询速率。

原有的MyBatis-Generator插件不满足条件,MyBatis-Generator插件可以生成依赖于主键的查询select,依赖于主键的选择性修改update。故需要修改MyBatis-Generator插件中的代码。

目标:

通过修改源码的方式,生成达到目的mybatis的mapper

解决方案:

下载所需的MyBatis-Generator插件的源码包,解压后的得到

在这里插入图片描述

这里只需要修改core中的文件即可

在这里插入图片描述

太熟悉了,简简单单的maven项目,直接动手撸代码,目标很明确,selectByPrimaryKey和updateByPrimaryKey修改为满足条件的sql语句(及携带customerId)

xml生成代码位置:

在这里插入图片描述

标红处为生成xml的java代码

原理:

这几个类通过拼接StringBuilder.append()方法,最后通过解析元素的方式生成,可以理解为xml解析。

xml的生成代码如何修改:

这里修改mapper.xml中selectByPrimaryKey()方法,updateByPrimaryKey()同理

    @Override
    public void addElements(XmlElement parentElement) {
        XmlElement answer = new XmlElement("select"); //$NON-NLS-1$

        answer.addAttribute(new Attribute(
                "id", introspectedTable.getSelectByPrimaryKeyStatementId())); //$NON-NLS-1$
        if (introspectedTable.getRules().generateResultMapWithBLOBs()) {
            answer.addAttribute(new Attribute("resultMap", //$NON-NLS-1$
                    introspectedTable.getResultMapWithBLOBsId()));
        } else {
            answer.addAttribute(new Attribute("resultMap", //$NON-NLS-1$
                    introspectedTable.getBaseResultMapId()));
        }

        String parameterType;
        if (introspectedTable.getRules().generatePrimaryKeyClass()) {
            parameterType = 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) {
                parameterType = "map"; //$NON-NLS-1$
            } else {
                parameterType = introspectedTable.getPrimaryKeyColumns().get(0)
                        .getFullyQualifiedJavaType().toString();
            }
        }

        answer.addAttribute(new Attribute("parameterType", //$NON-NLS-1$
                parameterType));

        context.getCommentGenerator().addComment(answer);

        StringBuilder sb = new StringBuilder();
        sb.append("select "); //$NON-NLS-1$

        if (stringHasValue(introspectedTable
                .getSelectByPrimaryKeyQueryId())) {
            sb.append('\'');
            sb.append(introspectedTable.getSelectByPrimaryKeyQueryId());
            sb.append("' as QUERYID,"); //$NON-NLS-1$
        }
        answer.addElement(new TextElement(sb.toString()));
        answer.addElement(getBaseColumnListElement());
        if (introspectedTable.hasBLOBColumns()) {
            answer.addElement(new TextElement(",")); //$NON-NLS-1$
            answer.addElement(getBlobColumnListElement());
        }

        sb.setLength(0);
        sb.append("from "); //$NON-NLS-1$
        sb.append(introspectedTable
                .getAliasedFullyQualifiedTableNameAtRuntime());
        answer.addElement(new TextElement(sb.toString()));

        boolean and = false;
        for (IntrospectedColumn introspectedColumn : introspectedTable
                .getPrimaryKeyColumns()) {
            sb.setLength(0);
            if (and) {
                sb.append("  and "); //$NON-NLS-1$
            } else {
                sb.append("where "); //$NON-NLS-1$
                and = true;
            }
//这里为生成sql的最后位置
            sb.append(MyBatis3FormattingUtilities
                    .getAliasedEscapedColumnName(introspectedColumn));
            sb.append(" = "); //$NON-NLS-1$
            //原来的代码是            sb.append(MyBatis3FormattingUtilities.getParameterClause(introspectedColumn));
            sb.append(MyBatis3FormattingUtilities
                    .getParameterClause1(introspectedColumn));
            answer.addElement(new TextElement(sb.toString()));
        }

        if (context.getPlugins()
                .sqlMapSelectByPrimaryKeyElementGenerated(answer,
                        introspectedTable)) {
            parentElement.addElement(answer);
        }
    }

在这里插入图片描述

修改核心拼接代码

public static String getParameterClause(
        IntrospectedColumn introspectedColumn) {
    return getParameterClause(introspectedColumn, null);
}
public static String getParameterClause1(
        IntrospectedColumn introspectedColumn) {
    return getParameterClause1(introspectedColumn, null);
}
public static String getParameterClause1(
        IntrospectedColumn introspectedColumn, String prefix) {
    StringBuilder sb = new StringBuilder();

    sb.append("#{"); //$NON-NLS-1$
    sb.append(introspectedColumn.getJavaProperty(prefix));
    sb.append(",jdbcType="); //$NON-NLS-1$
    sb.append(introspectedColumn.getJdbcTypeName());

    if (stringHasValue(introspectedColumn.getTypeHandler())) {
        sb.append(",typeHandler="); //$NON-NLS-1$
        sb.append(introspectedColumn.getTypeHandler());
    }

    sb.append('}');
    sb.append(" and CUSTOMER_ID = #{customerId,jdbcType=VARCHAR}");

    return sb.toString();
}
public static String getParameterClause(
        IntrospectedColumn introspectedColumn, String prefix) {
    StringBuilder sb = new StringBuilder();

    sb.append("#{"); //$NON-NLS-1$
    sb.append(introspectedColumn.getJavaProperty(prefix));
    sb.append(",jdbcType="); //$NON-NLS-1$
    sb.append(introspectedColumn.getJdbcTypeName());

    if (stringHasValue(introspectedColumn.getTypeHandler())) {
        sb.append(",typeHandler="); //$NON-NLS-1$
        sb.append(introspectedColumn.getTypeHandler());
    }

    sb.append('}');

    return sb.toString();
}

注意:

getParameterClause()和getParameterClause()为源代码

getParameterClause1()和getParameterClause1()为源代码

直接复制代码并在最后加入sb.append(" and CUSTOMER_ID = #{customerId,jdbcType=VARCHAR}");

同理修改mapper.xml中updateByPrimaryKey()方法也是如此,可复用

生成之后效果图

在这里插入图片描述

mybatis接口的修改:

原有java接口代码

MalltTrade selectByPrimaryKey(String tradeId);     

需要生成

MalltTrade selectByPrimaryKey(Map map);      

这里为生成接口代码的位置

在这里插入图片描述

读代码:

在这里插入图片描述

if中条件为true时:单主键,false时:联合主键。

简单点先看true

第二行代码,FullyQualifiedJavaType要映射我们所需的参数,及MalltTrade selectByPrimaryKey(Map map);方法的参数,查看他的类型

在这里插入图片描述

好烦!

Map的包是import java.util.Map;

和Map不是同一个包下的,这里改动较大,故采用另一种方式修改这个接口。

java的io流处理

直接上代码:

public void handle(String filename){
    RandomAccessFile raf = null;
    try {
        raf = new RandomAccessFile(filename, "rw");
        String line = null;
        long lastPoint = 0; //记住上一次的偏移量
        int i=0;
        int m=3;
        StringBuffer stringBuffer = new StringBuffer();
        while ((line = raf.readLine()) != null) {

            final long ponit = raf.getFilePointer();
            if(line.contains("selectByPrimaryKey")){
                //不可这里进行string的修改,他这个是边读边写,偏移量是有问题的,例如多一个字符少一个字符都会引起文件的串行,不信的可以试试。
                raf.seek(lastPoint);
                raf.writeBytes(line);

            }
            //导入Map,import
            if (line.contains("import com.sitech.mios.modules.order.dao.po")){
                System.out.println(i);
                line=line+"\nimport java.util.Map;\n";
            }
            //修改参数,为什么不用replace,因为replace对于联合主键来说他生成的形式是MalltDataDictionary selectByPrimaryKey(@Param("xxx") xxx,@Param("yyy ") xxx); 忘记保存了,可自己尝试生成一下,括号太多,使用正则太麻烦,反正我写不出来这个正则,h 
            if(line.contains("selectByPrimaryKey")){
                String[] split = line.split("\\(");
                String str=split[0]+"(Map map);       ";//line.replace(split[1], "Map map);       ");
                line=str;
            }
            stringBuffer.append(line+"\n");
            lastPoint = ponit;
            i++;
        }
        String s = stringBuffer.toString();
        //目标文件位置,与上方一致
        File file = new File(filename);
        FileWriter fout = new FileWriter(file);// 创建文件输出流
        fout.write(s);
        fout.close();// 关闭输出流

    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            raf.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

String filename为mapper.java的位置

拿下拿下,完美收工!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值