欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

tk.mybatis如何擴(kuò)展自己的通用mapper

 更新時(shí)間:2021年06月11日 11:41:08   作者:OUOll  
這篇文章主要介紹了tk.mybatis如何擴(kuò)展自己的通用mapper操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

tk.mybatis擴(kuò)展自己的通用mapper

目的:tk.mybatis 提供的通用mapper,雖然使用方便,不過在有些sql還是不能滿足我們的需要的,而且我們希望對(duì)于deleted語(yǔ)句進(jìn)行管控(因?yàn)橥ㄓ胢apper提供的都是物理刪除,有時(shí)我們對(duì)一些敏感數(shù)據(jù)只能進(jìn)行邏輯刪除),因此我們將基于原有的通用mapper進(jìn)行自己的擴(kuò)展

1 jar引入

     <!-- 非springboot -->
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper</artifactId>
            <version>3.4.0</version>
        </dependency>

非springboot項(xiàng)目引這個(gè)包

      <!-- springboot -->
             <dependency>
                <groupId>tk.mybatis</groupId>
                <artifactId>mapper-spring-boot-starter</artifactId>
                <version>2.0.2</version>
            </dependency>

springboot項(xiàng)目直接引這個(gè)包,本次我們將基于springboot進(jìn)行開發(fā),這里注意jar包版本,過低的版本將會(huì)出現(xiàn)問題,下面會(huì)介紹

2 編寫配置類

package com.example.configuration;
import com.example.common.mapper.commonMapper.CommonMapper;
import org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import tk.mybatis.spring.mapper.MapperScannerConfigurer;
import java.util.Properties;
@Configuration
@AutoConfigureAfter(MybatisAutoConfiguration.class)
public class MyBatisConfiguration {
    @Bean
    public MapperScannerConfigurer mapperScannerConfigurer() {
        MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
        mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
        mapperScannerConfigurer.setBasePackage("com.example.dao.mapper");
        Properties properties = new Properties();
        properties.setProperty("mappers", CommonMapper.class.getName());
        properties.setProperty("notEmpty", "false");
        properties.setProperty("identity", "MYSQL");
        properties.setProperty("order","BEFORE");
        mapperScannerConfigurer.setProperties(properties);
        return mapperScannerConfigurer;
    }
}

這里要注意兩點(diǎn):

1>CommonMapper這個(gè)是我們自己定義的通用mapper,它放置一個(gè)單獨(dú)的包下面。也就是說這個(gè)包下面只有這個(gè)一個(gè)mapper,否則我們?cè)趯?shí)用泛型時(shí)會(huì)出現(xiàn)類型轉(zhuǎn)換的問題。(我在這里糾結(jié)了好久)

2>這里我們配置了自定義mapper的掃描路徑。注意springboot項(xiàng)目一定要注意jar包版本,版本過低的話,在配置類中的定義是沒有用的。還是掃描不到,我之前使用的版本1.2.3就會(huì)出現(xiàn)這個(gè)問題,更換更高的版本就可以解決了。

3 常規(guī)方法接口整合到自己的自定義Mapper接口上

因?yàn)槲覀兪褂玫氖莔ysql數(shù)據(jù)庫(kù),所以在使用通用功能的時(shí)候就選擇性引入一些經(jīng)常使用的方法,下面是自己定義的常用mapper類的整合(這里會(huì)拋棄一些不常用的類或不是mysql的方法類)。這些基類不要放在 BasePackage的路徑下,這個(gè)路徑下的mapper都是要指定明確的泛型類型的。

1 > 提供查詢功能Mapper:

package com.example.common.mapper.basics;
import tk.mybatis.mapper.common.Marker;
import tk.mybatis.mapper.common.base.select.*;
import tk.mybatis.mapper.common.condition.SelectByConditionMapper;
import tk.mybatis.mapper.common.condition.SelectCountByConditionMapper;
import tk.mybatis.mapper.common.example.SelectByExampleMapper;
import tk.mybatis.mapper.common.ids.SelectByIdsMapper;
/**
 * @desc 基礎(chǔ)查詢功能mapper
 *
 */
public interface SelectMapper<T> extends Marker,
        SelectOneMapper<T>,
        tk.mybatis.mapper.common.base.select.SelectMapper<T>,
        SelectAllMapper<T>,
        SelectCountMapper<T>,
        SelectByPrimaryKeyMapper<T>,
        ExistsWithPrimaryKeyMapper<T>,
        SelectByIdsMapper<T>,
        SelectByConditionMapper<T>,
        SelectCountByConditionMapper<T>,
        SelectByExampleMapper<T> {
}

