myBatis SqlMapper 和 Java 文件自由合并

本文介绍了如何在使用MyBatis Generator时,有效地合并生成的sqlMapper XML文件和Java Model及Client文件。通过自定义插件方法,实现了XML文件的节点去重和Java文件的导入、注解、字段、方法更新。同时讨论了在对象完全生成后不保存文件,自行处理保存的方式,提供了多种灵活的文件合并策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在使用 MyBatis-generator 生成代码时,总有各种场景需要合并生成的 sqlMapper XML文件和 生成的Model 及 Client 文件。

通过参考各种文档和不断的一点点实验总结了以下方法:

1.XML 文件:mybatis-generator 本身支持融合,但是在融合的时候,老的相同的节点不会被删除,导致生成后的文件节点重复。所以在插件的 sqlMapDocumentGenerated 方法中 先把原来的XML文件读出为XML Document,然后与生成的新的 Document 进行比较,删除老的Document中与新Document相同的节点,然后再保存回文件。mybatis 进行融合的时候老文件已经没有自动生成的节点了,所以融合以后是最终想要的文件。

2.Java文件:mybatis-generator 不支持 java文件的融合,搜索到的资料,很多都是修改源码,但这样就不通用了。我的处理方法是在相应的插件方法中(比如  clientGenerated, modelBaseRecordClassGenerated)把老的文件使用 JavaParse 解析出来,然后逐一与新的 Interface 或 TopLevelClass 对比,把不存在新生成对象中的 import, annotation, field, method 等添加到新的对象中去。

3.还有另一个种方法,就是在对象完全生成以后的相应插件方法中返回 false,这样mybatis-generator 就不会保存文件,我们自己处理要保存的文件。这样方法就比较多样了:比如还是像上面那样处理,然后 getFormatContent ,自己保存;又或者在文件中加上某个明显的标记,把老文件中属于自定义的部分用正则拿出来,然后放到新对象的 getFormatContent 返回字符串的后面。

 

代码:

XML 的融合:

    @Override
    public boolean sqlMapDocumentGenerated(org.mybatis.generator.api.dom.xml.Document document,
                                           IntrospectedTable introspectedTable) {

        this.document = document;
        String targetPackage = super.context.getSqlMapGeneratorConfiguration().getTargetPackage();
        String targetProject = super.context.getSqlMapGeneratorConfiguration().getTargetProject();
        try
        {
            File directory = shellCallback.getDirectory(targetProject, targetPackage);
            String fileName = introspectedTable.getTableConfiguration().getDomainObjectName() + "Mapper.xml";
            File xmlFile = new File(directory, fileName);
            if (!directory.exists() || !xmlFile.exists()) {
                return true;
            }

            // old exist xml nodes
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            dbf.setValidating(false);
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document doc = db.parse(new FileInputStream(xmlFile));
            org.w3c.dom.Element rootElement = doc.getDocumentElement();
            NodeList list = rootElement.getChildNodes();

            // new xml nodes
            List<Element> elements = document.getRootElement().getElements();

            // match pattern
            Pattern p = Pattern.compile("<(\\w+)\\s+id=\"(\\w+)\"");

            List<Node> oldDocumentWillRemoveElements = new ArrayList<Node>();

            boolean findSameNode = false;
            // traverse new nodes to compare old nodes to filter
            for (Iterator<Element> elementIt = elements.iterator(); elementIt.hasNext(); ) {
                findSameNode = false;
                String newNodeName = "";
                String NewIdValue = "";
                Element element = elementIt.next();
                Matcher m = p.matcher(element.getFormattedContent(0));
                if (m.find()) {
                    newNodeName = m.group(1);
                    NewIdValue = m.group(2);
                }

                for (int i = 0; i < list.getLength(); i++) {
                    Node node = list.item(i);
                    if (node.getNodeType() == Node.ELEMENT_NODE) {
                        if (newNodeName.equals(node.getNodeName())) {
                            NamedNodeMap attr = node.getAttributes();
                            for (int j = 0; j < attr.getLength(); j++) {
                                Node attrNode = attr.item(j);
                                if (attrNode.getNodeName().equals("id") && attrNode.getNodeValue().equals(NewIdValue)) {
                                    //elementIt.remove();
                                    oldDocumentWillRemoveElements.add(node);
                                    findSameNode = true;
                                    break;
                                }
                            }
                            if (findSameNode == true)
                                break;
                        }
                    }
                }
            }

            // remove old xml nodes that exist in new xml
            for(Node n : oldDocumentWillRemoveElements){
                rootElement.removeChild(n);
            }
            System.out.println("deleted same nodes from old document:" + oldDocumentWillRemoveElements.size());

            // save old xml document
            //TransformerFactory tff = TransformerFactory.newInstance();
            //Transformer tf = tff.newTransformer();
            //tf.setOutputProperty(OutputKeys.INDENT, "no");
            //tf.transform(new DOMSource(doc), new StreamResult(xmlFile));

            DomWriter dw = new DomWriter();
            String s = dw.toString(doc);
            FileOutputStream fos = new FileOutputStream(xmlFile, false);
            OutputStreamWriter osw;

                osw = new OutputStreamWriter(fos, "UTF-8");


            BufferedWriter bw = new BufferedWriter(osw);
            bw.write(s);
            bw.close();
            System.out.println("saved old document");
        }
        catch (Exception ex){
            System.out.println("【Error】");
            ex.printStackTrace();
        }
    }

 

