日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

【Java代码】使用 org.apache.ibatis.plugin.Interceptor 拦截器实现全局 mapper.xml 参数注入(可用于切换数据库实例schema+Demo举例源码)

發(fā)布時間:2024/10/6 java 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Java代码】使用 org.apache.ibatis.plugin.Interceptor 拦截器实现全局 mapper.xml 参数注入(可用于切换数据库实例schema+Demo举例源码) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

1. why

??項目沒有使用MyBatis,進行數(shù)據(jù)操作時使用的是jdbc中默認的schema,現(xiàn)在項目要加入多租戶,同一個數(shù)據(jù)庫下不同租戶使用不同的實例schema,這就要在mapper文件內(nèi)所有的表名稱前加上schema,并動態(tài)傳遞其參數(shù)值,這樣每個SQL都要添加這個參數(shù),如果傳遞的是對象,也要給對象加相應的屬性,這個工作量可想而知。
??必須想辦法,將schema參數(shù)傳遞給所有的SQL,辦法就是全局配置。

2. code

2.1 實現(xiàn)攔截器接口并重寫方法

攔截器【 1?? SchemaInterceptor】實現(xiàn)(如果用戶調(diào)用的SQL接口里沒有傳 schemaName 就用默認值):

@Intercepts({@Signature(method = "update",args = {MappedStatement.class, Object.class}, type = Executor.class),@Signature(method = "query",args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}, type = Executor.class) }) public class SchemaInterceptor implements Interceptor {/*** 這里沒有打印日志*/private static Log LOG = LogFactory.getLog(SchemaInterceptor.class);/*** mapper.xml 使用SCHEMA時的參數(shù)名稱*/private static final String SCHEMA = "schemaName";/*** 設置默認的schema*/private String schema = "public";/*** 攔截到的動態(tài)SQL處理后放入此對象*/private Set<Integer> sourceStorage = new HashSet<>();@Overridepublic Object intercept(Invocation invocation) throws Throwable {Object[] args = invocation.getArgs();MappedStatement mappedStatement = (MappedStatement) args[0];SqlSource sqlSource = mappedStatement.getSqlSource();// 只攔截動態(tài)SQLif (sqlSource instanceof DynamicSqlSource) {// 獲取到sqlNode對象Field field = DynamicSqlSource.class.getDeclaredField("rootSqlNode");field.setAccessible(true);SqlNode sqlNode = (SqlNode) field.get(sqlSource);if (!sourceStorage.contains(sqlSource.hashCode())) {// 獲取動態(tài)代理對象Map<String, Object> argMap = (HashMap<String, Object>) args[1];// 判斷是否傳遞 schemaName或schema 如果已經(jīng)傳遞則使用用戶傳遞的值 否則使用默認值String schemaNameStr = "schemaName", schemaStr = "schema";if (StringUtils.isEmpty(MapUtils.getString(argMap, schemaNameStr)) && StringUtils.isEmpty(MapUtils.getString(argMap, schemaStr))) {SqlNode proxyNode = proxyNode(sqlNode);field.set(sqlSource, proxyNode);}sourceStorage.add(sqlSource.hashCode());}}return invocation.proceed();}/*** 通過動態(tài)代理對象 添加schema參數(shù)** @param sqlNode SQL節(jié)點* @return SqlNode*/private SqlNode proxyNode(SqlNode sqlNode) {return (SqlNode) Proxy.newProxyInstance(sqlNode.getClass().getClassLoader(),new Class[]{SqlNode.class}, new SqlNodeInvocationHandler(sqlNode));}@Overridepublic Object plugin(Object target) {return Plugin.wrap(target, this);}@Overridepublic void setProperties(Properties properties) {LOG.debug("setProperties====>" + properties);}private class SqlNodeInvocationHandler implements InvocationHandler {private SqlNode target;SqlNodeInvocationHandler(SqlNode target) {super();this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {DynamicContext context = (DynamicContext) args[0];// 給schema添加.setSchema(schema);// 設置schemacontext.getBindings().put(SCHEMA, schema);return method.invoke(target, args);}}/*** 給schema 添加.** @param schema schemaName*/private void setSchema(String schema) {String pointStr = ".";if (StringUtils.isNotBlank(schema)) {if (!schema.endsWith(pointStr)) {schema += pointStr;}}this.schema = schema;} }

2.2 攔截器注冊

攔截器【 2?? 注冊】給 SqlSessionFactoryBean 添加插件:

@Bean(name = "sqlSessionFactory_greenplum")@Primarypublic SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource_greenplum") DataSource dataSource)throws Exception {final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();// 設置數(shù)據(jù)源參數(shù)sessionFactory.setDataSource(dataSource);// mapper路徑和mybatis配置文件路徑sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(GreenplumConfiguration.MAPPER_LOCATION));sessionFactory.setConfigLocation(new ClassPathResource(mybatisConfigPath));// 添加自定義的schema攔截器【此次配置的重點】sessionFactory.setPlugins(new Interceptor[]{new SchemaInterceptor()});return sessionFactory.getObject();}

2.3 攔截器注入?yún)?shù)使用