2>提供新增功能mapper

package com.example.common.mapper.basics;
import tk.mybatis.mapper.common.Marker;
import tk.mybatis.mapper.common.MySqlMapper;
import tk.mybatis.mapper.common.base.insert.InsertSelectiveMapper;
/**
 * @desc 基礎(chǔ)插入功能mapper
 */
public interface InsertMapper<T> extends Marker,
        tk.mybatis.mapper.common.base.insert.InsertMapper<T>,
        InsertSelectiveMapper<T>,
        MySqlMapper<T>{
}

3>提供更新功能mapper

package com.example.common.mapper.basics;
import tk.mybatis.mapper.common.Marker;
import tk.mybatis.mapper.common.base.update.UpdateByPrimaryKeyMapper;
import tk.mybatis.mapper.common.base.update.UpdateByPrimaryKeySelectiveMapper;
import tk.mybatis.mapper.common.condition.UpdateByConditionMapper;
import tk.mybatis.mapper.common.condition.UpdateByConditionSelectiveMapper;
import tk.mybatis.mapper.common.example.UpdateByExampleSelectiveMapper;
/**
 * @desc 基礎(chǔ)更新功能mapper
 *
 */
public interface UpdateMapper<T> extends Marker,
        UpdateByPrimaryKeyMapper<T>,
        UpdateByPrimaryKeySelectiveMapper<T>,
        UpdateByConditionMapper<T>,
        UpdateByConditionSelectiveMapper<T>,
        UpdateByExampleSelectiveMapper<T> {
}

4>提供刪除功能mapper

package com.example.common.mapper.basics;
import com.example.common.mapper.defined.DeleteShamByIdsMapper;
import tk.mybatis.mapper.common.Marker;
import tk.mybatis.mapper.common.base.delete.DeleteByPrimaryKeyMapper;
import tk.mybatis.mapper.common.condition.DeleteByConditionMapper;
import tk.mybatis.mapper.common.ids.DeleteByIdsMapper;
/**
 * @desc 基礎(chǔ)刪除功能mapper
 *
 */
public interface DeleteMapper<T> extends Marker,
        tk.mybatis.mapper.common.base.delete.DeleteMapper<T>,
        DeleteByPrimaryKeyMapper<T>,
        DeleteByConditionMapper<T>,
        DeleteByIdsMapper<T>{
}

5>提供增刪改查的基類 CommonMapper

package com.example.common.mapper.commonMapper;
import com.example.common.mapper.basics.DeleteMapper;
import com.example.common.mapper.basics.InsertMapper;
import com.example.common.mapper.basics.SelectMapper;
import com.example.common.mapper.basics.UpdateMapper;
/**
 * @param <T>
 * @desc 基礎(chǔ)增刪改查功能mapper
 */
public interface CommonMapper<T> extends
        DeleteMapper<T>,
        InsertMapper<T>,
        SelectMapper<T>,
        UpdateMapper<T> {
}

6>實(shí)體對(duì)象

package com.example.dao.entity;
import lombok.Data;
import javax.persistence.Id;
import javax.persistence.Table;
import java.io.Serializable;
@Table(name="user")
@Data
public class User implements Serializable {
    @Id
    private Integer id;
    private String trueName;
    private String userName;    
    private Integer isDeleted;
}

7>讓自定義mapper繼承CommenMapper,就可以使用這些語(yǔ)句了

package com.example.dao.mapper;
import com.example.common.mapper.commonMapper.CommonMapper;
import com.example.dao.entity.User;
public interface UserMapper extends CommonMapper<User> {
}

接下來我們會(huì)對(duì) CommonMapper中提供刪除方法的DeleteMapper進(jìn)行增強(qiáng),來給他添加邏輯刪除的語(yǔ)句

1>我們自定義的Provider需要去繼承 MapperTemplate并覆寫構(gòu)造方法

