Merge branch 'mybatis-flex:main' into main

This commit is contained in:
Jiabin Zhuang 2023-05-30 22:57:14 +08:00 committed by GitHub
commit d00c2a2599
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
45 changed files with 691 additions and 611 deletions

View File

@ -1,3 +1,21 @@
mybatis-flex v1.3.3 20230530:
新增:添加动态表名和动态 Schema 的支持 #I6VRMF #I6WS3E #I72X21
新增:添加 @Table(schema=xxx) 配置的支持 #I6VD6U
新增Left join 等关联查询时,支持直接赋值对象属性的功能
新增:添加 QueryWrapper.toDebugSQL() 方法,方便用于调试
优化Entity 父子类定义了相同字段时,应已子类优先
优化:对逻辑删除定义的非 Number 和 Bool 类型的 SQL 构建优化
优化:升级 MyBatis 到 3.5.13 最新版本
优化:升级 MyBatis 后,删除冗余的 FlexXMLConfigBuilder 实现
优化:升级 solon 版本,以支持原生编译功能,感谢 @西东
修复:分页查询在 left join 优化是,错误移除的问题
文档:优化 多表查询 的相关文档
文档:添加枚举属性构建 QueryWrapper 的相关文档
文档:添加自定义 MyBatis 的 Configuration 的文档
文档:添加动态表名和动态 Schema 的相关文档
mybatis-flex v1.3.2 20230528: mybatis-flex v1.3.2 20230528:
新增select (field1 * field2 * 100) as xxx from ... 的 SQL 构建场景 新增select (field1 * field2 * 100) as xxx from ... 的 SQL 构建场景
优化ClassUtil.wrap 方法修改为 getWrapType 优化ClassUtil.wrap 方法修改为 getWrapType

View File

@ -1,2 +0,0 @@
# gpgconf --kill gpg-agent
mvn deploy -pl "parent,mybatis-flex-annotation,mybatis-flex-codegen,mybatis-flex-core,mybatis-flex-spring,mybatis-flex-spring-boot-starter" -e -P release

View File

@ -87,6 +87,7 @@ export default defineConfig({
{text: '字段加密', link: '/zh/core/columns-encrypt'}, {text: '字段加密', link: '/zh/core/columns-encrypt'},
{text: '字典回写', link: '/zh/core/columns-dict'}, {text: '字典回写', link: '/zh/core/columns-dict'},
{text: '枚举属性', link: '/zh/core/enum-property'}, {text: '枚举属性', link: '/zh/core/enum-property'},
{text: '动态表名', link: '/zh/core/dynamic-table'},
{text: '多租户', link: '/zh/core/multi-tenancy'}, {text: '多租户', link: '/zh/core/multi-tenancy'},
] ]
}, },

View File

@ -0,0 +1,46 @@
# 动态表名
动态表名指的是用户在对数据进行 增删改查 的时候,传入表名能够根据上下文信息(比如用户信息、应用信息)等,动态修改当前的表。
## 使用场景
- 1、多租户不同的租户拥有不同的表
- 2、分库分表减轻数据压力
## 如何使用
在应用启动时,通过调用 `TableManager.setDynamicTableProcessor()` 配置动态表名处理器 `DynamicTableProcessor` 即可,如下代码所示:
```java
TableManager.setDynamicTableProcessor(new DynamicTableProcessor() {
@Override
public String process(String tableName) {
return tableName + "_01";
}
});
```
通过以上配置后我们对数据库进行增删改查MyBatis-Flex 都会调用 `DynamicTableProcessor.process` 方法,获得最新的表名进行 SQL 构建操作。因此,我们应该在 `process` 方法中,
判断当前的上下文(用户信息、应用信息)等,动态的返回对应的表名。
在某些情况下,我们临时修改映射关系,而非通过 `DynamicTableProcessor.process` 方法获取,可以通过如下配置:
```java
TableManager.setHintTableMapping("tb_account", "tb_account_01")
```
那么此时,当前线程不再通过 `DynamicTableProcessor` 去获取。
## 动态 Schema
动态 Schema 和动态表名类似,通过 `TableManager.setDynamicSchemaProcessor()` 配置动态 Schema 处理器 `DynamicSchemaProcessor` 即可,如下代码所示:
```java
TableManager.setDynamicSchemaProcessor(new DynamicSchemaProcessor() {
@Override
public String process(String schema) {
return schema + "_01";
}
});
```
动态 Schema 的配置,只对使用了注解 `@Table(schema="xxx")` 的 Entity 有效。

View File