java 文件的融合:

    @Override
    public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        String targetPackage = super.context.getJavaModelGeneratorConfiguration().getTargetPackage();
        String targetProject = super.context.getJavaModelGeneratorConfiguration().getTargetProject();
        try {
            File directory = shellCallback.getDirectory(targetProject, targetPackage);
            String fileName = introspectedTable.getTableConfiguration().getDomainObjectName() + ".java";
            File javaFile = new File(directory, fileName);

            CompilationUnit oldCU = JavaParser.parse(javaFile);
            NodeList<ImportDeclaration> oldImports = oldCU.getImports();

            // imports
            AddImports(oldImports, topLevelClass);

            NodeList<TypeDeclaration<?>> oldTypes = oldCU.getTypes();

            // types
            for (int i=0; i<oldTypes.size();i++){
                TypeDeclaration oldType = oldTypes.get(i);

                // class annotations
                NodeList<AnnotationExpr> oldTypeAnn = oldType.getAnnotations();
                AddAnnotations(oldTypeAnn, topLevelClass);

                // fields
                List<FieldDeclaration> oldTypeFields = oldType.getFields();
                List<Field> newFields = topLevelClass.getFields();
                AddFields(oldTypeFields, newFields, topLevelClass);

                // methos
                List<MethodDeclaration> oldTypeMethods = oldType.getMethods();
                AddMethods(oldTypeMethods, topLevelClass);

            }
        }
        catch (Exception e){
            e.printStackTrace();
        }
        return true;
    }

    @Override
    public boolean clientGenerated(Interface interfaze, TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        String targetPackage = super.context.getJavaClientGeneratorConfiguration().getTargetPackage();
        String targetProject = super.context.getJavaClientGeneratorConfiguration().getTargetProject();
        try {
            File directory = shellCallback.getDirectory(targetProject, targetPackage);
            String fileName = introspectedTable.getTableConfiguration().getDomainObjectName() + "Mapper.java";
            File javaFile = new File(directory, fileName);

            CompilationUnit oldCU = JavaParser.parse(javaFile);
            NodeList<ImportDeclaration> oldImports = oldCU.getImports();

            // imports
            AddImports(oldImports, interfaze);

            NodeList<TypeDeclaration<?>> oldTypes = oldCU.getTypes();
            // types
            for (int i=0; i<oldTypes.size();i++){
                TypeDeclaration oldType = oldTypes.get(i);

                // annotations
                NodeList<AnnotationExpr> oldTypeAnn = oldType.getAnnotations();
                AddAnnotations(oldTypeAnn, interfaze);

                // fields
                List<FieldDeclaration> oldTypeFields = oldType.getFields();
                List<Field> newFields = interfaze.getFields();
                AddFields(oldTypeFields, newFields, interfaze);

                // methos
                List<MethodDeclaration> oldTypeMethods = oldType.getMethods();
                AddMethods(oldTypeMethods, interfaze);
            }
        }
        catch (Exception e){
            e.printStackTrace();
        }

            return true;
    }

    private void SetModifiers(EnumSet<Modifier> modifiers, JavaElement element){
        Iterator<Modifier> it = modifiers.iterator();
        while (it.hasNext()) {
            Modifier modifier = it.next();
            switch (modifier){
                case FINAL:
                    element.setFinal(true);
                    break;
                case STATIC:
                    element.setStatic(true);
                    break;
                case VOLATILE:
                    if(element instanceof Field){
                        Field field = (Field)element;
                        field.setVolatile(true);
                    }
                    break;
                case TRANSIENT:
                    if(element instanceof Field){
                        Field field = (Field)element;
                        field.setTransient(true);
                    }
                    break;
                case NATIVE:
                    if(element instanceof Method){
                        Method method = (Method)element;
                        method.setNative(true);
                    }
                    break;
                case SYNCHRONIZED:
                    if(element instanceof Method){
                        Method method = (Method)element;
                        method.setSynchronized(true);
                    }
                    break;
                case PUBLIC:
                    element.setVisibility(JavaVisibility.PUBLIC);
                    break;
                case DEFAULT:
                    if(element instanceof Method){
                        Method method = (Method)element;
                        method.setDefault(true);
                    }
                    break;
                case PRIVATE:
                    element.setVisibility(JavaVisibility.PRIVATE);
                    break;
                case PROTECTED:
                    element.setVisibility(JavaVisibility.PROTECTED);
                    break;
            }
        }
    }

    private void AddAnnotations( NodeList<AnnotationExpr> oldTypeAnn, JavaElement element){
        if(oldTypeAnn == null || oldTypeAnn.size() < 1){
            return;
        }

        boolean isExist = false;
        for(int j = 0; j < oldTypeAnn.size(); j++){
            AnnotationExpr ota = oldTypeAnn.get(j);
            isExist = false;
            for(java.lang.String na : element.getAnnotations()){
                if(ota.toString().equals(na)) {
                    isExist = true;
                    break;
                }
            }

            if(!isExist){
                element.addAnnotation(ota.toString());
            }
        }
    }

    private void AddFields(List<FieldDeclaration> oldTypeFields, List<Field> newFields, org.mybatis.generator.api.dom.java.CompilationUnit cu){
        boolean isExist = false;
        for(int j =0;j<oldTypeFields.size();j++){
            FieldDeclaration of = oldTypeFields.get(j);
            isExist = false;
            for (Field f : newFields){
                if(of.getVariables().get(0).getName().toString().equals(f.getName())) {
                    isExist = true;
                    break;
                }
            }

            if(!isExist){
                Field nf = new Field();
                nf.setName(of.getVariables().get(0).getName().toString());
                nf.setType(new FullyQualifiedJavaType(of.getElementType().toString()));
                /* javaParser's  Type can not get the FullyQualified Name, so it must import the type in import part, and use the type shortname in code.*/
                SetModifiers(of.getModifiers(), nf);
                if(of.getVariables().get(0).getInitializer().isPresent()) {
                    nf.setInitializationString(of.getVariables().get(0).getInitializer().get().toString());
                }

                NodeList<AnnotationExpr> fas = of.getAnnotations();
                for (int k = 0; k < fas.size();k++){
                    AnnotationExpr ae = fas.get(k);
                    nf.addAnnotation(ae.toString());
                }

                if(cu instanceof Interface ){
                    Interface interfaze = (Interface)cu;
                    interfaze.addField(nf);
                }
                else if (cu instanceof  TopLevelClass){
                    TopLevelClass topLevelClass = (TopLevelClass)cu;
                    topLevelClass.addField(nf);
                }
            }
        }
    }

    private void AddImports(NodeList<ImportDeclaration> oldImports, org.mybatis.generator.api.dom.java.CompilationUnit cu){
        boolean isExist = false;
        Set<String> staticImports = cu.getStaticImports();
        Set<FullyQualifiedJavaType> imports = cu.getImportedTypes();

        for(int i =0; i < oldImports.size();i++){
            ImportDeclaration oldImport = oldImports.get(i);
            String oi = oldImport.getNameAsString() + (oldImport.isAsterisk() ? ".*" :"");
            isExist = false;

            if(oldImport.isStatic()){
                for(String nt: staticImports){
                    if (oi.equals(nt)){
                        isExist = true;
                        break;
                    }
                }
            }else {
                for(FullyQualifiedJavaType nt: imports){
                    if (oi.equals(nt.getFullyQualifiedName())){
                        isExist = true;
                        break;
                    }
                }
            }

            if(!isExist){
                if(oldImport.isStatic()){
                    cu.addStaticImport(oi);
                } else {
                    cu.addImportedType(new FullyQualifiedJavaType(oi));
                }
            }
        }
    }

    private void AddMethods(List<MethodDeclaration> oldTypeMethods, org.mybatis.generator.api.dom.java.CompilationUnit cu){
        /*in my case, the generated code have no methods, so ignore judging if methods exist in new class*/
        for (int j=0;j<oldTypeMethods.size();j++){
            MethodDeclaration omd = oldTypeMethods.get(j);
            Method method = new Method(omd.getNameAsString()); // method name
            SetModifiers(omd.getModifiers(), method);  // method modifiers
            method.setReturnType(new FullyQualifiedJavaType(omd.getType().toString())); // method return type
            // method body
            if(omd.getBody().isPresent()) {
                String[] body = omd.getBody().get().toString().split("\r\n");
                for (int k = 1; k < body.length - 1; k++){
                    body[k] = body[k].substring(4);
                }
                method.addBodyLines(Arrays.asList(Arrays.copyOfRange(body, 1, body.length -1)));
            }

            // method parameters
            NodeList<Parameter> ops = omd.getParameters();
            for(int k = 0; k < ops.size(); k ++){
                Parameter op = ops.get(k);
                org.mybatis.generator.api.dom.java.Parameter parameter = new org.mybatis.generator.api.dom.java.Parameter(
                        new FullyQualifiedJavaType(op.getType().toString()),
                        op.getName().toString());
                NodeList<AnnotationExpr> opAn = op.getAnnotations();
                for(int n = 0; n < opAn.size(); n++){
                    parameter.addAnnotation(opAn.get(n).toString());
                }
                method.addParameter(parameter);
            }

            // method annotations
            NodeList<AnnotationExpr> mae = omd.getAnnotations();
            for (int k = 0; k < mae.size();k++){
                method.addAnnotation(mae.get(k).toString());
            }

            // method exceptions
            NodeList<ReferenceType> exceptions = omd.getThrownExceptions();
            for(int k = 0; k < exceptions.size(); k++){
                method.addException(new FullyQualifiedJavaType(exceptions.get(k).toString()));
            }

            if(cu instanceof Interface){
                ((Interface)cu).addMethod(method);
            }
            else if(cu instanceof TopLevelClass){
                ((TopLevelClass)cu).addMethod(method);
            }
        }
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值