這個(gè)是源碼中的批量刪除

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package tk.mybatis.mapper.provider;
import java.util.Set;
import org.apache.ibatis.mapping.MappedStatement;
import tk.mybatis.mapper.MapperException;
import tk.mybatis.mapper.entity.EntityColumn;
import tk.mybatis.mapper.mapperhelper.EntityHelper;
import tk.mybatis.mapper.mapperhelper.MapperHelper;
import tk.mybatis.mapper.mapperhelper.MapperTemplate;
import tk.mybatis.mapper.mapperhelper.SqlHelper;
public class IdsProvider extends MapperTemplate {
    public IdsProvider(Class<?> mapperClass, MapperHelper mapperHelper) {
        super(mapperClass, mapperHelper);
    }
    public String deleteByIds(MappedStatement ms) {
        Class<?> entityClass = this.getEntityClass(ms);
        StringBuilder sql = new StringBuilder();
        sql.append(SqlHelper.deleteFromTable(entityClass, this.tableName(entityClass)));
        Set<EntityColumn> columnList = EntityHelper.getPKColumns(entityClass);
        if (columnList.size() == 1) {
            EntityColumn column = (EntityColumn)columnList.iterator().next();
            sql.append(" where ");
            sql.append(column.getColumn());
            sql.append(" in (${_parameter})");
            return sql.toString();
        } else {
            throw new MapperException("繼承 deleteByIds 方法的實(shí)體類[" + entityClass.getCanonicalName() + "]中必須只有一個(gè)帶有 @Id 注解的字段");
        }
    }
    public String selectByIds(MappedStatement ms) {
        Class<?> entityClass = this.getEntityClass(ms);
        this.setResultType(ms, entityClass);
        StringBuilder sql = new StringBuilder();
        sql.append(SqlHelper.selectAllColumns(entityClass));
        sql.append(SqlHelper.fromTable(entityClass, this.tableName(entityClass)));
        Set<EntityColumn> columnList = EntityHelper.getPKColumns(entityClass);
        if (columnList.size() == 1) {
            EntityColumn column = (EntityColumn)columnList.iterator().next();
            sql.append(" where ");
            sql.append(column.getColumn());
            sql.append(" in (${_parameter})");
            return sql.toString();
        } else {
            throw new MapperException("繼承 selectByIds 方法的實(shí)體類[" + entityClass.getCanonicalName() + "]中必須只有一個(gè)帶有 @Id 注解的字段");
        }
    }
}

接下來我們對(duì)IdsProvider 進(jìn)行擴(kuò)展使他支持批量邏輯刪除

1>創(chuàng)建IdsProvider的子類

package com.example.common.mapper.defined;
import org.apache.ibatis.mapping.MappedStatement;
import tk.mybatis.mapper.MapperException;
import tk.mybatis.mapper.entity.EntityColumn;
import tk.mybatis.mapper.mapperhelper.EntityHelper;
import tk.mybatis.mapper.mapperhelper.MapperHelper;
import tk.mybatis.mapper.mapperhelper.SqlHelper;
import tk.mybatis.mapper.provider.IdsProvider;
import java.util.Set;
public class IdsProviderDefined extends IdsProvider {
    public IdsProviderDefined(Class<?> mapperClass, MapperHelper mapperHelper) {
        super(mapperClass, mapperHelper);
    }
    public String deleteShamByIds(MappedStatement ms) {
        Class<?> entityClass = this.getEntityClass(ms);
        StringBuilder sql = new StringBuilder();
        sql.append(SqlHelper.updateTable(entityClass, this.tableName(entityClass)));
        sql.append("<set> is_deleted='1' </set>");
        Set<EntityColumn> columnList = EntityHelper.getPKColumns(entityClass);
        if (columnList.size() == 1) {
            EntityColumn column = (EntityColumn)columnList.iterator().next();
            sql.append(" where ");
            sql.append(column.getColumn());
            sql.append(" in (${_parameter})");
            return sql.toString();
        } else {
            throw new MapperException("繼承 deleteByIds 方法的實(shí)體類[" + entityClass.getCanonicalName() + "]中必須只有一個(gè)帶有 @Id 注解的字段");
        }
    }
}

deleteShamByIds就是我們門批量邏輯刪除的方法,這個(gè)方法其實(shí)就是再拼裝sql,tk中提供了很多幫助我們拼裝sql,和參數(shù)的類(SqlHelper,EntityHelper),我們可以使用

2>創(chuàng)建DeleteShamByIdsMapper接口

package com.example.common.mapper.defined;
import org.apache.ibatis.annotations.DeleteProvider;
public interface DeleteShamByIdsMapper<T> {
    @DeleteProvider(
            type = IdsProviderDefined.class,
            method = "dynamicSQL"
    )
    int deleteShamByIds(String var1);
    //這里的抽象方法的名稱必須和IdsProviderDefined 中的方法一致
}