@ -27,12 +27,12 @@ Maven示例
<dependency> <dependency>
<groupId>com.mybatis-flex</groupId> <groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-core</artifactId> <artifactId>mybatis-flex-core</artifactId>
<version>1.3.2</version> <version>1.3.3</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.mybatis-flex</groupId> <groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-processor</artifactId> <artifactId>mybatis-flex-processor</artifactId>
<version>1.3.2</version> <version>1.3.3</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
``` ```
@ -46,7 +46,7 @@ Gradle示例
```groovy ```groovy
// file: build.gradle // file: build.gradle
ext { ext {
mybatis_flex_version = '1.3.2' mybatis_flex_version = '1.3.3'
} }
dependencies { dependencies {
implementation("com.mybatis-flex:mybatis-flex-core:${mybatis_flex_version}") implementation("com.mybatis-flex:mybatis-flex-core:${mybatis_flex_version}")

View File

@ -12,12 +12,12 @@
<dependency> <dependency>
<groupId>com.mybatis-flex</groupId> <groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-core</artifactId> <artifactId>mybatis-flex-core</artifactId>
<version>1.3.2</version> <version>1.3.3</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.mybatis-flex</groupId> <groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-processor</artifactId> <artifactId>mybatis-flex-processor</artifactId>
<version>1.3.2</version> <version>1.3.3</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
``` ```
@ -28,12 +28,12 @@
<dependency> <dependency>
<groupId>com.mybatis-flex</groupId> <groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring</artifactId> <artifactId>mybatis-flex-spring</artifactId>
<version>1.3.2</version> <version>1.3.3</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.mybatis-flex</groupId> <groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-processor</artifactId> <artifactId>mybatis-flex-processor</artifactId>
<version>1.3.2</version> <version>1.3.3</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
`````` ``````
@ -44,12 +44,12 @@
<dependency> <dependency>
<groupId>com.mybatis-flex</groupId> <groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring-boot-starter</artifactId> <artifactId>mybatis-flex-spring-boot-starter</artifactId>
<version>1.3.2</version> <version>1.3.3</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.mybatis-flex</groupId> <groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-processor</artifactId> <artifactId>mybatis-flex-processor</artifactId>
<version>1.3.2</version> <version>1.3.3</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
``` ```
@ -70,7 +70,7 @@
<path> <path>
<groupId>com.mybatis-flex</groupId> <groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-processor</artifactId> <artifactId>mybatis-flex-processor</artifactId>
<version>1.3.2</version> <version>1.3.3</version>
</path> </path>
</annotationProcessorPaths> </annotationProcessorPaths>
</configuration> </configuration>

View File

@ -179,7 +179,7 @@ processor.baseMapperClass=com.domain.mapper.MyBaseMapper
``` ```
dependencies { dependencies {
... ...
annotationProcessor 'com.mybatis-flex:mybatis-flex-processor:1.3.2' annotationProcessor 'com.mybatis-flex:mybatis-flex-processor:1.3.3'
} }
``` ```

View File

@ -10,7 +10,7 @@
<dependency> <dependency>
<groupId>com.mybatis-flex</groupId> <groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-codegen</artifactId> <artifactId>mybatis-flex-codegen</artifactId>
<version>1.3.2</version> <version>1.3.3</version>
</dependency> </dependency>
``` ```

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>parent</artifactId> <artifactId>parent</artifactId>
<groupId>com.mybatis-flex</groupId> <groupId>com.mybatis-flex</groupId>
<version>1.3.2</version> <version>1.3.3</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>parent</artifactId> <artifactId>parent</artifactId>
<groupId>com.mybatis-flex</groupId> <groupId>com.mybatis-flex</groupId>
<version>1.3.2</version> <version>1.3.3</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@ -27,7 +27,7 @@
<dependency> <dependency>
<groupId>com.mybatis-flex</groupId> <groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring</artifactId> <artifactId>mybatis-flex-spring</artifactId>
<version>1.3.2</version> <version>1.3.3</version>
</dependency> </dependency>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>parent</artifactId> <artifactId>parent</artifactId>
<groupId>com.mybatis-flex</groupId> <groupId>com.mybatis-flex</groupId>
<version>1.3.2</version> <version>1.3.3</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@ -22,13 +22,13 @@
<dependency> <dependency>
<groupId>com.mybatis-flex</groupId> <groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-annotation</artifactId> <artifactId>mybatis-flex-annotation</artifactId>
<version>1.3.2</version> <version>1.3.3</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.mybatis-flex</groupId> <groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-processor</artifactId> <artifactId>mybatis-flex-processor</artifactId>
<version>1.3.2</version> <version>1.3.3</version>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -20,7 +20,7 @@ package com.mybatisflex.core;
*/ */
public class FlexConsts { public class FlexConsts {
public static final String NAME = "MyBatis-Flex"; public static final String NAME = "MyBatis-Flex";
public static final String VERSION = "1.3.2"; public static final String VERSION = "1.3.3";
public static final String DEFAULT_PRIMARY_FIELD = "id"; public static final String DEFAULT_PRIMARY_FIELD = "id";

View File

@ -17,20 +17,17 @@ package com.mybatisflex.core.audit;
import com.mybatisflex.core.mybatis.TypeHandlerObject; import com.mybatisflex.core.mybatis.TypeHandlerObject;
import com.mybatisflex.core.util.ClassUtil; import com.mybatisflex.core.util.ClassUtil;
import com.mybatisflex.core.util.DateUtil; import com.mybatisflex.core.util.SqlUtil;
import java.io.Serializable; import java.io.Serializable;
import java.lang.reflect.Array; import java.lang.reflect.Array;
import java.lang.reflect.Proxy; import java.lang.reflect.Proxy;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.SQLException; import java.sql.SQLException;
import java.time.LocalDateTime;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.regex.Matcher;
public class AuditMessage implements Serializable { public class AuditMessage implements Serializable {
@ -147,37 +144,11 @@ public class AuditMessage implements Serializable {
} }
public String getFullSql() { public String getFullSql() {
String sql = getQuery(); List<Object> queryParams = getQueryParams();
List<Object> params = getQueryParams(); return SqlUtil.replaceSqlParams(getQuery(), queryParams == null ? null : queryParams.toArray());
if (params != null) {
for (Object value : params) {
// null
if (value == null) {
sql = sql.replaceFirst("\\?", "null");
}
// number
else if (value instanceof Number || value instanceof Boolean) {
sql = sql.replaceFirst("\\?", value.toString());
}
// other
else {
StringBuilder sb = new StringBuilder();
sb.append("'");
if (value instanceof Date) {
sb.append(DateUtil.toDateTimeString((Date) value));
} else if (value instanceof LocalDateTime) {
sb.append(DateUtil.toDateTimeString(DateUtil.toDate((LocalDateTime) value)));
} else {
sb.append(value);
}
sb.append("'");
sql = sql.replaceFirst("\\?", Matcher.quoteReplacement(sb.toString()));
}
}
}
return sql;
} }
private PreparedStatement createPreparedStatement() { private PreparedStatement createPreparedStatement() {
return (PreparedStatement) Proxy.newProxyInstance( return (PreparedStatement) Proxy.newProxyInstance(
AuditMessage.class.getClassLoader(), AuditMessage.class.getClassLoader(),

View File

@ -18,6 +18,7 @@ package com.mybatisflex.core.dialect;
import com.mybatisflex.core.query.QueryWrapper; import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.row.Row; import com.mybatisflex.core.row.Row;
import com.mybatisflex.core.table.TableInfo; import com.mybatisflex.core.table.TableInfo;
import com.mybatisflex.core.table.TableManager;
import java.util.List; import java.util.List;
@ -25,6 +26,14 @@ public interface IDialect {
String wrap(String keyword); String wrap(String keyword);
default String getRealTable(String table) {
return TableManager.getRealTable(table);
}
default String getRealSchema(String schema) {
return TableManager.getRealSchema(schema);
}
String forHint(String hintString); String forHint(String hintString);
String forInsertRow(String tableName, Row row); String forInsertRow(String tableName, Row row);
@ -54,7 +63,6 @@ public interface IDialect {
String buildWhereConditionSql(QueryWrapper queryWrapper); String buildWhereConditionSql(QueryWrapper queryWrapper);
//////for entity ///// //////for entity /////
String forInsertEntity(TableInfo tableInfo, Object entity, boolean ignoreNulls); String forInsertEntity(TableInfo tableInfo, Object entity, boolean ignoreNulls);

View File

@ -59,6 +59,7 @@ public class CommonsDialectImpl implements IDialect {
return "*".equals(keyword) ? keyword : keywordWrap.wrap(keyword); return "*".equals(keyword) ? keyword : keywordWrap.wrap(keyword);
} }
@Override @Override
public String forHint(String hintString) { public String forHint(String hintString) {
return StringUtil.isNotBlank(hintString) ? "/*+ " + hintString + " */ " : ""; return StringUtil.isNotBlank(hintString) ? "/*+ " + hintString + " */ " : "";
@ -81,7 +82,7 @@ public class CommonsDialectImpl implements IDialect {
index++; index++;
} }
String sql = "INSERT INTO " + wrap(tableName) + String sql = "INSERT INTO " + wrap(getRealTable(tableName)) +
"(" + fields + ") VALUES " + "(" + fields + ") VALUES " +
"(" + questions + ")"; "(" + questions + ")";
return sql; return sql;
@ -111,7 +112,7 @@ public class CommonsDialectImpl implements IDialect {
} }
} }
String sql = "INSERT INTO " + wrap(tableName) + String sql = "INSERT INTO " + wrap(getRealTable(tableName)) +
"(" + fields + ") VALUES " + questions; "(" + fields + ") VALUES " + questions;
return sql; return sql;
} }
@ -121,7 +122,7 @@ public class CommonsDialectImpl implements IDialect {
public String forDeleteById(String tableName, String[] primaryKeys) { public String forDeleteById(String tableName, String[] primaryKeys) {
StringBuilder sql = new StringBuilder(); StringBuilder sql = new StringBuilder();
sql.append("DELETE FROM "); sql.append("DELETE FROM ");
sql.append(wrap(tableName)); sql.append(wrap(getRealTable(tableName)));
sql.append(" WHERE "); sql.append(" WHERE ");
for (int i = 0; i < primaryKeys.length; i++) { for (int i = 0; i < primaryKeys.length; i++) {
if (i > 0) { if (i > 0) {
@ -137,7 +138,7 @@ public class CommonsDialectImpl implements IDialect {
public String forDeleteBatchByIds(String tableName, String[] primaryKeys, Object[] ids) { public String forDeleteBatchByIds(String tableName, String[] primaryKeys, Object[] ids) {
StringBuilder sql = new StringBuilder(); StringBuilder sql = new StringBuilder();
sql.append("DELETE FROM "); sql.append("DELETE FROM ");
sql.append(wrap(tableName)); sql.append(wrap(getRealTable(tableName)));
sql.append(" WHERE "); sql.append(" WHERE ");
//多主键的场景 //多主键的场景
@ -180,7 +181,7 @@ public class CommonsDialectImpl implements IDialect {
Set<String> modifyAttrs = row.obtainModifyAttrs(); Set<String> modifyAttrs = row.obtainModifyAttrs();
String[] primaryKeys = RowCPI.obtainsPrimaryKeyStrings(row); String[] primaryKeys = RowCPI.obtainsPrimaryKeyStrings(row);
sql.append("UPDATE ").append(wrap(tableName)).append(" SET "); sql.append("UPDATE ").append(wrap(getRealTable(tableName))).append(" SET ");
int index = 0; int index = 0;
for (Map.Entry<String, Object> e : row.entrySet()) { for (Map.Entry<String, Object> e : row.entrySet()) {
String colName = e.getKey(); String colName = e.getKey();
@ -215,7 +216,7 @@ public class CommonsDialectImpl implements IDialect {
} }
String tableName = queryTables.get(0).getName(); String tableName = queryTables.get(0).getName();
sql.append("UPDATE ").append(wrap(tableName)).append(" SET "); sql.append("UPDATE ").append(wrap(getRealTable(tableName))).append(" SET ");
int index = 0; int index = 0;
for (String modifyAttr : modifyAttrs) { for (String modifyAttr : modifyAttrs) {
if (index > 0) { if (index > 0) {
@ -249,7 +250,7 @@ public class CommonsDialectImpl implements IDialect {
@Override @Override
public String forSelectOneById(String tableName, String[] primaryKeys, Object[] primaryValues) { public String forSelectOneById(String tableName, String[] primaryKeys, Object[] primaryValues) {
StringBuilder sql = new StringBuilder("SELECT * FROM "); StringBuilder sql = new StringBuilder("SELECT * FROM ");
sql.append(wrap(tableName)).append(" WHERE "); sql.append(wrap(getRealTable(tableName))).append(" WHERE ");
for (int i = 0; i < primaryKeys.length; i++) { for (int i = 0; i < primaryKeys.length; i++) {
if (i > 0) { if (i > 0) {
sql.append(" AND "); sql.append(" AND ");
@ -875,7 +876,7 @@ public class CommonsDialectImpl implements IDialect {
|| normalValueOfLogicDelete instanceof Boolean) { || normalValueOfLogicDelete instanceof Boolean) {
return normalValueOfLogicDelete; return normalValueOfLogicDelete;
} }
return "'" + normalValueOfLogicDelete.toString() + "'"; return "'" + normalValueOfLogicDelete + "'";
} }
@ -885,7 +886,7 @@ public class CommonsDialectImpl implements IDialect {
|| deletedValueOfLogicDelete instanceof Boolean) { || deletedValueOfLogicDelete instanceof Boolean) {
return deletedValueOfLogicDelete; return deletedValueOfLogicDelete;
} }
return "'" + deletedValueOfLogicDelete.toString() + "'"; return "'" + deletedValueOfLogicDelete + "'";
} }
} }

View File

@ -20,6 +20,7 @@ import com.mybatisflex.core.FlexGlobalConfig;
import com.mybatisflex.core.dialect.DbType; import com.mybatisflex.core.dialect.DbType;
import com.mybatisflex.core.dialect.DbTypeUtil; import com.mybatisflex.core.dialect.DbTypeUtil;
import com.mybatisflex.core.exception.FlexExceptions; import com.mybatisflex.core.exception.FlexExceptions;
import org.apache.ibatis.builder.xml.XMLConfigBuilder;
import org.apache.ibatis.exceptions.ExceptionFactory; import org.apache.ibatis.exceptions.ExceptionFactory;
import org.apache.ibatis.executor.ErrorContext; import org.apache.ibatis.executor.ErrorContext;
import org.apache.ibatis.session.Configuration; import org.apache.ibatis.session.Configuration;
@ -28,14 +29,39 @@ import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.Reader;
import java.util.Properties; import java.util.Properties;
public class FlexSqlSessionFactoryBuilder extends SqlSessionFactoryBuilder { public class FlexSqlSessionFactoryBuilder extends SqlSessionFactoryBuilder {
@Override
public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
try {
// 需要 mybaits v3.5.13+
// https://github.com/mybatis/mybatis-3/commit/d7826d71a7005a8b4d4e0e7a020db0f6c7e253a4
XMLConfigBuilder parser = new XMLConfigBuilder(FlexConfiguration.class, reader, environment, properties);
return build(parser.parse());
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error building SqlSession.", e);
} finally {
ErrorContext.instance().reset();
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
// Intentionally ignore. Prefer previous error.
}
}
}
@Override @Override
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) { public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
try { try {
FlexXMLConfigBuilder parser = new FlexXMLConfigBuilder(inputStream, environment, properties); // 需要 mybaits v3.5.13+
// https://github.com/mybatis/mybatis-3/commit/d7826d71a7005a8b4d4e0e7a020db0f6c7e253a4
XMLConfigBuilder parser = new XMLConfigBuilder(FlexConfiguration.class, inputStream, environment, properties);
return build(parser.parse()); return build(parser.parse());
} catch (Exception e) { } catch (Exception e) {
throw ExceptionFactory.wrapException("Error building SqlSession.", e); throw ExceptionFactory.wrapException("Error building SqlSession.", e);

View File

@ -1,409 +0,0 @@
/**
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mybatisflex.core.mybatis;
import org.apache.ibatis.builder.BaseBuilder;
import org.apache.ibatis.builder.BuilderException;
import org.apache.ibatis.builder.xml.XMLMapperBuilder;
import org.apache.ibatis.builder.xml.XMLMapperEntityResolver;
import org.apache.ibatis.datasource.DataSourceFactory;
import org.apache.ibatis.executor.ErrorContext;
import org.apache.ibatis.executor.loader.ProxyFactory;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.io.VFS;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.mapping.DatabaseIdProvider;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.parsing.XNode;
import org.apache.ibatis.parsing.XPathParser;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.reflection.DefaultReflectorFactory;
import org.apache.ibatis.reflection.MetaClass;
import org.apache.ibatis.reflection.ReflectorFactory;
import org.apache.ibatis.reflection.factory.ObjectFactory;
import org.apache.ibatis.reflection.wrapper.ObjectWrapperFactory;
import org.apache.ibatis.session.*;
import org.apache.ibatis.transaction.TransactionFactory;
import org.apache.ibatis.type.JdbcType;
import javax.sql.DataSource;
import java.io.InputStream;
import java.io.Reader;
import java.util.Properties;
/**
* @author Clinton Begin
* @author Kazuki Shimizu
*/
public class FlexXMLConfigBuilder extends BaseBuilder {
private boolean parsed;
private final XPathParser parser;
private String environment;
private final ReflectorFactory localReflectorFactory = new DefaultReflectorFactory();
public FlexXMLConfigBuilder(Reader reader) {
this(reader, null, null);
}
public FlexXMLConfigBuilder(Reader reader, String environment) {
this(reader, environment, null);
}
public FlexXMLConfigBuilder(Reader reader, String environment, Properties props) {
this(new XPathParser(reader, true, props, new XMLMapperEntityResolver()), environment, props);
}
public FlexXMLConfigBuilder(InputStream inputStream) {
this(inputStream, null, null);
}
public FlexXMLConfigBuilder(InputStream inputStream, String environment) {
this(inputStream, environment, null);
}
public FlexXMLConfigBuilder(InputStream inputStream, String environment, Properties props) {
this(new XPathParser(inputStream, true, props, new XMLMapperEntityResolver()), environment, props);
}
private FlexXMLConfigBuilder(XPathParser parser, String environment, Properties props) {
// 目前暂时只能通过这里替换 configuration
// 新的版本已经支持自定义 configuration但需新版本 release
// 详情 https://github.com/mybatis/mybatis-3/commit/d7826d71a7005a8b4d4e0e7a020db0f6c7e253a4
super(new FlexConfiguration());
ErrorContext.instance().resource("SQL Mapper Configuration");
this.configuration.setVariables(props);
this.parsed = false;
this.environment = environment;
this.parser = parser;
}
public Configuration parse() {
if (parsed) {
throw new BuilderException("Each XMLConfigBuilder can only be used once.");
}
parsed = true;
parseConfiguration(parser.evalNode("/configuration"));
return configuration;
}
private void parseConfiguration(XNode root) {
try {
// issue #117 read properties first
propertiesElement(root.evalNode("properties"));
Properties settings = settingsAsProperties(root.evalNode("settings"));
loadCustomVfs(settings);
loadCustomLogImpl(settings);
typeAliasesElement(root.evalNode("typeAliases"));
pluginElement(root.evalNode("plugins"));
objectFactoryElement(root.evalNode("objectFactory"));
objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
reflectorFactoryElement(root.evalNode("reflectorFactory"));
settingsElement(settings);
// read it after objectFactory and objectWrapperFactory issue #631
environmentsElement(root.evalNode("environments"));
databaseIdProviderElement(root.evalNode("databaseIdProvider"));
typeHandlerElement(root.evalNode("typeHandlers"));
mapperElement(root.evalNode("mappers"));
} catch (Exception e) {
throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
}
}
private Properties settingsAsProperties(XNode context) {
if (context == null) {
return new Properties();
}
Properties props = context.getChildrenAsProperties();
// Check that all settings are known to the configuration class
MetaClass metaConfig = MetaClass.forClass(Configuration.class, localReflectorFactory);
for (Object key : props.keySet()) {
if (!metaConfig.hasSetter(String.valueOf(key))) {
throw new BuilderException("The setting " + key + " is not known. Make sure you spelled it correctly (case sensitive).");
}
}
return props;
}
private void loadCustomVfs(Properties props) throws ClassNotFoundException {
String value = props.getProperty("vfsImpl");
if (value != null) {
String[] clazzes = value.split(",");
for (String clazz : clazzes) {
if (!clazz.isEmpty()) {
@SuppressWarnings("unchecked")
Class<? extends VFS> vfsImpl = (Class<? extends VFS>)Resources.classForName(clazz);
configuration.setVfsImpl(vfsImpl);
}
}
}
}
private void loadCustomLogImpl(Properties props) {
Class<? extends Log> logImpl = resolveClass(props.getProperty("logImpl"));
configuration.setLogImpl(logImpl);
}
private void typeAliasesElement(XNode parent) {
if (parent != null) {
for (XNode child : parent.getChildren()) {
if ("package".equals(child.getName())) {
String typeAliasPackage = child.getStringAttribute("name");
configuration.getTypeAliasRegistry().registerAliases(typeAliasPackage);
} else {
String alias = child.getStringAttribute("alias");
String type = child.getStringAttribute("type");
try {
Class<?> clazz = Resources.classForName(type);
if (alias == null) {
typeAliasRegistry.registerAlias(clazz);
} else {
typeAliasRegistry.registerAlias(alias, clazz);
}
} catch (ClassNotFoundException e) {
throw new BuilderException("Error registering typeAlias for '" + alias + "'. Cause: " + e, e);
}
}
}
}
}
private void pluginElement(XNode parent) throws Exception {
if (parent != null) {
for (XNode child : parent.getChildren()) {
String interceptor = child.getStringAttribute("interceptor");
Properties properties = child.getChildrenAsProperties();
Interceptor interceptorInstance = (Interceptor) resolveClass(interceptor).getDeclaredConstructor().newInstance();
interceptorInstance.setProperties(properties);
configuration.addInterceptor(interceptorInstance);
}
}
}
private void objectFactoryElement(XNode context) throws Exception {
if (context != null) {
String type = context.getStringAttribute("type");
Properties properties = context.getChildrenAsProperties();
ObjectFactory factory = (ObjectFactory) resolveClass(type).getDeclaredConstructor().newInstance();
factory.setProperties(properties);
configuration.setObjectFactory(factory);
}
}
private void objectWrapperFactoryElement(XNode context) throws Exception {
if (context != null) {
String type = context.getStringAttribute("type");
ObjectWrapperFactory factory = (ObjectWrapperFactory) resolveClass(type).getDeclaredConstructor().newInstance();
configuration.setObjectWrapperFactory(factory);
}
}
private void reflectorFactoryElement(XNode context) throws Exception {
if (context != null) {
String type = context.getStringAttribute("type");
ReflectorFactory factory = (ReflectorFactory) resolveClass(type).getDeclaredConstructor().newInstance();
configuration.setReflectorFactory(factory);
}
}
private void propertiesElement(XNode context) throws Exception {
if (context != null) {
Properties defaults = context.getChildrenAsProperties();
String resource = context.getStringAttribute("resource");
String url = context.getStringAttribute("url");
if (resource != null && url != null) {
throw new BuilderException("The properties element cannot specify both a URL and a resource based property file reference. Please specify one or the other.");
}
if (resource != null) {
defaults.putAll(Resources.getResourceAsProperties(resource));
} else if (url != null) {
defaults.putAll(Resources.getUrlAsProperties(url));
}
Properties vars = configuration.getVariables();
if (vars != null) {
defaults.putAll(vars);
}
parser.setVariables(defaults);
configuration.setVariables(defaults);
}
}
private void settingsElement(Properties props) {
configuration.setAutoMappingBehavior(AutoMappingBehavior.valueOf(props.getProperty("autoMappingBehavior", "PARTIAL")));
configuration.setAutoMappingUnknownColumnBehavior(AutoMappingUnknownColumnBehavior.valueOf(props.getProperty("autoMappingUnknownColumnBehavior", "NONE")));
configuration.setCacheEnabled(booleanValueOf(props.getProperty("cacheEnabled"), true));
configuration.setProxyFactory((ProxyFactory) createInstance(props.getProperty("proxyFactory")));
configuration.setLazyLoadingEnabled(booleanValueOf(props.getProperty("lazyLoadingEnabled"), false));
configuration.setAggressiveLazyLoading(booleanValueOf(props.getProperty("aggressiveLazyLoading"), false));
configuration.setMultipleResultSetsEnabled(booleanValueOf(props.getProperty("multipleResultSetsEnabled"), true));
configuration.setUseColumnLabel(booleanValueOf(props.getProperty("useColumnLabel"), true));
configuration.setUseGeneratedKeys(booleanValueOf(props.getProperty("useGeneratedKeys"), false));
configuration.setDefaultExecutorType(ExecutorType.valueOf(props.getProperty("defaultExecutorType", "SIMPLE")));
configuration.setDefaultStatementTimeout(integerValueOf(props.getProperty("defaultStatementTimeout"), null));
configuration.setDefaultFetchSize(integerValueOf(props.getProperty("defaultFetchSize"), null));
configuration.setDefaultResultSetType(resolveResultSetType(props.getProperty("defaultResultSetType")));
configuration.setMapUnderscoreToCamelCase(booleanValueOf(props.getProperty("mapUnderscoreToCamelCase"), false));
configuration.setSafeRowBoundsEnabled(booleanValueOf(props.getProperty("safeRowBoundsEnabled"), false));
configuration.setLocalCacheScope(LocalCacheScope.valueOf(props.getProperty("localCacheScope", "SESSION")));
configuration.setJdbcTypeForNull(JdbcType.valueOf(props.getProperty("jdbcTypeForNull", "OTHER")));
configuration.setLazyLoadTriggerMethods(stringSetValueOf(props.getProperty("lazyLoadTriggerMethods"), "equals,clone,hashCode,toString"));
configuration.setSafeResultHandlerEnabled(booleanValueOf(props.getProperty("safeResultHandlerEnabled"), true));
configuration.setDefaultScriptingLanguage(resolveClass(props.getProperty("defaultScriptingLanguage")));
configuration.setDefaultEnumTypeHandler(resolveClass(props.getProperty("defaultEnumTypeHandler")));
configuration.setCallSettersOnNulls(booleanValueOf(props.getProperty("callSettersOnNulls"), false));
configuration.setUseActualParamName(booleanValueOf(props.getProperty("useActualParamName"), true));
configuration.setReturnInstanceForEmptyRow(booleanValueOf(props.getProperty("returnInstanceForEmptyRow"), false));
configuration.setLogPrefix(props.getProperty("logPrefix"));
configuration.setConfigurationFactory(resolveClass(props.getProperty("configurationFactory")));
configuration.setShrinkWhitespacesInSql(booleanValueOf(props.getProperty("shrinkWhitespacesInSql"), false));
configuration.setArgNameBasedConstructorAutoMapping(booleanValueOf(props.getProperty("argNameBasedConstructorAutoMapping"), false));
configuration.setDefaultSqlProviderType(resolveClass(props.getProperty("defaultSqlProviderType")));
configuration.setNullableOnForEach(booleanValueOf(props.getProperty("nullableOnForEach"), false));
}
private void environmentsElement(XNode context) throws Exception {
if (context != null) {
if (environment == null) {
environment = context.getStringAttribute("default");
}
for (XNode child : context.getChildren()) {
String id = child.getStringAttribute("id");
if (isSpecifiedEnvironment(id)) {
TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager"));
DataSourceFactory dsFactory = dataSourceElement(child.evalNode("dataSource"));
DataSource dataSource = dsFactory.getDataSource();
Environment.Builder environmentBuilder = new Environment.Builder(id)
.transactionFactory(txFactory)
.dataSource(dataSource);
configuration.setEnvironment(environmentBuilder.build());
break;
}
}
}
}
private void databaseIdProviderElement(XNode context) throws Exception {
DatabaseIdProvider databaseIdProvider = null;
if (context != null) {
String type = context.getStringAttribute("type");
// awful patch to keep backward compatibility
if ("VENDOR".equals(type)) {
type = "DB_VENDOR";
}
Properties properties = context.getChildrenAsProperties();
databaseIdProvider = (DatabaseIdProvider) resolveClass(type).getDeclaredConstructor().newInstance();
databaseIdProvider.setProperties(properties);
}
Environment environment = configuration.getEnvironment();
if (environment != null && databaseIdProvider != null) {
String databaseId = databaseIdProvider.getDatabaseId(environment.getDataSource());
configuration.setDatabaseId(databaseId);
}
}
private TransactionFactory transactionManagerElement(XNode context) throws Exception {
if (context != null) {
String type = context.getStringAttribute("type");
Properties props = context.getChildrenAsProperties();
TransactionFactory factory = (TransactionFactory) resolveClass(type).getDeclaredConstructor().newInstance();
factory.setProperties(props);
return factory;
}
throw new BuilderException("Environment declaration requires a TransactionFactory.");
}
private DataSourceFactory dataSourceElement(XNode context) throws Exception {
if (context != null) {
String type = context.getStringAttribute("type");
Properties props = context.getChildrenAsProperties();
DataSourceFactory factory = (DataSourceFactory) resolveClass(type).getDeclaredConstructor().newInstance();
factory.setProperties(props);
return factory;
}
throw new BuilderException("Environment declaration requires a DataSourceFactory.");
}
private void typeHandlerElement(XNode parent) {
if (parent != null) {
for (XNode child : parent.getChildren()) {
if ("package".equals(child.getName())) {
String typeHandlerPackage = child.getStringAttribute("name");
typeHandlerRegistry.register(typeHandlerPackage);
} else {
String javaTypeName = child.getStringAttribute("javaType");
String jdbcTypeName = child.getStringAttribute("jdbcType");
String handlerTypeName = child.getStringAttribute("handler");
Class<?> javaTypeClass = resolveClass(javaTypeName);
JdbcType jdbcType = resolveJdbcType(jdbcTypeName);
Class<?> typeHandlerClass = resolveClass(handlerTypeName);
if (javaTypeClass != null) {
if (jdbcType == null) {
typeHandlerRegistry.register(javaTypeClass, typeHandlerClass);
} else {
typeHandlerRegistry.register(javaTypeClass, jdbcType, typeHandlerClass);
}
} else {
typeHandlerRegistry.register(typeHandlerClass);
}
}
}
}
}
private void mapperElement(XNode parent) throws Exception {
if (parent != null) {
for (XNode child : parent.getChildren()) {
if ("package".equals(child.getName())) {
String mapperPackage = child.getStringAttribute("name");
configuration.addMappers(mapperPackage);
} else {
String resource = child.getStringAttribute("resource");
String url = child.getStringAttribute("url");
String mapperClass = child.getStringAttribute("class");
if (resource != null && url == null && mapperClass == null) {
ErrorContext.instance().resource(resource);
try(InputStream inputStream = Resources.getResourceAsStream(resource)) {
XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
mapperParser.parse();
}
} else if (resource == null && url != null && mapperClass == null) {
ErrorContext.instance().resource(url);
try(InputStream inputStream = Resources.getUrlAsStream(url)){
XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments());
mapperParser.parse();
}
} else if (resource == null && url == null && mapperClass != null) {
Class<?> mapperInterface = Resources.classForName(mapperClass);
configuration.addMapper(mapperInterface);
} else {
throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one.");
}
}
}
}
}
private boolean isSpecifiedEnvironment(String id) {
if (environment == null) {
throw new BuilderException("No environment specified.");
}
if (id == null) {
throw new BuilderException("Environment requires an id attribute.");
}
return environment.equals(id);
}
}

View File

@ -175,7 +175,7 @@ public class EntitySqlProvider {
} }
TableInfo tableInfo = ProviderUtil.getTableInfo(context); TableInfo tableInfo = ProviderUtil.getTableInfo(context);
CPI.setFromIfNecessary(queryWrapper, tableInfo.getTableName()); CPI.setFromIfNecessary(queryWrapper, tableInfo.getSchema(), tableInfo.getTableName());
tableInfo.appendConditions(null, queryWrapper); tableInfo.appendConditions(null, queryWrapper);
ProviderUtil.setSqlArgs(params, CPI.getValueArray(queryWrapper)); ProviderUtil.setSqlArgs(params, CPI.getValueArray(queryWrapper));
@ -339,7 +339,7 @@ public class EntitySqlProvider {
tableInfo.appendConditions(null, queryWrapper); tableInfo.appendConditions(null, queryWrapper);
CPI.setSelectColumnsIfNecessary(queryWrapper, tableInfo.getDefaultQueryColumn()); CPI.setSelectColumnsIfNecessary(queryWrapper, tableInfo.getDefaultQueryColumn());
CPI.setFromIfNecessary(queryWrapper, tableInfo.getTableName()); CPI.setFromIfNecessary(queryWrapper, tableInfo.getSchema(), tableInfo.getTableName());
} }
Object[] values = CPI.getValueArray(queryWrapper); Object[] values = CPI.getValueArray(queryWrapper);
@ -366,7 +366,7 @@ public class EntitySqlProvider {
for (TableInfo tableInfo : tableInfos) { for (TableInfo tableInfo : tableInfos) {
tableInfo.appendConditions(null, queryWrapper); tableInfo.appendConditions(null, queryWrapper);
CPI.setFromIfNecessary(queryWrapper, tableInfo.getTableName()); CPI.setFromIfNecessary(queryWrapper, tableInfo.getSchema(), tableInfo.getTableName());
} }
Object[] values = CPI.getValueArray(queryWrapper); Object[] values = CPI.getValueArray(queryWrapper);

View File

@ -162,7 +162,7 @@ public class CPI {
return queryWrapper.getEndFragments(); return queryWrapper.getEndFragments();
} }
public static void setEndFragments(QueryWrapper queryWrapper,List<String> endFragments) { public static void setEndFragments(QueryWrapper queryWrapper, List<String> endFragments) {
queryWrapper.setEndFragments(endFragments); queryWrapper.setEndFragments(endFragments);
} }
@ -200,6 +200,13 @@ public class CPI {
} }
} }
public static void setFromIfNecessary(QueryWrapper queryWrapper, String schema, String tableName) {
if (StringUtil.isNotBlank(tableName)
&& CollectionUtil.isEmpty(queryWrapper.getQueryTables())) {
queryWrapper.from(new QueryTable(schema, tableName));
}
}
public static boolean containsTable(QueryCondition condition, String... tables) { public static boolean containsTable(QueryCondition condition, String... tables) {
return condition != null && condition.containsTable(tables); return condition != null && condition.containsTable(tables);
} }

View File

@ -43,9 +43,9 @@ public class Join implements Serializable {
protected QueryCondition on; protected QueryCondition on;
protected boolean effective; protected boolean effective;
public Join(String type, String table, boolean when) { public Join(String type, QueryTable table, boolean when) {
this.type = type; this.type = type;
this.queryTable = new QueryTable(table); this.queryTable = table;
this.effective = when; this.effective = when;
} }
@ -65,7 +65,7 @@ public class Join implements Serializable {
this.on = condition; this.on = condition;
} }
QueryCondition getOnCondition(){ QueryCondition getOnCondition() {
return on; return on;
} }

View File

@ -18,10 +18,7 @@ package com.mybatisflex.core.query;
import com.mybatisflex.core.dialect.IDialect; import com.mybatisflex.core.dialect.IDialect;
import com.mybatisflex.core.table.TableDef; import com.mybatisflex.core.table.TableDef;
import com.mybatisflex.core.util.LambdaGetter; import com.mybatisflex.core.util.*;
import com.mybatisflex.core.util.LambdaUtil;
import com.mybatisflex.core.util.SqlUtil;
import com.mybatisflex.core.util.StringUtil;
import java.io.Serializable; import java.io.Serializable;
import java.util.Collection; import java.util.Collection;
@ -45,15 +42,15 @@ public class QueryColumn implements Serializable {
this.name = name; this.name = name;
} }
public QueryColumn(String tableName, String name) { public QueryColumn(String schema, String tableName, String name) {
SqlUtil.keepColumnSafely(name); SqlUtil.keepColumnSafely(name);
this.table = new QueryTable(tableName); this.table = new QueryTable(schema, tableName);
this.name = name; this.name = name;
} }
public QueryColumn(TableDef tableDef, String name) { public QueryColumn(TableDef tableDef, String name) {
SqlUtil.keepColumnSafely(name); SqlUtil.keepColumnSafely(name);
this.table = new QueryTable(tableDef.getTableName()); this.table = new QueryTable(tableDef);
this.name = name; this.name = name;
} }
@ -358,25 +355,56 @@ public class QueryColumn implements Serializable {
} }
protected String wrap(IDialect dialect, String table, String column) {
if (StringUtil.isNotBlank(table)) {
return dialect.wrap(table) + "." + dialect.wrap(column);
} else {
return dialect.wrap(column);
}
}
String toConditionSql(List<QueryTable> queryTables, IDialect dialect) { String toConditionSql(List<QueryTable> queryTables, IDialect dialect) {
String tableName = WrapperUtil.getColumnTableName(queryTables, table); QueryTable selectTable = getSelectTable(queryTables, table);
return wrap(dialect, tableName, name); if (selectTable == null) {
return dialect.wrap(name);
} else {
if (StringUtil.isNotBlank(selectTable.alias)) {
return dialect.wrap(selectTable.alias) + "." + dialect.wrap(name);
} else if (StringUtil.isNotBlank(selectTable.getSchema()) && StringUtil.isNotBlank(selectTable.getName())) {
return dialect.wrap(dialect.getRealSchema(selectTable.schema)) + "." + dialect.wrap(dialect.getRealTable(selectTable.getName())) + "." + dialect.wrap(name);
} else if (StringUtil.isNotBlank(selectTable.getName())) {
return dialect.wrap(dialect.getRealTable(selectTable.getName())) + "." + dialect.wrap(name);
} else {
return dialect.wrap(name);
}
}
} }
String toSelectSql(List<QueryTable> queryTables, IDialect dialect) { String toSelectSql(List<QueryTable> queryTables, IDialect dialect) {
String tableName = WrapperUtil.getColumnTableName(queryTables, table); return toConditionSql(queryTables, dialect) + WrapperUtil.buildAsAlias(alias, dialect);
return wrap(dialect, tableName, name) + WrapperUtil.buildAsAlias(alias, dialect);
} }
QueryTable getSelectTable(List<QueryTable> queryTables, QueryTable columnTable) {
if (queryTables == null || queryTables.isEmpty()) {
return null;
}
if (queryTables.size() == 1 && queryTables.get(0).isSameTable(columnTable)) {
//ignore table
return null;
}
if (CollectionUtil.isEmpty(queryTables)) {
return columnTable;
}
if (columnTable == null && queryTables.size() == 1) {
return queryTables.get(0);
}
for (QueryTable table : queryTables) {
if (table.isSameTable(columnTable)) {
return table;
}
}
return columnTable;
}
@Override @Override
public String toString() { public String toString() {
return "QueryColumn{" + return "QueryColumn{" +

View File

@ -62,9 +62,9 @@ public class QueryCondition implements Serializable {
} }
public static QueryCondition create(String table, String column, String logic, Object value) { public static QueryCondition create(String schema, String table, String column, String logic, Object value) {
QueryCondition condition = new QueryCondition(); QueryCondition condition = new QueryCondition();
condition.setColumn(new QueryColumn(table, column)); condition.setColumn(new QueryColumn(schema, table, column));
condition.setLogic(logic); condition.setLogic(logic);
condition.setValue(value); condition.setValue(value);
return condition; return condition;

View File

@ -16,6 +16,8 @@
package com.mybatisflex.core.query; package com.mybatisflex.core.query;
import com.mybatisflex.core.dialect.IDialect; import com.mybatisflex.core.dialect.IDialect;
import com.mybatisflex.core.table.TableDef;
import com.mybatisflex.core.util.StringUtil;
import java.io.Serializable; import java.io.Serializable;
import java.util.Objects; import java.util.Objects;
@ -25,21 +27,41 @@ import java.util.Objects;
*/ */
public class QueryTable implements Serializable { public class QueryTable implements Serializable {
protected String schema;
protected String name; protected String name;
protected String alias; protected String alias;
public QueryTable() { public QueryTable() {
} }
public QueryTable(TableDef tableDef) {
this.name = tableDef.getTableName();
this.schema = tableDef.getSchema();
}
public QueryTable(String name) { public QueryTable(String name) {
this.name = name; this.name = name;
} }
public QueryTable(String table, String alias) { public QueryTable(String schema, String name) {
this.schema = schema;
this.name = name;
}
public QueryTable(String schema, String table, String alias) {
this.schema = schema;
this.name = table; this.name = table;
this.alias = alias; this.alias = alias;
} }
public String getSchema() {
return schema;
}
public void setSchema(String schema) {
this.schema = schema;
}
public String getName() { public String getName() {
return name; return name;
} }
@ -55,21 +77,38 @@ public class QueryTable implements Serializable {
} }
boolean isSameTable(QueryTable table) { boolean isSameTable(QueryTable table) {
return table != null && Objects.equals(name, table.name); if (table == null) {
return false;
}
if (StringUtil.isNotBlank(alias) && StringUtil.isNotBlank(table.alias)) {
if (Objects.equals(alias, table.alias)) {
return false;
}
}
return Objects.equals(name, table.name);
} }
Object[] getValueArray() { Object[] getValueArray() {
return WrapperUtil.NULL_PARA_ARRAY; return WrapperUtil.NULL_PARA_ARRAY;
} }
public String toSql(IDialect dialect) { public String toSql(IDialect dialect) {
return dialect.wrap(name) + WrapperUtil.buildAsAlias(alias, dialect); String sql;
if (StringUtil.isNotBlank(schema)) {
sql = dialect.wrap(dialect.getRealSchema(schema)) + "." + dialect.wrap(dialect.getRealTable(name)) + WrapperUtil.buildAsAlias(alias, dialect);
} else {
sql = dialect.wrap(dialect.getRealTable(name)) + WrapperUtil.buildAsAlias(alias, dialect);
}
return sql;
} }
@Override @Override
public String toString() { public String toString() {
return "QueryTable{" + return "QueryTable{" +
"name='" + name + '\'' + "schema='" + schema + '\'' +
", name='" + name + '\'' +
", alias='" + alias + '\'' + ", alias='" + alias + '\'' +
'}'; '}';
} }

View File

@ -15,10 +15,12 @@
*/ */
package com.mybatisflex.core.query; package com.mybatisflex.core.query;
import com.mybatisflex.core.dialect.DialectFactory;
import com.mybatisflex.core.exception.FlexExceptions; import com.mybatisflex.core.exception.FlexExceptions;
import com.mybatisflex.core.table.TableDef; import com.mybatisflex.core.table.TableDef;
import com.mybatisflex.core.util.ArrayUtil; import com.mybatisflex.core.util.ArrayUtil;
import com.mybatisflex.core.util.CollectionUtil; import com.mybatisflex.core.util.CollectionUtil;
import com.mybatisflex.core.util.SqlUtil;
import com.mybatisflex.core.util.StringUtil; import com.mybatisflex.core.util.StringUtil;
import java.util.*; import java.util.*;
@ -42,7 +44,7 @@ public class QueryWrapper extends BaseQueryWrapper<QueryWrapper> {
public QueryWrapper from(TableDef... tableDefs) { public QueryWrapper from(TableDef... tableDefs) {
for (TableDef tableDef : tableDefs) { for (TableDef tableDef : tableDefs) {
from(new QueryTable(tableDef.getTableName())); from(new QueryTable(tableDef));
} }
return this; return this;
} }
@ -53,7 +55,14 @@ public class QueryWrapper extends BaseQueryWrapper<QueryWrapper> {
if (StringUtil.isBlank(table)) { if (StringUtil.isBlank(table)) {
throw new IllegalArgumentException("table must not be null or blank."); throw new IllegalArgumentException("table must not be null or blank.");
} }
from(new QueryTable(table)); int indexOf = table.indexOf(".");
if (indexOf > 0) {
String schema = table.substring(0, indexOf);
table = table.substring(indexOf + 1);
from(new QueryTable(schema, table));
} else {
from(new QueryTable(table));
}
} }
return this; return this;
} }
@ -151,21 +160,20 @@ public class QueryWrapper extends BaseQueryWrapper<QueryWrapper> {
public Joiner<QueryWrapper> leftJoin(String table) { public Joiner<QueryWrapper> leftJoin(String table) {
return joining(Join.TYPE_LEFT, table, true); return joining(Join.TYPE_LEFT, new QueryTable(table), true);
} }
public Joiner<QueryWrapper> leftJoinIf(String table, boolean when) { public Joiner<QueryWrapper> leftJoinIf(String table, boolean when) {
return joining(Join.TYPE_LEFT, table, when); return joining(Join.TYPE_LEFT, new QueryTable(table), when);
} }
public Joiner<QueryWrapper> leftJoin(TableDef table) { public Joiner<QueryWrapper> leftJoin(TableDef table) {
return joining(Join.TYPE_LEFT, table.getTableName(), true); return joining(Join.TYPE_LEFT, new QueryTable(table), true);
} }
public Joiner<QueryWrapper> leftJoinIf(TableDef table, boolean when) { public Joiner<QueryWrapper> leftJoinIf(TableDef table, boolean when) {
return joining(Join.TYPE_LEFT, table.getTableName(), when); return joining(Join.TYPE_LEFT, new QueryTable(table), when);
} }
public Joiner<QueryWrapper> leftJoin(QueryWrapper table) { public Joiner<QueryWrapper> leftJoin(QueryWrapper table) {
@ -176,12 +184,21 @@ public class QueryWrapper extends BaseQueryWrapper<QueryWrapper> {
return joining(Join.TYPE_LEFT, table, when); return joining(Join.TYPE_LEFT, table, when);
} }
public Joiner<QueryWrapper> rightJoin(String table) { public Joiner<QueryWrapper> rightJoin(String table) {
return joining(Join.TYPE_RIGHT, table, true); return joining(Join.TYPE_RIGHT, new QueryTable(table), true);
} }
public Joiner<QueryWrapper> rightJoinIf(String table, boolean when) { public Joiner<QueryWrapper> rightJoinIf(String table, boolean when) {
return joining(Join.TYPE_RIGHT, table, when); return joining(Join.TYPE_RIGHT, new QueryTable(table), when);
}
public Joiner<QueryWrapper> rightJoinIf(TableDef table) {
return joining(Join.TYPE_RIGHT, new QueryTable(table), true);
}
public Joiner<QueryWrapper> rightJoinIf(TableDef table, boolean when) {
return joining(Join.TYPE_RIGHT, new QueryTable(table), when);
} }
public Joiner<QueryWrapper> rightJoin(QueryWrapper table) { public Joiner<QueryWrapper> rightJoin(QueryWrapper table) {
@ -192,12 +209,13 @@ public class QueryWrapper extends BaseQueryWrapper<QueryWrapper> {
return joining(Join.TYPE_RIGHT, table, when); return joining(Join.TYPE_RIGHT, table, when);
} }
public Joiner<QueryWrapper> innerJoin(String table) { public Joiner<QueryWrapper> innerJoin(String table) {
return joining(Join.TYPE_INNER, table, true); return joining(Join.TYPE_INNER, new QueryTable(table), true);
} }
public Joiner<QueryWrapper> innerJoinIf(String table, boolean when) { public Joiner<QueryWrapper> innerJoinIf(String table, boolean when) {
return joining(Join.TYPE_INNER, table, when); return joining(Join.TYPE_INNER, new QueryTable(table), when);
} }
public Joiner<QueryWrapper> innerJoin(TableDef table) { public Joiner<QueryWrapper> innerJoin(TableDef table) {
@ -205,7 +223,7 @@ public class QueryWrapper extends BaseQueryWrapper<QueryWrapper> {
} }
public Joiner<QueryWrapper> innerJoinIf(TableDef table, boolean when) { public Joiner<QueryWrapper> innerJoinIf(TableDef table, boolean when) {
return joining(Join.TYPE_INNER, table.getTableName(), when); return joining(Join.TYPE_INNER, new QueryTable(table), when);
} }
public Joiner<QueryWrapper> innerJoin(QueryWrapper table) { public Joiner<QueryWrapper> innerJoin(QueryWrapper table) {
@ -216,12 +234,21 @@ public class QueryWrapper extends BaseQueryWrapper<QueryWrapper> {
return joining(Join.TYPE_INNER, table, when); return joining(Join.TYPE_INNER, table, when);
} }
public Joiner<QueryWrapper> fullJoin(String table) { public Joiner<QueryWrapper> fullJoin(String table) {
return joining(Join.TYPE_FULL, table, true); return joining(Join.TYPE_FULL, new QueryTable(table), true);
} }
public Joiner<QueryWrapper> fullJoinIf(String table, boolean when) { public Joiner<QueryWrapper> fullJoinIf(String table, boolean when) {
return joining(Join.TYPE_FULL, table, when); return joining(Join.TYPE_FULL, new QueryTable(table), when);
}
public Joiner<QueryWrapper> fullJoinIf(TableDef table) {
return joining(Join.TYPE_FULL, new QueryTable(table), true);
}
public Joiner<QueryWrapper> fullJoinIf(TableDef table, boolean when) {
return joining(Join.TYPE_FULL, new QueryTable(table), when);
} }
public Joiner<QueryWrapper> fullJoin(QueryWrapper table) { public Joiner<QueryWrapper> fullJoin(QueryWrapper table) {
@ -232,12 +259,21 @@ public class QueryWrapper extends BaseQueryWrapper<QueryWrapper> {
return joining(Join.TYPE_FULL, table, when); return joining(Join.TYPE_FULL, table, when);
} }
public Joiner<QueryWrapper> crossJoin(String table) { public Joiner<QueryWrapper> crossJoin(String table) {
return joining(Join.TYPE_CROSS, table, true); return joining(Join.TYPE_CROSS, new QueryTable(table), true);
} }
public Joiner<QueryWrapper> crossJoinIf(String table, boolean when) { public Joiner<QueryWrapper> crossJoinIf(String table, boolean when) {
return joining(Join.TYPE_CROSS, table, when); return joining(Join.TYPE_CROSS, new QueryTable(table), when);
}
public Joiner<QueryWrapper> crossJoinIf(TableDef table) {
return joining(Join.TYPE_CROSS, new QueryTable(table), true);
}
public Joiner<QueryWrapper> crossJoinIf(TableDef table, boolean when) {
return joining(Join.TYPE_CROSS, new QueryTable(table), when);
} }
public Joiner<QueryWrapper> crossJoin(QueryWrapper table) { public Joiner<QueryWrapper> crossJoin(QueryWrapper table) {
@ -248,12 +284,21 @@ public class QueryWrapper extends BaseQueryWrapper<QueryWrapper> {
return joining(Join.TYPE_CROSS, table, when); return joining(Join.TYPE_CROSS, table, when);
} }
public Joiner<QueryWrapper> join(String table) { public Joiner<QueryWrapper> join(String table) {
return joining(Join.TYPE_JOIN, table, true); return joining(Join.TYPE_JOIN, new QueryTable(table), true);
} }
public Joiner<QueryWrapper> join(String table, boolean when) { public Joiner<QueryWrapper> join(String table, boolean when) {
return joining(Join.TYPE_JOIN, table, when); return joining(Join.TYPE_JOIN, new QueryTable(table), when);
}
public Joiner<QueryWrapper> join(TableDef table) {
return joining(Join.TYPE_JOIN, new QueryTable(table), true);
}
public Joiner<QueryWrapper> join(TableDef table, boolean when) {
return joining(Join.TYPE_JOIN, new QueryTable(table), when);
} }
public Joiner<QueryWrapper> join(QueryWrapper table) { public Joiner<QueryWrapper> join(QueryWrapper table) {
@ -264,6 +309,7 @@ public class QueryWrapper extends BaseQueryWrapper<QueryWrapper> {
return joining(Join.TYPE_JOIN, table, when); return joining(Join.TYPE_JOIN, table, when);
} }
public QueryWrapper union(QueryWrapper unionQuery) { public QueryWrapper union(QueryWrapper unionQuery) {
if (unions == null) { if (unions == null) {
unions = new ArrayList<>(); unions = new ArrayList<>();
@ -297,7 +343,7 @@ public class QueryWrapper extends BaseQueryWrapper<QueryWrapper> {
// } // }
protected Joiner<QueryWrapper> joining(String type, String table, boolean condition) { protected Joiner<QueryWrapper> joining(String type, QueryTable table, boolean condition) {
Join join = new Join(type, table, condition); Join join = new Join(type, table, condition);
addJoinTable(join.getQueryTable()); addJoinTable(join.getQueryTable());
return new Joiner<>(addJoin(join), join); return new Joiner<>(addJoin(join), join);
@ -489,4 +535,10 @@ public class QueryWrapper extends BaseQueryWrapper<QueryWrapper> {
} }
public String toDebugSQL() {
String sql = DialectFactory.getDialect().forSelectByQuery(this);
return SqlUtil.replaceSqlParams(sql, getValueArray());
}
} }

View File

@ -18,7 +18,6 @@ package com.mybatisflex.core.query;
import com.mybatisflex.core.dialect.IDialect; import com.mybatisflex.core.dialect.IDialect;
import com.mybatisflex.core.util.ClassUtil; import com.mybatisflex.core.util.ClassUtil;
import com.mybatisflex.core.util.CollectionUtil;
import com.mybatisflex.core.util.EnumWrapper; import com.mybatisflex.core.util.EnumWrapper;
import com.mybatisflex.core.util.StringUtil; import com.mybatisflex.core.util.StringUtil;
@ -132,39 +131,7 @@ class WrapperUtil {
} }
public static String getColumnTableName(List<QueryTable> queryTables, QueryTable queryTable) {
if (queryTables == null) {
return "";
}
if (queryTables.size() == 1 && queryTables.get(0).isSameTable(queryTable)) {
return "";
}
QueryTable realTable = getRealTable(queryTables, queryTable);
if (realTable == null) {
return "";
}
return StringUtil.isNotBlank(realTable.alias) ? realTable.alias : realTable.name;
}
public static QueryTable getRealTable(List<QueryTable> queryTables, QueryTable queryTable) {
if (CollectionUtil.isEmpty(queryTables)) {
return queryTable;
}
if (queryTable == null && queryTables.size() == 1) {
return queryTables.get(0);
}
for (QueryTable table : queryTables) {
if (table.isSameTable(queryTable)) {
return table;
}
}
return queryTable;
}
} }

View File

@ -0,0 +1,20 @@
/**
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mybatisflex.core.table;
public interface DynamicSchemaProcessor {
String process(String schema);
}

View File

@ -0,0 +1,20 @@
/**
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mybatisflex.core.table;
public interface DynamicTableProcessor {
String process(String tableName);
}

View File

@ -21,8 +21,14 @@ import java.io.Serializable;
public class TableDef implements Serializable { public class TableDef implements Serializable {
private String schema;
private final String tableName; private final String tableName;
public TableDef(String schema, String tableName) {
this.schema = schema;
this.tableName = tableName;
}
public TableDef(String tableName) { public TableDef(String tableName) {
this.tableName = tableName; this.tableName = tableName;
} }
@ -31,8 +37,12 @@ public class TableDef implements Serializable {
return tableName; return tableName;
} }
public String getSchema() {
return schema;
}
public QueryTable as(String alias) { public QueryTable as(String alias) {
return new QueryTable(tableName, alias); return new QueryTable(schema, tableName, alias);
} }

View File

@ -577,12 +577,12 @@ public class TableInfo {
if (versionValue == null) { if (versionValue == null) {
throw FlexExceptions.wrap("The version value of entity[%s] must not be null.", entity); throw FlexExceptions.wrap("The version value of entity[%s] must not be null.", entity);
} }
queryWrapper.and(QueryCondition.create(tableName, versionColumn, QueryCondition.LOGIC_EQUALS, versionValue)); queryWrapper.and(QueryCondition.create(schema, tableName, versionColumn, QueryCondition.LOGIC_EQUALS, versionValue));
} }
//逻辑删除 //逻辑删除
if (StringUtil.isNotBlank(logicDeleteColumn)) { if (StringUtil.isNotBlank(logicDeleteColumn)) {
queryWrapper.and(QueryCondition.create(tableName, logicDeleteColumn, QueryCondition.LOGIC_EQUALS queryWrapper.and(QueryCondition.create(schema, tableName, logicDeleteColumn, QueryCondition.LOGIC_EQUALS
, FlexGlobalConfig.getDefaultConfig().getNormalValueOfLogicDelete())); , FlexGlobalConfig.getDefaultConfig().getNormalValueOfLogicDelete()));
} }
@ -590,9 +590,9 @@ public class TableInfo {
Object[] tenantIdArgs = buildTenantIdArgs(); Object[] tenantIdArgs = buildTenantIdArgs();
if (ArrayUtil.isNotEmpty(tenantIdArgs)) { if (ArrayUtil.isNotEmpty(tenantIdArgs)) {
if (tenantIdArgs.length == 1) { if (tenantIdArgs.length == 1) {
queryWrapper.and(QueryCondition.create(tableName, tenantIdColumn, QueryCondition.LOGIC_EQUALS, tenantIdArgs[0])); queryWrapper.and(QueryCondition.create(schema, tableName, tenantIdColumn, QueryCondition.LOGIC_EQUALS, tenantIdArgs[0]));
} else { } else {
queryWrapper.and(QueryCondition.create(tableName, tenantIdColumn, QueryCondition.LOGIC_IN, tenantIdArgs)); queryWrapper.and(QueryCondition.create(schema, tableName, tenantIdColumn, QueryCondition.LOGIC_IN, tenantIdArgs));
} }
} }
@ -647,7 +647,7 @@ public class TableInfo {
public List<QueryColumn> getDefaultQueryColumn() { public List<QueryColumn> getDefaultQueryColumn() {
return Arrays.stream(defaultColumns) return Arrays.stream(defaultColumns)
.map(name -> new QueryColumn(getTableName(), name)) .map(name -> new QueryColumn(schema, getTableName(), name))
.collect(Collectors.toList()); .collect(Collectors.toList());
} }

View File

@ -0,0 +1,110 @@
/**
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mybatisflex.core.table;
import com.mybatisflex.core.util.StringUtil;
import java.util.HashMap;
import java.util.Map;
public class TableManager {
private static DynamicTableProcessor dynamicTableProcessor;
private static DynamicSchemaProcessor dynamicSchemaProcessor;
private static final ThreadLocal<Map<String, String>> tableNameMappingTL = ThreadLocal.withInitial(HashMap::new);
private static final ThreadLocal<Map<String, String>> schemaMappingTL = ThreadLocal.withInitial(HashMap::new);
public static DynamicTableProcessor getDynamicTableProcessor() {
return dynamicTableProcessor;
}
public static void setDynamicTableProcessor(DynamicTableProcessor dynamicTableProcessor) {
TableManager.dynamicTableProcessor = dynamicTableProcessor;
}
public static DynamicSchemaProcessor getDynamicSchemaProcessor() {
return dynamicSchemaProcessor;
}
public static void setDynamicSchemaProcessor(DynamicSchemaProcessor dynamicSchemaProcessor) {
TableManager.dynamicSchemaProcessor = dynamicSchemaProcessor;
}
public static void setHintTableMapping(String tableName, String mappingTable) {
tableNameMappingTL.get().put(tableName, mappingTable);
}
public static String getHintTableMapping(String tableName) {
return tableNameMappingTL.get().get(tableName);
}
public static void setHintSchemaMapping(String schema, String mappingSchema) {
schemaMappingTL.get().put(schema, mappingSchema);
}
public static String getHintSchemaMapping(String schema) {
return schemaMappingTL.get().get(schema);
}
public static String getRealTable(String tableName) {
if (dynamicTableProcessor == null) {
return tableName;
}
Map<String, String> mapping = tableNameMappingTL.get();
String dynamicTableName = mapping.get(tableName);
if (StringUtil.isNotBlank(dynamicTableName)) {
return dynamicTableName;
}
dynamicTableName = dynamicTableProcessor.process(tableName);
mapping.put(tableName, dynamicTableName);
return dynamicTableName;
}
public static String getRealSchema(String schema) {
if (dynamicSchemaProcessor == null) {
return schema;
}
Map<String, String> mapping = schemaMappingTL.get();
String dynamiSchema = mapping.get(schema);
if (StringUtil.isNotBlank(dynamiSchema)) {
return dynamiSchema;
}
dynamiSchema = dynamicSchemaProcessor.process(schema);
mapping.put(schema, dynamiSchema);
return dynamiSchema;
}
// public static void clear() {
// if (dynamicTableProcessor != null) {
// tableNameMappingTL.remove();
// }
// if (dynamicSchemaProcessor != null) {
// schemaMappingTL.remove();
// }
// }
}

View File

@ -15,6 +15,10 @@
*/ */
package com.mybatisflex.core.util; package com.mybatisflex.core.util;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.regex.Matcher;
public class SqlUtil { public class SqlUtil {
@ -72,4 +76,35 @@ public class SqlUtil {
return result != null && result.longValue() > 0; return result != null && result.longValue() > 0;
} }
public static String replaceSqlParams(String sql, Object[] params){
if (params != null && params.length > 0) {
for (Object value : params) {
// null
if (value == null) {
sql = sql.replaceFirst("\\?", "null");
}
// number
else if (value instanceof Number || value instanceof Boolean) {
sql = sql.replaceFirst("\\?", value.toString());
}
// other
else {
StringBuilder sb = new StringBuilder();
sb.append("'");
if (value instanceof Date) {
sb.append(DateUtil.toDateTimeString((Date) value));
} else if (value instanceof LocalDateTime) {
sb.append(DateUtil.toDateTimeString(DateUtil.toDate((LocalDateTime) value)));
} else {
sb.append(value);
}
sb.append("'");
sql = sql.replaceFirst("\\?", Matcher.quoteReplacement(sb.toString()));
}
}
}
return sql;
}
} }

View File

@ -0,0 +1,84 @@
package com.mybatisflex.coretest;
import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.Table;
import java.util.Date;
@Table(value = "tb_a01",schema = "flex")
public class Account01 {
@Id
private Long id;
private String userName;
private Date birthday;
private int sex;
private Integer age;
private boolean isNormal;
@Column(isLogicDelete = true)
private Boolean isDelete;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public boolean isNormal() {
return isNormal;
}
public void setNormal(boolean normal) {
isNormal = normal;
}
public Boolean getDelete() {
return isDelete;
}
public void setDelete(Boolean delete) {
isDelete = delete;
}
}

View File

@ -1,18 +1,21 @@
package com.mybatisflex.coretest; package com.mybatisflex.coretest;
import com.mybatisflex.core.dialect.impl.CommonsDialectImpl;
import com.mybatisflex.core.dialect.IDialect; import com.mybatisflex.core.dialect.IDialect;
import com.mybatisflex.core.dialect.KeywordWrap; import com.mybatisflex.core.dialect.KeywordWrap;
import com.mybatisflex.core.dialect.LimitOffsetProcessor; import com.mybatisflex.core.dialect.LimitOffsetProcessor;
import com.mybatisflex.core.dialect.impl.CommonsDialectImpl;
import com.mybatisflex.core.query.CPI; import com.mybatisflex.core.query.CPI;
import com.mybatisflex.core.query.QueryWrapper; import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.table.DynamicTableProcessor;
import com.mybatisflex.core.table.TableInfo; import com.mybatisflex.core.table.TableInfo;
import com.mybatisflex.core.table.TableInfoFactory; import com.mybatisflex.core.table.TableInfoFactory;
import com.mybatisflex.core.table.TableManager;
import org.junit.Test; import org.junit.Test;
import java.util.Arrays; import java.util.Arrays;
import static com.mybatisflex.core.query.QueryMethods.*; import static com.mybatisflex.core.query.QueryMethods.*;
import static com.mybatisflex.coretest.table.Account01TableDef.ACCOUNT01;
import static com.mybatisflex.coretest.table.AccountTableDef.ACCOUNT; import static com.mybatisflex.coretest.table.AccountTableDef.ACCOUNT;
import static com.mybatisflex.coretest.table.ArticleTableDef.ARTICLE; import static com.mybatisflex.coretest.table.ArticleTableDef.ARTICLE;
@ -30,6 +33,52 @@ public class AccountSqlTester {
System.out.println(sql); System.out.println(sql);
} }
@Test
public void testSelectWithSchemaSql() {
QueryWrapper query = new QueryWrapper()
.select()
.from(ACCOUNT01);
IDialect dialect = new CommonsDialectImpl();
String sql = dialect.forSelectByQuery(query);
System.out.println(sql);
}
@Test
public void testSelectWithSchemaSql01() {
QueryWrapper query = new QueryWrapper()
.select()
.from(ACCOUNT01).leftJoin(ACCOUNT).on(ACCOUNT01.ID.eq(ACCOUNT.ID))
.where(ACCOUNT01.ID.ge(100))
.and(ACCOUNT.SEX.eq(1));
TableManager.setDynamicTableProcessor(new DynamicTableProcessor() {
@Override
public String process(String tableName) {
return tableName+"_01";
}
});
TableManager.setDynamicTableProcessor(original -> original+"_01");
System.out.println(query.toDebugSQL());
}
@Test
public void testSelectWithSchemaSql02() {
QueryWrapper query = new QueryWrapper()
.select()
.from(ACCOUNT01).as("a1").leftJoin(ACCOUNT).on(ACCOUNT01.ID.eq(ACCOUNT.ID))
.where(ACCOUNT01.ID.ge(100))
.and(ACCOUNT.SEX.eq(1));
TableManager.setDynamicTableProcessor(original -> original+"_01");
TableManager.setDynamicTableProcessor(original -> original+"_01");
System.out.println(query.toDebugSQL());
}
@Test @Test
public void testSelectColumnsSql() { public void testSelectColumnsSql() {
QueryWrapper query = new QueryWrapper() QueryWrapper query = new QueryWrapper()

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>parent</artifactId> <artifactId>parent</artifactId>
<groupId>com.mybatis-flex</groupId> <groupId>com.mybatis-flex</groupId>
<version>1.3.2</version> <version>1.3.3</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@ -20,7 +20,7 @@
<dependency> <dependency>
<groupId>com.mybatis-flex</groupId> <groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-annotation</artifactId> <artifactId>mybatis-flex-annotation</artifactId>
<version>1.3.2</version> <version>1.3.3</version>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@ -81,7 +81,7 @@ public class QueryEntityProcessor extends AbstractProcessor {
"@classesInfo" + "@classesInfo" +
"}\n"; "}\n";
private static final String tableDefTemplate = "\n\n public static final @entityClassTableDef @tableField = new @entityClassTableDef(\"@tableName\");\n"; private static final String tableDefTemplate = "\n\n public static final @entityClassTableDef @tableField = new @entityClassTableDef(\"@schema\", \"@tableName\");\n";
private static final String singleEntityClassTemplate = "package @package;\n" + private static final String singleEntityClassTemplate = "package @package;\n" +
"\n" + "\n" +
@ -96,8 +96,8 @@ public class QueryEntityProcessor extends AbstractProcessor {
"@defaultColumns" + "@defaultColumns" +
"@allColumns" + "@allColumns" +
"\n" + "\n" +
" public @entityClassTableDef(String tableName) {\n" + " public @entityClassTableDef(String schema, String tableName) {\n" +
" super(tableName);\n" + " super(schema, tableName);\n" +
" }\n" + " }\n" +
"}\n"; "}\n";
@ -109,8 +109,8 @@ public class QueryEntityProcessor extends AbstractProcessor {
"@defaultColumns" + "@defaultColumns" +
"@allColumns" + "@allColumns" +
"\n" + "\n" +
" public @entityClassTableDef(String tableName) {\n" + " public @entityClassTableDef(String schema, String tableName) {\n" +
" super(tableName);\n" + " super(schema, tableName);\n" +
" }\n" + " }\n" +
" }\n"; " }\n";
@ -177,6 +177,10 @@ public class QueryEntityProcessor extends AbstractProcessor {
} }
} }
String schema = table != null && table.value().trim().length() != 0
? table.schema()
: "";
String tableName = table != null && table.value().trim().length() != 0 String tableName = table != null && table.value().trim().length() != 0
? table.value() ? table.value()
: firstCharToLowerCase(entityClassElement.getSimpleName().toString()); : firstCharToLowerCase(entityClassElement.getSimpleName().toString());
@ -203,13 +207,13 @@ public class QueryEntityProcessor extends AbstractProcessor {
} }
if (allInTables) { if (allInTables) {
String content = buildTablesClass(entitySimpleName, tableName, propertyAndColumns, defaultColumns, tablesNameStyle, null, allInTables); String content = buildTablesClass(entitySimpleName, schema, tableName, propertyAndColumns, defaultColumns, tablesNameStyle, null, allInTables);
tablesContent.append(content); tablesContent.append(content);
} }
//每一个 entity 生成一个独立的文件 //每一个 entity 生成一个独立的文件
else { else {
String realGenPackage = genTablesPackage == null || genTablesPackage.trim().length() == 0 ? guessPackage.toString() : genTablesPackage; String realGenPackage = genTablesPackage == null || genTablesPackage.trim().length() == 0 ? guessPackage.toString() : genTablesPackage;
String content = buildTablesClass(entitySimpleName, tableName, propertyAndColumns, defaultColumns, tablesNameStyle, realGenPackage, allInTables); String content = buildTablesClass(entitySimpleName, schema, tableName, propertyAndColumns, defaultColumns, tablesNameStyle, realGenPackage, allInTables);
genClass(genPath, realGenPackage, entitySimpleName + "TableDef", content); genClass(genPath, realGenPackage, entitySimpleName + "TableDef", content);
} }
@ -327,12 +331,13 @@ public class QueryEntityProcessor extends AbstractProcessor {
} }
private String buildTablesClass(String entityClass, String tableName, Map<String, String> propertyAndColumns private String buildTablesClass(String entityClass, String schema, String tableName, Map<String, String> propertyAndColumns
, List<String> defaultColumns, String tablesNameStyle, String realGenPackage, boolean allInTables) { , List<String> defaultColumns, String tablesNameStyle, String realGenPackage, boolean allInTables) {
// tableDefTemplate = " public static final @entityClassTableDef @tableField = new @entityClassTableDef(\"@tableName\");\n"; // tableDefTemplate = " public static final @entityClassTableDef @tableField = new @entityClassTableDef(\"@tableName\");\n";
String tableDef = tableDefTemplate.replace("@entityClass", entityClass) String tableDef = tableDefTemplate.replace("@entityClass", entityClass)
.replace("@schema", schema)
.replace("@tableField", buildName(entityClass, tablesNameStyle)) .replace("@tableField", buildName(entityClass, tablesNameStyle))
.replace("@tableName", tableName); .replace("@tableName", tableName);

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>parent</artifactId> <artifactId>parent</artifactId>
<groupId>com.mybatis-flex</groupId> <groupId>com.mybatis-flex</groupId>
<version>1.3.2</version> <version>1.3.3</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@ -21,7 +21,7 @@
<dependency> <dependency>
<groupId>com.mybatis-flex</groupId> <groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-core</artifactId> <artifactId>mybatis-flex-core</artifactId>
<version>1.3.2</version> <version>1.3.3</version>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>parent</artifactId> <artifactId>parent</artifactId>
<groupId>com.mybatis-flex</groupId> <groupId>com.mybatis-flex</groupId>
<version>1.3.2</version> <version>1.3.3</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@ -21,7 +21,7 @@
<dependency> <dependency>
<groupId>com.mybatis-flex</groupId> <groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring</artifactId> <artifactId>mybatis-flex-spring</artifactId>
<version>1.3.2</version> <version>1.3.3</version>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>parent</artifactId> <artifactId>parent</artifactId>
<groupId>com.mybatis-flex</groupId> <groupId>com.mybatis-flex</groupId>
<version>1.3.2</version> <version>1.3.3</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@ -20,7 +20,7 @@
<dependency> <dependency>
<groupId>com.mybatis-flex</groupId> <groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-core</artifactId> <artifactId>mybatis-flex-core</artifactId>
<version>1.3.2</version> <version>1.3.3</version>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -19,7 +19,7 @@ import com.mybatisflex.core.FlexConsts;
import com.mybatisflex.core.datasource.FlexDataSource; import com.mybatisflex.core.datasource.FlexDataSource;
import com.mybatisflex.core.mybatis.FlexConfiguration; import com.mybatisflex.core.mybatis.FlexConfiguration;
import com.mybatisflex.core.mybatis.FlexSqlSessionFactoryBuilder; import com.mybatisflex.core.mybatis.FlexSqlSessionFactoryBuilder;
import com.mybatisflex.core.mybatis.FlexXMLConfigBuilder; import org.apache.ibatis.builder.xml.XMLConfigBuilder;
import org.apache.ibatis.builder.xml.XMLMapperBuilder; import org.apache.ibatis.builder.xml.XMLMapperBuilder;
import org.apache.ibatis.cache.Cache; import org.apache.ibatis.cache.Cache;
import org.apache.ibatis.executor.ErrorContext; import org.apache.ibatis.executor.ErrorContext;
@ -492,8 +492,7 @@ public class FlexSqlSessionFactoryBean extends SqlSessionFactoryBean
final Configuration targetConfiguration; final Configuration targetConfiguration;
// XMLConfigBuilder xmlConfigBuilder = null; XMLConfigBuilder xmlConfigBuilder = null;
FlexXMLConfigBuilder xmlConfigBuilder = null;
if (this.configuration != null) { if (this.configuration != null) {
targetConfiguration = this.configuration; targetConfiguration = this.configuration;
if (targetConfiguration.getVariables() == null) { if (targetConfiguration.getVariables() == null) {
@ -502,12 +501,11 @@ public class FlexSqlSessionFactoryBean extends SqlSessionFactoryBean
targetConfiguration.getVariables().putAll(this.configurationProperties); targetConfiguration.getVariables().putAll(this.configurationProperties);
} }
} else if (this.configLocation != null) { } else if (this.configLocation != null) {
// xmlConfigBuilder = new XMLConfigBuilder(this.configLocation.getInputStream(), null, this.configurationProperties); xmlConfigBuilder = new XMLConfigBuilder(FlexConfiguration.class, this.configLocation.getInputStream(), null, this.configurationProperties);
xmlConfigBuilder = new FlexXMLConfigBuilder(this.configLocation.getInputStream(), null, this.configurationProperties);
targetConfiguration = xmlConfigBuilder.getConfiguration(); targetConfiguration = xmlConfigBuilder.getConfiguration();
} else { } else {
LOGGER.debug( LOGGER.debug(
() -> "Property 'configuration' or 'configLocation' not specified, using default MyBatis Configuration"); () -> "Property 'configuration' or 'configLocation' not specified, using default Flex Configuration");
// targetConfiguration = new Configuration(); // targetConfiguration = new Configuration();
targetConfiguration = new FlexConfiguration(); targetConfiguration = new FlexConfiguration();
Optional.ofNullable(this.configurationProperties).ifPresent(targetConfiguration::setVariables); Optional.ofNullable(this.configurationProperties).ifPresent(targetConfiguration::setVariables);

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>mybatis-flex-test</artifactId> <artifactId>mybatis-flex-test</artifactId>
<groupId>com.mybatis-flex</groupId> <groupId>com.mybatis-flex</groupId>
<version>1.3.2</version> <version>1.3.3</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@ -20,7 +20,7 @@
<dependency> <dependency>
<groupId>com.mybatis-flex</groupId> <groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-core</artifactId> <artifactId>mybatis-flex-core</artifactId>
<version>1.3.2</version> <version>1.3.3</version>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -21,15 +21,11 @@ import com.mybatisflex.core.audit.ConsoleMessageCollector;
import com.mybatisflex.core.audit.MessageCollector; import com.mybatisflex.core.audit.MessageCollector;
import com.mybatisflex.core.paginate.Page; import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper; import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.row.Db;
import com.mybatisflex.core.row.RowUtil;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import javax.sql.DataSource; import javax.sql.DataSource;
import java.util.List;
import static com.mybatisflex.core.query.QueryMethods.select;
import static com.mybatisflex.test.table.AccountTableDef.ACCOUNT; import static com.mybatisflex.test.table.AccountTableDef.ACCOUNT;
import static com.mybatisflex.test.table.ArticleTableDef.ARTICLE; import static com.mybatisflex.test.table.ArticleTableDef.ARTICLE;
@ -138,7 +134,7 @@ public class EntityTestStarter {
.leftJoin(ACCOUNT).on(ARTICLE.ACCOUNT_ID.eq(ACCOUNT.ID)) .leftJoin(ACCOUNT).on(ARTICLE.ACCOUNT_ID.eq(ACCOUNT.ID))
.where(ARTICLE.ID.ge(0).or(ACCOUNT.ID.ge(0))); .where(ARTICLE.ID.ge(0).or(ACCOUNT.ID.ge(0)));
RowUtil.printPretty(Db.selectListByQuery(asWrapper)); // RowUtil.printPretty(Db.selectListByQuery(asWrapper));
// //
// List<ArticleDTO> articleDTOS = accountMapper.selectListByQueryAs(asWrapper, ArticleDTO.class); // List<ArticleDTO> articleDTOS = accountMapper.selectListByQueryAs(asWrapper, ArticleDTO.class);
// System.out.println(articleDTOS); // System.out.println(articleDTOS);
@ -195,15 +191,15 @@ public class EntityTestStarter {
// .or(SYS_CONFIG.TYPE.like(word).when(StrChecker.isNotBlank(word))) // .or(SYS_CONFIG.TYPE.like(word).when(StrChecker.isNotBlank(word)))
// ); // );
List<Account> accounts = accountMapper.selectListByQuery( // List<Account> accounts = accountMapper.selectListByQuery(
select().where(ACCOUNT.AGE.ge(18).when(false)) // select().where(ACCOUNT.AGE.ge(18).when(false))
.and(ACCOUNT.USER_NAME.like("aaaa").when(false) // .and(ACCOUNT.USER_NAME.like("aaaa").when(false)
.or(ACCOUNT.USER_NAME.like("aaaa").when(false)) // .or(ACCOUNT.USER_NAME.like("aaaa").when(false))
.or(ACCOUNT.USER_NAME.like("aaaa").when(false)) // .or(ACCOUNT.USER_NAME.like("aaaa").when(false))
.or(ACCOUNT.USER_NAME.like("aaaa").when(false)) // .or(ACCOUNT.USER_NAME.like("aaaa").when(false))
) // )
); // );
System.out.println(accounts); // System.out.println(accounts);
// Page<Account> paginate = accountMapper.paginate(1, 10, QueryWrapper.create()); // Page<Account> paginate = accountMapper.paginate(1, 10, QueryWrapper.create());

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>mybatis-flex-test</artifactId> <artifactId>mybatis-flex-test</artifactId>
<groupId>com.mybatis-flex</groupId> <groupId>com.mybatis-flex</groupId>
<version>1.3.2</version> <version>1.3.3</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@ -21,7 +21,7 @@
<dependency> <dependency>
<groupId>com.mybatis-flex</groupId> <groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring-boot-starter</artifactId> <artifactId>mybatis-flex-spring-boot-starter</artifactId>
<version>1.3.2</version> <version>1.3.3</version>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>mybatis-flex-test</artifactId> <artifactId>mybatis-flex-test</artifactId>
<groupId>com.mybatis-flex</groupId> <groupId>com.mybatis-flex</groupId>
<version>1.3.2</version> <version>1.3.3</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@ -20,13 +20,13 @@
<dependency> <dependency>
<groupId>com.mybatis-flex</groupId> <groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-core</artifactId> <artifactId>mybatis-flex-core</artifactId>
<version>1.3.2</version> <version>1.3.3</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.mybatis-flex</groupId> <groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring</artifactId> <artifactId>mybatis-flex-spring</artifactId>
<version>1.3.2</version> <version>1.3.3</version>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>parent</artifactId> <artifactId>parent</artifactId>
<groupId>com.mybatis-flex</groupId> <groupId>com.mybatis-flex</groupId>
<version>1.3.2</version> <version>1.3.3</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@ -59,7 +59,7 @@
<path> <path>
<groupId>com.mybatis-flex</groupId> <groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-processor</artifactId> <artifactId>mybatis-flex-processor</artifactId>
<version>1.3.2</version> <version>1.3.3</version>
</path> </path>
</annotationProcessorPaths> </annotationProcessorPaths>
</configuration> </configuration>

View File

@ -7,7 +7,7 @@
<groupId>com.mybatis-flex</groupId> <groupId>com.mybatis-flex</groupId>
<artifactId>parent</artifactId> <artifactId>parent</artifactId>
<packaging>pom</packaging> <packaging>pom</packaging>
<version>1.3.2</version> <version>1.3.3</version>
<name>mybatis-flex</name> <name>mybatis-flex</name>
<url>https://mybatis-flex.com</url> <url>https://mybatis-flex.com</url>