Springboot整合通用mapper

共 9336字,需浏览 19分钟

 ·

2020-09-16 07:35

点击上方蓝色字体,选择“标星公众号”

优质文章,第一时间送达

66套java从入门到精通实战课程分享

引言

我第一次整合orm框架的时候,本来使用jpa,多表联查比较麻烦(只是单纯的使用,没深入使用,可能有比较好的方法使用,我没用到),单纯使用mybatis,写单纯的crud的方法,感觉自己手写太麻烦,如果用mybatis的逆向工程,它又给你生成各种方法,我觉得很烦。那有没有一个框架可以简简单单的让我不需要太多的东西就可以使用单表的操作呢,我发现了通用mapper。(后来其实发现,mybatis-plus两个思路大同小异,都挺好的。)

一、导入依赖

    
        
            tk.mybatis
            mapper
            4.1.5
        

        
            tk.mybatis
            mapper-spring-boot-starter
            2.1.5
        



        
       
            org.mybatis.generator
            mybatis-generator-core
            1.3.6
        


        
            org.mybatis.spring.boot
            mybatis-spring-boot-starter
            2.1.0
        


        
            mysql
            mysql-connector-java
            runtime
        

        
            org.springframework.boot
            spring-boot-starter-jdbc
        

        
            com.github.pagehelper
            pagehelper-spring-boot-starter
            1.2.5
        


        
            org.springframework.boot
            spring-boot-starter-test
        

        
         
          
            org.mybatis.generator
            mybatis-generator-core
            1.3.6
        

        
            org.springframework.boot
            spring-boot-starter-freemarker
        

         
          
            org.springframework.boot
            spring-boot-starter-web
        


第一部分核心依赖,第二部分是一些配套的,看你需求。我是用mybatis的逆向工程的

二、启动类添加注解

@MapperScan(value = "com.xyo.it.service.**.mapper")

注意,这个是import tk.mybatis.spring.annotation.MapperScan;扫描的你的mapper,注意通配符的使用

三、yaml

mybatis:
      mapper-locations: classpath:mapping/**/*Mapper.xml
      type-aliases-package: com.xyo.it.*.entity

这个应该是mybatis的注解,用于扫描xml的吧?

四、使用

前面都不是重点,重点在使用,帮我们做到了什么。

1. 继承通用的Mapper,必须指定泛型

public interface RecordMapper extends BaseMapper {
}

一旦继承了Mapper,继承的Mapper就拥有了Mapper所有的通用方法。

里面包含了几乎所有的单表的crud方法。而查询的话,基本使用的Example。

     Example example = new Example(FiveClassRecord.class);
        Example.Criteria criteria = example.or();
        criteria.andEqualTo("taskNo", lcyhTaskNo);//注意,这个是类的属性,与mybatis不同,不是用数据库的字段名,是用的类的属性,

咋一看是没什么东西,但是我主要看上了他的组装功能

2.接口可以自定义搭配继承

如果你想按需选择接口,不想使用Mapper包含的那么多的方法,你可以创建自己的MyMapper,自己搭配想要的方法

主要场景在于,我可能之前用的是oracle数据库,然后我切换回db2数据库,突然发现,id自增,不需要指定id了,那怎么办

Mapper3接口有两种形式,一种是提供了一个方法的接口。还有一种是不提供方法,但是继承了多个单方法的接口,一般是某类方法的集合。

你可以按需的组装

//注意,如果是sqlserverMapper这种,因为insert不允许id包含为null,所以继承sqlServerMapper
//另外这俩方法和base中的插入方法重名,不能同时存在!所以拆分了
public interface BaseMapper extends BaseSelectMapper, BaseUpdateMapper, BaseDeleteMapper, ExampleMapper, RowBoundsMapper, SqlServerMapper, MyBatchInsertMapper {
}

我的基本mapper就是这样,组合了基本的crud,查询,分页。加上一个自定义的mapper,这个后续说。

主要问题在于,mybatis不是跟hibernate一样提供方言,所以,d自增,不需要指定id了,那么我们就可以用支持不带上id的插入。

3.支持逆向工程

public class GeneratorSqlmap {

    public void generator() throws Exception {
        List warnings = new ArrayList();
        boolean overwrite = true;
        // 指定配置文件
        File configFile = new File("./src/main/resources/generatorConfig/generatorConfig.xml");
        ConfigurationParser cp = new ConfigurationParser(warnings);
        Configuration config = cp.parseConfiguration(configFile);
        DefaultShellCallback callback = new DefaultShellCallback(overwrite);
        MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
        myBatisGenerator.generate(null);
    }