3>在DeleteMapper中繼承我們自定義的邏輯刪除接口DeleteShamByIdsMapper

package com.example.common.mapper.basics;
import com.example.common.mapper.defined.DeleteShamByIdsMapper;
import tk.mybatis.mapper.common.Marker;
import tk.mybatis.mapper.common.base.delete.DeleteByPrimaryKeyMapper;
import tk.mybatis.mapper.common.condition.DeleteByConditionMapper;
import tk.mybatis.mapper.common.ids.DeleteByIdsMapper;
/**
 * @desc 基礎(chǔ)刪除功能mapper
 *
 */
public interface DeleteMapper<T> extends Marker,
        tk.mybatis.mapper.common.base.delete.DeleteMapper<T>,
        DeleteByPrimaryKeyMapper<T>,
        DeleteByConditionMapper<T>,
        DeleteByIdsMapper<T>,
        DeleteShamByIdsMapper<T>{
}

到這里我們自定義的批量邏輯刪除就定義好了,我們可以通過這種方式擴(kuò)展通用mapper。

TK mybatis插件通用mapper與oracle的幾個(gè)坑

最近公司有幾個(gè)項(xiàng)目的數(shù)據(jù)庫(kù)用的oracle,有段時(shí)間沒用,然后果斷就掉坑里面了,記錄幾個(gè)比較有代表性的。

1:關(guān)于oracle的批量數(shù)據(jù)插入,我用TK通用mapper的insertList方法自動(dòng)拼接出來的sql是這樣的

insert  into table(column1,column2)values 
(value1,value2),
(value3,value4)。。。

咋一看沒啥問題啊,然后就一直報(bào) sql未正確結(jié)束,出于對(duì)自己sql的過于自信,導(dǎo)致一直都在思考是否是參數(shù)問題,浪費(fèi)了好幾個(gè)小時(shí),后來把sql拼好直接丟到數(shù)據(jù)庫(kù)跑了跑才發(fā)現(xiàn),這種sql確實(shí)是不能在oracle跑的,oracle批量插入的語(yǔ)法應(yīng)該是:

INSERT ALL 
INTO A(field_1,field_2) VALUES (value_1,value_2) 
INTO A(field_1,field_2) VALUES (value_3,value_4) 
INTO A(field_1,field_2) VALUES (value_5,value_6)

粗略的瞅了下TK的代碼,貌似確實(shí)沒有校驗(yàn)數(shù)據(jù)庫(kù)驅(qū)動(dòng)就直接開始拼sql了