注入【 3?? mapper.xml】這里使用 ${schemaName} 獲取配置的 schema 的值:

<!--執(zhí)行插入文件數(shù)據(jù)SQL--> <insert id="insertFileData" parameterType="map">insert into ${schemaName}${target_table}( ${table_field} ) VALUES ( ${field_value} ) </insert>

3. 總結(jié)

首先要注意的是,這里用的不是SpringMVC里的攔截器,而是mybatis的攔截器,攔截器是在執(zhí)行mapper文件內(nèi)的SQL前觸發(fā)的,此時,如果你傳遞了schema參數(shù),攔截器就不會覆蓋schema的值,如果沒有配置,則使用配置的默認值。

與50位技術專家面對面20年技術見證,附贈技術全景圖

總結(jié)

以上是生活随笔為你收集整理的【Java代码】使用 org.apache.ibatis.plugin.Interceptor 拦截器实现全局 mapper.xml 参数注入(可用于切换数据库实例schema+Demo举例源码)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 无码人妻丰满熟妇区五十路 | 色图综合| 极品蜜桃臀肥臀-x88av | 欧美二区视频 | 欧美午夜精品一区二区三区 | 欧美黄色短片 | 日韩午夜毛片 | 成人久久久久久久 | 熟女高潮一区二区三区视频 | 性做久久 | 嫩草影院在线观看视频 | 狠狠撸狠狠干 | 综合婷婷久久 | 日韩aⅴ在线观看 | 国产激情在线播放 | 久久人妻少妇嫩草av无码专区 | 久久久久久综合 | 亚洲伊人av | 国产又粗又黄视频 | 久久久九九九热 | 超碰在线观看免费版 | 91在线在线 | 亚日韩欧美 | 日本欧美一区二区 | 国产chinese男男gaygay视频 | 欧美最猛性xxxxx(亚洲精品) | 久久99精品国产.久久久久久 | 99国产超薄肉色丝袜交足 | 亚洲成人av | 国产精品探花一区二区在线观看 | 午夜色播| 开心激情久久 | 99国产在线观看 | 超碰97在线播放 | 五十路在线视频 | 免费观看av | 99这里只有精品 | 国产精品无码久久久久久 | 久久亚洲精品国产精品黑人v | 超碰成人久久 | 主人性调教le百合sm | 妞干网精品| 国产激情av一区二区三区 | 性色视频在线 | 久久99精品国产麻豆婷婷洗澡 | 狠狠躁夜夜躁人爽 | 国产精品一区不卡 | 中文字幕日韩精品一区 | 免费看欧美黑人毛片 | a视频在线观看免费 | 一本一本久久a久久精品综合麻豆 | 欧美日韩在线一区二区三区 | 亚洲区精品 | 天天夜夜人人 | 久久99深爱久久99精品 | 99日精品 | 精品一区二区三区电影 | 男女黄床上色视频免费的软件 | 黄色羞羞网站 | 欧美韩日国产 | 蜜桃精品久久久久久久免费影院 | 久久久老熟女一区二区三区91 | 无码一区二区波多野结衣播放搜索 | 亚洲AV不卡无码一区二区三区 | 精品久久久久久久久久久 | 国产精品无码专区av免费播放 | 国产美女精品在线 | 国产视频第三页 | 香蕉伊思人视频 | 亚洲男人天堂网站 | 免费在线看黄色片 | 日韩免费淫片 | 久久综合久久综合久久综合 | 国产亚洲欧洲 | 人人妻人人玩人人澡人人爽 | 爱插美女网 | 一本色道久久88综合无码 | 国产suv一区二区 | 午夜激情在线 | 深田咏美av在线 | 2021久久 | 亚洲第一视频在线 | 亚日韩| 午夜久久久久久噜噜噜噜 | 久草中文视频 | 色噜噜综合 | 精品少妇久久久久久888优播 | 天天操天天操 | 双腿张开被9个男人调教 | 99精品视频一区二区三区 | 国产激情综合 | 青青网站| 一级黄色片在线看 | 一二三区中文字幕 | 精品一区二区久久久 | 男女搞黄网站 | 欧美一级色 | 亚洲欧美日韩一区在线观看 | 欧美性xxxxxxxxx |