Mybatis Generator: What's the best way to separate out “auto generated” and “hand edited files”

前端 未结 4 964
终归单人心
终归单人心 2020-12-22 23:32

I am on a project that uses both Mybatis (for persisting java to database) and Mybatis Generator (to automatically generate the mapper xml files and java i

4条回答
  •  野趣味
    野趣味 (楼主)
    2020-12-23 00:01

    The Larry.Z solution help me to solve the same problem to separate auto generated from hand edited files. I had a custom folder structure in my project and adapted Larry solution to work in my project and add this answer to help other by use Larry solution adapting it.

    The best solution is to add feature to Mybatis generator (MBG) to integrate hand modified xml mapper. MBG had to be added parsing features to add corresponding hand node method to client mapper interface but right now this features do not exist so I use and adapted Larry.Z solution.

    In my project I use:

      
    ...  
    1.7  
    3.2.2.RELEASE  
    3.2.2  
    1.2.0  
    1.3.2  
    ...  
      
    

    My folder structure is:

    /dao/: MBG generated dao class

    /dao/extended/: Extended generated class (Extended)

    /sqlmap/: MBG generated client Interface and corresponding xml mapper

    /sqlmap/extended/:
    hand xml mapper and hand client Interface
    (Extended extends InterfaceGenerated {...)

    /sqlmap/generated/: copy of MBG generated mapper namespace changed

    I have configured Mybatis - spring

      
    

    Implement myBeanNameGenerator only if you need to have custom name like me. In this example you can delete row p:nameGenerator-ref="myBeanNameGenerator"

    If all your client Interfaces become extended you can substitute above
    p:basePackage=".sqlmap.extended"

    (my project configuration is huge so I have extract most important bit )

    This is an example of my client interface and mapper hand coded:

    import .dao.Countries;
    import .sqlmap.CountriesMapper;
    import org.apache.ibatis.annotations.Param;
    
    public interface CountriesMapperExtended extends CountriesMapper {
    
    /**
     *
     * @param code
     * @return
     */
    Countries selectByCountryCode(@Param("code") String code);
    

    }

    Where CountriesMapper is the client interface MBG generated

    The hand coded correlated xml mapper is:

    
    
    
    
      
    
    
    

    To make all work I have to integrate in xml mapper all interface method MBG generated and, to do this, I copied MBG generated xml mapper in /sqlmap/generated/ and change his namespace:

    
    
    
    ... unchanged ...
      
    

    The problem raise when db change and I have to use MBG to reflect the new db structure.

    So I have create quickly a bash script that watch in /sqlmap/extended/ and check if there is an hand coded xml mapper. If there is hand coded xml mapper, copy corresponding MBG generated changing his namespace.

    All this code is not an graceful solution but works.

    The bash script overwrite file in /sqlmap/generated/ so, not put in this folder your code.

    Make a backup copy of your project and modify the bash script, to custom it and use on your responsibility.

    #!/bin/bash
    CURDIR="$(pwd)"
    SCRIPT_DIR=`dirname $0`
    usage()
    {
    cat << EOF
    usage: $0 options
    
    This script is usefull to generate xml map to extend mybatis 
    generator client interfaces. It suppose this structure:
    /sqlmap/           : generated xml mapper and interfaces
    /sqlmap/extended/  : extended xml mapper and interfaces
    /sqlmap/generated/ : copy of generated xml mapper changing
                               its namespace
    
    If exist a mapper xml in /sqlmap/extend identify by a name 
    ending in Extended this script generate a copy of original generated
    xml map of extended interface changing then namespace to reflect the 
    extended Interface in /sqlmap/generated.
    
    This script require a list of base path:
    $0 path1 path2 ...
    
    Required parameters are marked by an *
    
    OPTIONS:
      -h, --help          Show this message
    
    EOF
    }
    
    declare -a BASES
    let INDEX=0
    TEMP=`getopt -o "hb:" --long "help,base:" -n "$0" -- "$@"`
    eval set -- "$TEMP"
    while true ; do
        case "$1" in
            -h|--help) 
                usage
                exit 1 ;;
            --) 
                shift ;
                break ;;
            *) 
                echo "Too mutch parametes!!! abort." ;
                exit 1 ;;
        esac
    done
    #process all paths
    let INDEX=0
    BASE="$1"
    while [ "${BASE:0:1}" == "/" ]
    do
        shift ;
        BASES[$INDEX]="$BASE"
        let INDEX+=1
        BASE="$1"
    done
    if [ "$INDEX" -le "0" ]
    then
        echo "--bases options cannot be emplty"
        usage
        exit 1
    fi
    
    for BASE in ${BASES[@]}
    do
        if [ ! -d "$BASE" ]
        then
            echo "Error: every base parameter must be a folder!!"
            echo "Base=$BASE is not a folder"
            usage
            exit 1
        fi
        SQLMAP="$BASE/sqlmap"
        if [ ! -d "$SQLMAP" ]
        then
            echo "Error: every base parameter must have a sqlmap folder!!"
            echo "$SQLMAP is not a folder"
            usage
            exit 1
        fi
        EXTENDED="$BASE/sqlmap/extended"
        if [ ! -d "$EXTENDED" ]
        then
            echo "Error: every base parameter must have a sqlmap/extended folder!!"
            echo "$EXTENDED is not a folder"
            usage
            exit 1
        fi
        GENERATED="$BASE/sqlmap/generated"
        if [ ! -d "$GENERATED" ]
        then
            mkdir -p "$GENERATED"
        fi
        while IFS= read -r -d '' file
        do
            name="${file##*/}" 
            #path="${file%/*}"
            ext=".${name##*.}"
            nameNoSuffix="${name%$ext}"
            nameBase="${nameNoSuffix%Extended}"
            sed -r 's/\s*$//' "$SQLMAP/$nameBase.xml" > "$GENERATED/$nameNoSuffix.xml"
        done < <(eval "find $EXTENDED/ -type f -name \*Extended\.xml -print0")
    
    done
    exit 0
    

    Use of the script

    $ ./post-generator.sh "/home/..." do not put the last / on path

    This path is the path to the folder that contains sqlmap, sqlmap/extended, sqlmap/generated

    You can use a list of path if you, like me, have more then one

    To use it by maven, I use this plugin in project pom.xml:

                
                    exec-maven-plugin
                    org.codehaus.mojo
                    1.2.1
                    
                        
                            build client extended xml
                            
                                exec
                            
                        
                    
                    
                        ${basedir}/scripts/post-generator.sh
                        ${basedir}/scripts
                        
                            ${basedir}/
                            ${basedir}/
                        
                    
                
    

    On project folder you can use $ mvn exec:exec or $ mvn mybatis-generator:generate exec:exec

    If you use Netbeans you can configure a project action to run these goals mybatis-generator:generate exec:exec without left Netbeans. You can start it by hand when you have a change in db structure.

    Now you can work on exended mapper without problem and let MBG do his work if db structure change.

    In your bean you can inject extended interface that have
    automatic generated MBG methods plus your hand coded methods:

        
    

    Where countriesMapperExtended bean is generated by mapperScanner above.

提交回复
热议问题