    // 执行main方法以生成代码
    public static void main(String[] args) {
        try {
            GeneratorSqlmap generatorSqlmap = new GeneratorSqlmap();
            generatorSqlmap.generator();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

generatorConfig.xml

"-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">


    "DB2Tables" targetRuntime="MyBatis3">
        type="tk.mybatis.mapper.generator.MapperPlugin">
            "mappers" value="com.platform.common.BaseMapper"/>
        



        
            
            "suppressAllComments" value="true"/>
        

        
        "com.ibm.db2.jcc.DB2Driver"
                        connectionURL="jdbc:db2://66.10.93.82:60004/DFTCE:currentSchema=DFTCE;"
                        userId="dftce"
                        password="2vgrTNY51pK3hQ2e">
        




        

        
        
            "forceBigDecimals" value="false" />
        

        

        "com.beawan.exterinvoke.out.newhfw.entity" targetProject=".\src\main\java">

            
            "enableSubPackages" value="false" />
            
            "trimStrings" value="true" />
        

        
        "mapping.newhfw"  targetProject=".\src\main\resources">

            
            "enableSubPackages" value="false" />
        

        
        type="XMLMAPPER" targetPackage="com.beawan.exterinvoke.out.newhfw.mapper" targetProject=".\src\main\java">

            
            "enableSubPackages" value="false" />

        


        


        "DFTCE" tableName="COM_EXECUTE_INFO" domainObjectName="comExecuteInfo"
               enableCountByExample="false"  enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" >
            "ID" sqlStatement="JDBC"/>
            "ID" javaType="java.lang.Long"/>
            "C_CASE_CODE" property="C_CASE_CODE" />
            "C_INAME" property="C_INAME" />
            "N_CARD_TYPE" property="N_CARD_TYPE" />
            "C_CARD_NUM" property="C_CARD_NUM" />
            "C_GIST_CID" property="C_GIST_CID" />
            "APPLY_PARTY" property="APPLY_PARTY" />
            "EXECUTED_PARTY" property="EXECUTED_PARTY" />
            "C_COURT_NAME" property="C_COURT_NAME" />
            "C_PARTY_TYPE" property="C_PARTY_TYPE" />
            "C_BUEINESS_ENTITY_NAME" property="C_BUEINESS_ENTITY_NAME" />
            "C_ADDRESS" property="C_ADDRESS" />
            "C_PUBLISH_DATE" property="C_PUBLISH_DATE" />
            "C_REG_DATE" property="C_REG_DATE" />
            "N_APPLY_MONEY" property="N_APPLY_MONEY" />
            "N_EXECUTED_MONEY" property="N_EXECUTED_MONEY" />
            "C_EFFECTIVE_FLAG" property="C_EFFECTIVE_FLAG" />
            "D_DATA_DATE" property="D_DATA_DATE" />
        




    


这里我指定了mybatis的插件为tkmapper的,然后让他mapper继承我的通用mapper,同时不让生成example类。

那么会生成什么呢?

就两个,一个entity类,一个mapper。

entity

@Table(name = "AC_CONFIGURATION")
public class AcConfiguration {
    @Id
    @Column(name = "ID")
    @GeneratedValue(generator = "JDBC")
    private Long id;

    @Column(name = "ASSESS_CARD_ID")
    private Long assessCardId;

    @Column(name = "STATE")
    private String state;

    @Column(name = "PASS_SCORE")
    private Double passScore;

    @Column(name = "REJECT_SCORE")
    private Double rejectScore;

    @Column(name = "FINANCE_RATION")
    private Double financeRation;

    @Column(name = "UNFINANCE_RATIO")
    private Double unfinanceRatio;

    @Column(name = "SCORE_WAY")
    private String scoreWay;

    @Column(name = "LOAN_TYPE")
    private String loanType;

    @Column(name = "GUARANTEE_TYPE")
    private String guaranteeType;

    @Column(name = "ENTERPRISE_TYPE")
    private String enterpriseType;

    @Column(name = "CARD_TYPE")
    private String cardType;

    @Column(name = "SUGG_SCORE")
    private Double suggScore;

    @Column(name = "AC_CUS_LEVEL_SET")
    private String acCusLevelSet;

    /**
     * 非持久化字段
     */
    private List acCusLevelList;

    /**
     * @return ID
     */
    public Long getId() {
        return id;
    }

    /**
     * @param id
     */
    public void setId(Long id) {
        this.id = id;
    }

    public List getAcCusLevelList() {
        return acCusLevelList;
    }

    public void setAcCusLevelList(List acCusLevelList) {
        this.acCusLevelList = acCusLevelList;
    }

    /**
     * @return ASSESS_CARD_ID
     */
    public Long getAssessCardId() {
        return assessCardId;
    }

    /**
     * @param assessCardId
     */
    public void setAssessCardId(Long assessCardId) {
        this.assessCardId = assessCardId;
    }

    /**
     * @return STATE
     */
    public String getState() {
        return state;
    }

    /**
     * @param state
     */
    public void setState(String state) {
        this.state = state == null ? null : state.trim();
    }

    /**
     * @return PASS_SCORE
     */
    public Double getPassScore() {
        return passScore;
    }

看出来了没有,就是用的jpa的注解

所以切换的成本很低

非持久化字段,可以加 @Transient 注解

而mapper就继承了我的通用mapper,比mybatis的逆向工程生成简洁了很多。

4.支持开发自己的mapper

我还是看上了这个功能,开发自己的mapper,diy很开心

比如我们要开发一个批量插入功能,那么怎么做

定义批量接口

@RegisterMapper
public interface MyBatchInsertMapper {
    @Options(useGeneratedKeys = true,keyProperty = "id")
    @InsertProvider(type = MyBatchInsertProvider.class,method = "dynamicSQL")
    int batchInsert(List recoordList);
}

实现自定义的类MyBatchInsertProvider.class

public class MyBatchInsertProvider extends MapperTemplate {
    public MyBatchInsertProvider(Class mapperClass, MapperHelper mapperHelper) {
        super(mapperClass, mapperHelper);
    }
    public String batchInsert(MappedStatement ms){
        final Class entiyClass = this.getEntityClass(ms);
        EntityTable table = EntityHelper.getEntityTable(entiyClass);
        LinkedHashSet tableColumns = table.getEntityClassColumns();
        LinkedHashSet nopkColumns = getNoPKColumn(tableColumns);

        StringBuilder sql = new StringBuilder();
        sql.append("insert into ");
        sql.append(table.getName());
        sql.append("(");
        boolean first = true;
        for(EntityColumn column :nopkColumns){
            if(!first){
                sql.append(",");
            }
            sql.append(column.getColumn());
            first=false;
        }
        sql.append(") values ");
        sql.append("");
        sql.append("(");
        first=true;
        for(EntityColumn column : nopkColumns){
            if(!first){
                sql.append(",");
            }
            sql.append("#{record.").append(column.getProperty()).append("}");
            first=false;
        }
        sql.append(")");
        sql.append("");
        return sql.toString();
    }
     public static LinkedHashSet getNoPKColumn( LinkedHashSet tableColumns){
         LinkedHashSet noPKColumn =new LinkedHashSet<>();
         if(CollectionUtil.isNullOrEmpty(tableColumns)) return null;
         for(EntityColumn entityColumn:tableColumns){
             if(!"id".equals(entityColumn.getColumn().toLowerCase()) ){
                 noPKColumn.add(entityColumn);
             }
         }
         return noPKColumn;
     }
}


其实思路就是凭借mybatis格式的xml

这样我们就实现了批量插入,支持的是不带上id的批量插入

结语

通用Mapper都可以极大的方便开发人员。可以随意的按照自己的需要选择通用方法,还可以很方便的开发自己的通用方法。

极其方便的使用MyBatis单表的增删改查。

支持单表操作,不支持通用的多表联合查询。

其实这样还是比较简单的使用,我的使用方法是先在数据库设计生成好表,加好注释,然后运行逆向工程,生成了entity和mapper和xml,然后我再运行我自己写的自动生成 模板的servcie接口和实现类,以及controller,这样一个完整的后台的单表查询接口就写完了,我只需要设计表就好,其他都只是运行下代码就好。

toLowerCase()) ){
noPKColumn.add(entityColumn);
}
}
return noPKColumn;
}
}

其实思路就是凭借mybatis格式的xml

这样我们就实现了批量插入,支持的是不带上id的批量插入

##  结语

通用Mapper都可以极大的方便开发人员。可以随意的按照自己的需要选择通用方法,还可以很方便的开发自己的通用方法。

极其方便的使用MyBatis单表的增删改查。

支持单表操作,不支持通用的多表联合查询。

其实这样还是比较简单的使用,我的使用方法是先在数据库设计生成好表,加好注释,然后运行逆向工程,生成了entity和mapper和xml,然后我再运行我自己写的自动生成 模板的servcie接口和实现类,以及controller,这样一个完整的后台的单表查询接口就写完了,我只需要设计表就好,其他都只是运行下代码就好。

大部分市面上的单表接口,也是这样的思路生成的,不过不同的是,我加上了自己的逻辑,写了自己的模板。



版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:

http://blog.csdn.net/Wzy000001/article/details/108542223




粉丝福利:108本java从入门到大神精选电子书领取

???

?长按上方锋哥微信二维码 2 秒
备注「1234」即可获取资料以及
可以进入java1234官方微信群



感谢点赞支持下哈 


浏览 44
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报