746 Star 2.8K Fork 834

abel533 / Mybatis_PageHelper

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
PageAutoDialect.java 14.61 KB
一键复制 编辑 原始数据 按行查看 历史
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2023 abel533@gmail.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.github.pagehelper.page;
import com.github.pagehelper.AutoDialect;
import com.github.pagehelper.Dialect;
import com.github.pagehelper.PageException;
import com.github.pagehelper.dialect.AbstractHelperDialect;
import com.github.pagehelper.dialect.auto.*;
import com.github.pagehelper.dialect.helper.*;
import com.github.pagehelper.util.ClassUtil;
import com.github.pagehelper.util.StringUtil;
import org.apache.ibatis.mapping.MappedStatement;
import javax.sql.DataSource;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;
/**
* 基础方言信息
*
* @author liuzh
*/
public class PageAutoDialect {
private static Map<String, Class<? extends Dialect>> dialectAliasMap = new LinkedHashMap<>();
private static Map<String, Class<? extends AutoDialect>> autoDialectMap = new LinkedHashMap<>();
public static void registerDialectAlias(String alias, Class<? extends Dialect> dialectClass) {
dialectAliasMap.put(alias, dialectClass);
}
static {
//注册别名
registerDialectAlias("hsqldb", HsqldbDialect.class);
registerDialectAlias("h2", HsqldbDialect.class);
registerDialectAlias("phoenix", HsqldbDialect.class);
registerDialectAlias("postgresql", PostgreSqlDialect.class);
registerDialectAlias("mysql", MySqlDialect.class);
registerDialectAlias("mariadb", MySqlDialect.class);
registerDialectAlias("sqlite", MySqlDialect.class);
registerDialectAlias("herddb", HerdDBDialect.class);
registerDialectAlias("oracle", OracleDialect.class);
registerDialectAlias("oracle9i", Oracle9iDialect.class);
registerDialectAlias("db2", Db2Dialect.class);
registerDialectAlias("as400", AS400Dialect.class);
registerDialectAlias("informix", InformixDialect.class);
//解决 informix-sqli #129,仍然保留上面的
registerDialectAlias("informix-sqli", InformixDialect.class);
registerDialectAlias("sqlserver", SqlServerDialect.class);
registerDialectAlias("sqlserver2012", SqlServer2012Dialect.class);
registerDialectAlias("derby", SqlServer2012Dialect.class);
//达梦数据库,https://github.com/mybatis-book/book/issues/43
registerDialectAlias("dm", OracleDialect.class);
//阿里云PPAS数据库,https://github.com/pagehelper/Mybatis-PageHelper/issues/281
registerDialectAlias("edb", OracleDialect.class);
//神通数据库
registerDialectAlias("oscar", OscarDialect.class);
registerDialectAlias("clickhouse", MySqlDialect.class);
//瀚高数据库
registerDialectAlias("highgo", HsqldbDialect.class);
//虚谷数据库
registerDialectAlias("xugu", HsqldbDialect.class);
registerDialectAlias("impala", HsqldbDialect.class);
registerDialectAlias("firebirdsql", FirebirdDialect.class);
//人大金仓数据库
registerDialectAlias("kingbase", PostgreSqlDialect.class);
// 人大金仓新版本kingbase8
registerDialectAlias("kingbase8", PostgreSqlDialect.class);
//行云数据库
registerDialectAlias("xcloud", CirroDataDialect.class);
//openGauss数据库
registerDialectAlias("opengauss", PostgreSqlDialect.class);
//注册 AutoDialect
//想要实现和以前版本相同的效果时,可以配置 autoDialectClass=old
registerAutoDialectAlias("old", DefaultAutoDialect.class);
registerAutoDialectAlias("hikari", HikariAutoDialect.class);
registerAutoDialectAlias("druid", DruidAutoDialect.class);
registerAutoDialectAlias("tomcat-jdbc", TomcatAutoDialect.class);
registerAutoDialectAlias("dbcp", DbcpAutoDialect.class);
registerAutoDialectAlias("c3p0", C3P0AutoDialect.class);
//不配置时,默认使用 DataSourceNegotiationAutoDialect
registerAutoDialectAlias("default", DataSourceNegotiationAutoDialect.class);
}
public static void registerAutoDialectAlias(String alias, Class<? extends AutoDialect> autoDialectClass) {
autoDialectMap.put(alias, autoDialectClass);
}
/**
* 自动获取dialect,如果没有setProperties或setSqlUtilConfig,也可以正常进行
*/
private boolean autoDialect = true;
/**
* 属性配置
*/
private Properties properties;
/**
* 缓存 dialect 实现,key 有两种,分别为 jdbcurl 和 dialectClassName
*/
private Map<Object, AbstractHelperDialect> urlDialectMap = new ConcurrentHashMap<Object, AbstractHelperDialect>();
private ReentrantLock lock = new ReentrantLock();
private AbstractHelperDialect delegate;
private ThreadLocal<AbstractHelperDialect> dialectThreadLocal = new ThreadLocal<AbstractHelperDialect>();
private AutoDialect autoDialectDelegate;
public static String fromJdbcUrl(String jdbcUrl) {
final String url = jdbcUrl.toLowerCase();
for (String dialect : dialectAliasMap.keySet()) {
if (url.contains(":" + dialect.toLowerCase() + ":")) {
return dialect;
}
}
return null;
}
//获取当前的代理对象
public AbstractHelperDialect getDelegate() {
if (delegate != null) {
return delegate;
}
return dialectThreadLocal.get();
}
//移除代理对象
public void clearDelegate() {
dialectThreadLocal.remove();
}
public AbstractHelperDialect getDialectThreadLocal() {
return dialectThreadLocal.get();
}
public void setDialectThreadLocal(AbstractHelperDialect delegate) {
this.dialectThreadLocal.set(delegate);
}
/**
* 反射类
*
* @param className
* @return
* @throws Exception
*/
public static Class resloveDialectClass(String className) throws Exception {
if (dialectAliasMap.containsKey(className.toLowerCase())) {
return dialectAliasMap.get(className.toLowerCase());
} else {
return Class.forName(className);
}
}
/**
* 初始化 helper
*
* @param dialectClass
* @param properties
*/
public static AbstractHelperDialect instanceDialect(String dialectClass, Properties properties) {
AbstractHelperDialect dialect;
if (StringUtil.isEmpty(dialectClass)) {
throw new PageException("When you use the PageHelper pagination plugin, you must set the helper property");
}
try {
Class sqlDialectClass = resloveDialectClass(dialectClass);
if (AbstractHelperDialect.class.isAssignableFrom(sqlDialectClass)) {
dialect = (AbstractHelperDialect) sqlDialectClass.newInstance();
} else {
throw new PageException("When using PageHelper, the dialect must be an implementation class that implements the " + AbstractHelperDialect.class.getCanonicalName() + " interface!");
}
} catch (Exception e) {
throw new PageException("error initializing helper dialectclass[" + dialectClass + "]" + e.getMessage(), e);
}
dialect.setProperties(properties);
return dialect;
}
/**
* 多数据动态获取时,每次需要初始化,还可以运行时指定具体的实现
*
* @param ms
* @param dialectClass 分页实现,必须是 {@link AbstractHelperDialect} 实现类,可以使用当前类中注册的别名,例如 "mysql", "oracle"
*/
public void initDelegateDialect(MappedStatement ms, String dialectClass) {
if (StringUtil.isNotEmpty(dialectClass)) {
AbstractHelperDialect dialect = urlDialectMap.get(dialectClass);
if (dialect == null) {
lock.lock();
try {
if ((dialect = urlDialectMap.get(dialectClass)) == null) {
dialect = instanceDialect(dialectClass, properties);
urlDialectMap.put(dialectClass, dialect);
}
} finally {
lock.unlock();
}
}
dialectThreadLocal.set(dialect);
} else if (delegate == null) {
if (autoDialect) {
this.delegate = autoGetDialect(ms);
} else {
dialectThreadLocal.set(autoGetDialect(ms));
}
}
}
/**
* 自动获取分页方言实现
*
* @param ms
* @return
*/
public AbstractHelperDialect autoGetDialect(MappedStatement ms) {
DataSource dataSource = ms.getConfiguration().getEnvironment().getDataSource();
Object dialectKey = autoDialectDelegate.extractDialectKey(ms, dataSource, properties);
if (dialectKey == null) {
return autoDialectDelegate.extractDialect(dialectKey, ms, dataSource, properties);
} else if (!urlDialectMap.containsKey(dialectKey)) {
lock.lock();
try {
if (!urlDialectMap.containsKey(dialectKey)) {
urlDialectMap.put(dialectKey, autoDialectDelegate.extractDialect(dialectKey, ms, dataSource, properties));
}
} finally {
lock.unlock();
}
}
return urlDialectMap.get(dialectKey);
}
/**
* 初始化自定义 AutoDialect
*
* @param properties
*/
private void initAutoDialectClass(Properties properties) {
String autoDialectClassStr = properties.getProperty("autoDialectClass");
if (StringUtil.isNotEmpty(autoDialectClassStr)) {
try {
Class<? extends AutoDialect> autoDialectClass;
if (autoDialectMap.containsKey(autoDialectClassStr)) {
autoDialectClass = autoDialectMap.get(autoDialectClassStr);
} else {
autoDialectClass = (Class<AutoDialect>) Class.forName(autoDialectClassStr);
}
this.autoDialectDelegate = ClassUtil.newInstance(autoDialectClass, properties);
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("Make sure that the AutoDialect implementation class ("
+ autoDialectClassStr + ") for the autoDialectClass configuration exists!", e);
} catch (Exception e) {
throw new RuntimeException(autoDialectClassStr + "Class must provide a constructor without parameters", e);
}
} else {
this.autoDialectDelegate = new DataSourceNegotiationAutoDialect();
}
}
/**
* 初始化方言别名
*
* @param properties
*/
private void initDialectAlias(Properties properties) {
String dialectAlias = properties.getProperty("dialectAlias");
if (StringUtil.isNotEmpty(dialectAlias)) {
String[] alias = dialectAlias.split(";");
for (int i = 0; i < alias.length; i++) {
String[] kv = alias[i].split("=");
if (kv.length != 2) {
throw new IllegalArgumentException("dialectAlias parameter misconfigured," +
"Please follow alias1=xx.dialectClass; alias2=dialectClass2!");
}
for (int j = 0; j < kv.length; j++) {
try {
//允许配置如 dm=oracle, 直接引用oracle实现
if (dialectAliasMap.containsKey(kv[1])) {
registerDialectAlias(kv[0], dialectAliasMap.get(kv[1]));
} else {
Class<? extends Dialect> diallectClass = (Class<? extends Dialect>) Class.forName(kv[1]);
//允许覆盖已有的实现
registerDialectAlias(kv[0], diallectClass);
}
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("Make sure the Dialect implementation class configured by dialectAlias exists!", e);
}
}
}
}
}
public void setProperties(Properties properties) {
this.properties = properties;
//初始化自定义AutoDialect
initAutoDialectClass(properties);
//使用 sqlserver2012 作为默认分页方式,这种情况在动态数据源时方便使用
String useSqlserver2012 = properties.getProperty("useSqlserver2012");
if (StringUtil.isNotEmpty(useSqlserver2012) && Boolean.parseBoolean(useSqlserver2012)) {
registerDialectAlias("sqlserver", SqlServer2012Dialect.class);
registerDialectAlias("sqlserver2008", SqlServerDialect.class);
}
initDialectAlias(properties);
//指定的 Helper 数据库方言,和 不同
String dialect = properties.getProperty("helperDialect");
//运行时获取数据源
String runtimeDialect = properties.getProperty("autoRuntimeDialect");
//1.动态多数据源
if (StringUtil.isNotEmpty(runtimeDialect) && "TRUE".equalsIgnoreCase(runtimeDialect)) {
this.autoDialect = false;
}
//2.动态获取方言
else if (StringUtil.isEmpty(dialect)) {
autoDialect = true;
}
//3.指定方言
else {
autoDialect = false;
this.delegate = instanceDialect(dialect, properties);
}
}
}
Java
1
https://gitee.com/free/Mybatis_PageHelper.git
git@gitee.com:free/Mybatis_PageHelper.git
free
Mybatis_PageHelper
Mybatis_PageHelper
master

搜索帮助