public String insertList(MappedStatement ms) {
        Class<?> entityClass = this.getEntityClass(ms);
        StringBuilder sql = new StringBuilder();
        sql.append(SqlHelper.insertIntoTable(entityClass, this.tableName(entityClass)));
        sql.append(SqlHelper.insertColumns(entityClass, true, false, false));
        sql.append(" VALUES ");
        sql.append("<foreach collection=\"list\" item=\"record\" separator=\",\" >");
        sql.append("<trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">");
        Set<EntityColumn> columnList = EntityHelper.getColumns(entityClass);
        Iterator var5 = columnList.iterator();
        while(var5.hasNext()) {
            EntityColumn column = (EntityColumn)var5.next();
            if (!column.isId() && column.isInsertable()) {
                sql.append(column.getColumnHolder("record") + ",");
            }
        }
        sql.append("</trim>");
        sql.append("</foreach>");
        return sql.toString();
    }

不過我覺得這種插件肯定是有兼容方案的,并且使用了這個(gè)插件跟使用源生mybatis并不沖突,所以實(shí)際對(duì)開發(fā)并沒有影響,算是復(fù)習(xí)一下oracle的基礎(chǔ)并提醒下自己,程序員還是老老實(shí)實(shí)先run起來,自以為是的經(jīng)驗(yàn)有時(shí)候也很坑的。

2:關(guān)于oracle的比較符號(hào)(<> =)和null

先復(fù)習(xí)一下

一般數(shù)據(jù)庫(kù)查詢某某字段為空或者不為空的時(shí)候都是用is null或者is not null

如果查詢條件使用=null或者<>null是查不出來數(shù)據(jù)的

但是賦值卻可以用=null如

update BUS_PLATFORM.bus_trans set return_code = null where return_msg= 'tac驗(yàn)證通過';

這個(gè)是可以執(zhí)行成功的,不過這個(gè)都是表外的值操作,那么當(dāng)表內(nèi)的數(shù)據(jù)有null時(shí),又有啥坑呢,比如

select * from table1 where name <>'zhansan'

查詢表中name字段不為zhangsan的數(shù)據(jù),當(dāng)表中有name為null的數(shù)據(jù)時(shí),這些數(shù)據(jù)也是查不出來的.比如表中有100條數(shù)據(jù),一條數(shù)據(jù)的name值為zhangsan ,九條數(shù)據(jù)的name值為null,那么這條sql只能查出90條數(shù)據(jù),所以如果確切的需求要查詢name值不為zhangsan的數(shù)據(jù)且包括name值為null的數(shù)據(jù),sql應(yīng)該為

select * from table1 where name <>'zhansan' or name is null

3:這個(gè)是mybatis的一個(gè)規(guī)范,基本是湊數(shù)的,不過也坑過我

先上內(nèi)容:mybatis插入null值時(shí)需要指定該值的類型(jdbctype),不然會(huì)報(bào)錯(cuò)。

因?yàn)椴恢付愋偷脑抦ybatis會(huì)自己去適配匹配的數(shù)據(jù)庫(kù)字段類型,null適配不了。搞不定就報(bào)錯(cuò),很穩(wěn)。不過一般使用xml配置sql的話一般都不會(huì)有這個(gè)問題,寫的時(shí)候順手都會(huì)寫上。這個(gè)也是我使用TK的時(shí)候暴露出來的問題,在使用insert方法的時(shí)候有null就掛了,不過TK有個(gè)insertSelective方法做插入的時(shí)候會(huì)自動(dòng)過濾掉空值。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • mybatis postgresql 批量刪除操作方法

    mybatis postgresql 批量刪除操作方法

    PostgreSQL是一種特性非常齊全的自由軟件的對(duì)象-關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng)(ORDBMS),這篇文章主要介紹了mybatis postgresql 批量刪除操作,需要的朋友可以參考下
    2020-02-02
  • 如何為Repository添加自定義方法

    如何為Repository添加自定義方法

    這篇文章主要介紹了如何為Repository添加自定義方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Java實(shí)現(xiàn)調(diào)用jython執(zhí)行python文件的方法

    Java實(shí)現(xiàn)調(diào)用jython執(zhí)行python文件的方法

    這篇文章主要介紹了Java實(shí)現(xiàn)調(diào)用jython執(zhí)行python文件的方法,結(jié)合實(shí)例形式分析了Java調(diào)用jython執(zhí)行python文件的常見操作技巧及相關(guān)問題解決方法,需要的朋友可以參考下
    2018-03-03
  • java登錄驗(yàn)證碼實(shí)現(xiàn)代碼

    java登錄驗(yàn)證碼實(shí)現(xiàn)代碼

    這篇文章介紹了java實(shí)現(xiàn)登錄驗(yàn)證碼:用興趣的同學(xué)可以參考一下
    2013-10-10
  • IDEA 端口占用的解決方法(推薦)

    IDEA 端口占用的解決方法(推薦)

    這篇文章主要介紹了IDEA 端口占用的解決方法,本文通過兩種方法給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-10-10
  • SpringBoot-JWT生成Token和攔截器的使用(訪問受限資源)

    SpringBoot-JWT生成Token和攔截器的使用(訪問受限資源)

    本文主要介紹了SpringBoot-JWT生成Token和攔截器的使用(訪問受限資源),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • java異或加密算法

    java異或加密算法

    這篇文章主要介紹了java異或加密算法,有需要的朋友可以參考一下
    2013-12-12
  • Spring boot 在idea中添加熱部署插件的圖文教程

    Spring boot 在idea中添加熱部署插件的圖文教程

    這篇文章主要介紹了Spring boot 在idea中添加熱部署插件的圖文教程,本文通過圖文并茂的形式給大家展示具體步驟,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-10-10
  • spring boot中使用http請(qǐng)求的示例代碼

    spring boot中使用http請(qǐng)求的示例代碼

    本篇文章主要介紹了spring boot中 使用http請(qǐng)求的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-12-12
  • Java注解的Retention和RetentionPolicy實(shí)例分析

    Java注解的Retention和RetentionPolicy實(shí)例分析

    這篇文章主要介紹了Java注解的Retention和RetentionPolicy,結(jié)合實(shí)例形式分析了Java注解Retention和RetentionPolicy的基本功能及使用方法,需要的朋友可以參考下
    2019-09-09

最新評(píng)論