Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Administrator
magic-api
Commits
02897568
Commit
02897568
authored
Dec 18, 2023
by
liang.tang
Browse files
magic-api
parents
Pipeline
#222
failed with stages
in 0 seconds
Changes
320
Pipelines
1
Show whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
1765 additions
and
0 deletions
+1765
-0
magic-api/src/main/java/org/ssssssss/magicapi/modules/db/BoundSql.java
.../main/java/org/ssssssss/magicapi/modules/db/BoundSql.java
+192
-0
magic-api/src/main/java/org/ssssssss/magicapi/modules/db/ColumnMapperAdapter.java
...org/ssssssss/magicapi/modules/db/ColumnMapperAdapter.java
+64
-0
magic-api/src/main/java/org/ssssssss/magicapi/modules/db/SQLModule.java
...main/java/org/ssssssss/magicapi/modules/db/SQLModule.java
+783
-0
magic-api/src/main/java/org/ssssssss/magicapi/modules/db/SingleRowResultSetExtractor.java
...ssss/magicapi/modules/db/SingleRowResultSetExtractor.java
+50
-0
magic-api/src/main/java/org/ssssssss/magicapi/modules/db/Transaction.java
...in/java/org/ssssssss/magicapi/modules/db/Transaction.java
+40
-0
magic-api/src/main/java/org/ssssssss/magicapi/modules/db/cache/DefaultSqlCache.java
...g/ssssssss/magicapi/modules/db/cache/DefaultSqlCache.java
+37
-0
magic-api/src/main/java/org/ssssssss/magicapi/modules/db/cache/LRUCache.java
...java/org/ssssssss/magicapi/modules/db/cache/LRUCache.java
+133
-0
magic-api/src/main/java/org/ssssssss/magicapi/modules/db/cache/SqlCache.java
...java/org/ssssssss/magicapi/modules/db/cache/SqlCache.java
+56
-0
magic-api/src/main/java/org/ssssssss/magicapi/modules/db/dialect/ClickhouseDialect.java
...ssssss/magicapi/modules/db/dialect/ClickhouseDialect.java
+14
-0
magic-api/src/main/java/org/ssssssss/magicapi/modules/db/dialect/DB2Dialect.java
.../org/ssssssss/magicapi/modules/db/dialect/DB2Dialect.java
+24
-0
magic-api/src/main/java/org/ssssssss/magicapi/modules/db/dialect/Dialect.java
...ava/org/ssssssss/magicapi/modules/db/dialect/Dialect.java
+60
-0
magic-api/src/main/java/org/ssssssss/magicapi/modules/db/dialect/DialectAdapter.java
.../ssssssss/magicapi/modules/db/dialect/DialectAdapter.java
+53
-0
magic-api/src/main/java/org/ssssssss/magicapi/modules/db/dialect/DmDialect.java
...a/org/ssssssss/magicapi/modules/db/dialect/DmDialect.java
+26
-0
magic-api/src/main/java/org/ssssssss/magicapi/modules/db/dialect/KingbaseSQLDialect.java
...sssss/magicapi/modules/db/dialect/KingbaseSQLDialect.java
+24
-0
magic-api/src/main/java/org/ssssssss/magicapi/modules/db/dialect/MySQLDialect.java
...rg/ssssssss/magicapi/modules/db/dialect/MySQLDialect.java
+24
-0
magic-api/src/main/java/org/ssssssss/magicapi/modules/db/dialect/OracleDialect.java
...g/ssssssss/magicapi/modules/db/dialect/OracleDialect.java
+26
-0
magic-api/src/main/java/org/ssssssss/magicapi/modules/db/dialect/PostgreSQLDialect.java
...ssssss/magicapi/modules/db/dialect/PostgreSQLDialect.java
+23
-0
magic-api/src/main/java/org/ssssssss/magicapi/modules/db/dialect/SQLServer2005Dialect.java
...sss/magicapi/modules/db/dialect/SQLServer2005Dialect.java
+67
-0
magic-api/src/main/java/org/ssssssss/magicapi/modules/db/dialect/SQLServerDialect.java
...sssssss/magicapi/modules/db/dialect/SQLServerDialect.java
+23
-0
magic-api/src/main/java/org/ssssssss/magicapi/modules/db/inteceptor/DefaultSqlInterceptor.java
...magicapi/modules/db/inteceptor/DefaultSqlInterceptor.java
+46
-0
No files found.
magic-api/src/main/java/org/ssssssss/magicapi/modules/db/BoundSql.java
0 → 100644
View file @
02897568
package
org.ssssssss.magicapi.modules.db
;
import
org.ssssssss.magicapi.core.context.RequestContext
;
import
org.ssssssss.magicapi.core.context.RequestEntity
;
import
org.ssssssss.magicapi.modules.db.inteceptor.SQLInterceptor
;
import
org.ssssssss.magicapi.modules.db.mybatis.MybatisParser
;
import
org.ssssssss.magicapi.modules.db.mybatis.SqlNode
;
import
org.ssssssss.magicapi.modules.db.mybatis.TextSqlNode
;
import
org.ssssssss.script.runtime.RuntimeContext
;
import
java.util.*
;
import
java.util.function.Supplier
;
import
java.util.regex.Pattern
;
/**
* SQL参数处理
*
* @author mxd
*/
public
class
BoundSql
{
private
static
final
Pattern
REPLACE_MULTI_WHITE_LINE
=
Pattern
.
compile
(
"(\r?\n(\\s*\r?\n)+)"
);
private
static
final
List
<
String
>
MYBATIS_TAGS
=
Arrays
.
asList
(
"</where>"
,
"</if>"
,
"</trim>"
,
"</set>"
,
"</foreach>"
);
private
String
sqlOrXml
;
private
List
<
Object
>
parameters
=
new
ArrayList
<>();
private
Set
<
String
>
excludeColumns
;
private
SQLModule
sqlModule
;
private
Map
<
String
,
Object
>
bindParameters
;
private
RuntimeContext
runtimeContext
;
public
BoundSql
(
RuntimeContext
runtimeContext
,
String
sqlOrXml
,
List
<
Object
>
parameters
,
SQLModule
sqlModule
)
{
this
.
sqlOrXml
=
sqlOrXml
;
this
.
parameters
=
parameters
;
this
.
sqlModule
=
sqlModule
;
this
.
runtimeContext
=
runtimeContext
;
}
public
BoundSql
(
RuntimeContext
runtimeContext
,
String
sqlOrXml
,
Map
<
String
,
Object
>
parameters
,
SQLModule
sqlModule
)
{
this
.
sqlOrXml
=
sqlOrXml
;
this
.
bindParameters
=
parameters
;
this
.
sqlModule
=
sqlModule
;
this
.
runtimeContext
=
runtimeContext
;
this
.
init
();
}
private
BoundSql
(
RuntimeContext
runtimeContext
,
String
sqlOrXml
)
{
this
.
sqlOrXml
=
sqlOrXml
;
this
.
runtimeContext
=
runtimeContext
;
this
.
init
();
}
BoundSql
(
RuntimeContext
runtimeContext
,
String
sql
,
SQLModule
sqlModule
)
{
this
(
runtimeContext
,
sql
);
this
.
sqlModule
=
sqlModule
;
}
private
BoundSql
()
{
}
private
void
init
()
{
Map
<
String
,
Object
>
varMap
=
new
HashMap
<>();
if
(
this
.
bindParameters
!=
null
)
{
varMap
.
putAll
(
this
.
bindParameters
);
}
else
{
varMap
.
putAll
(
runtimeContext
.
getVarMap
());
}
if
(
MYBATIS_TAGS
.
stream
().
anyMatch
(
it
->
this
.
sqlOrXml
.
contains
(
it
)))
{
SqlNode
sqlNode
=
MybatisParser
.
parse
(
this
.
sqlOrXml
);
this
.
sqlOrXml
=
sqlNode
.
getSql
(
varMap
);
this
.
parameters
=
sqlNode
.
getParameters
();
}
else
{
normal
(
varMap
);
}
}
private
void
normal
(
Map
<
String
,
Object
>
varMap
)
{
this
.
sqlOrXml
=
TextSqlNode
.
parseSql
(
this
.
sqlOrXml
,
varMap
,
parameters
);
this
.
sqlOrXml
=
this
.
sqlOrXml
==
null
?
null
:
REPLACE_MULTI_WHITE_LINE
.
matcher
(
this
.
sqlOrXml
.
trim
()).
replaceAll
(
"\r\n"
);
}
public
SQLModule
getSqlModule
()
{
return
sqlModule
;
}
BoundSql
copy
(
String
newSqlOrXml
)
{
BoundSql
boundSql
=
new
BoundSql
();
boundSql
.
parameters
=
this
.
parameters
;
boundSql
.
bindParameters
=
this
.
bindParameters
;
boundSql
.
sqlOrXml
=
newSqlOrXml
;
boundSql
.
excludeColumns
=
this
.
excludeColumns
;
boundSql
.
sqlModule
=
this
.
sqlModule
;
boundSql
.
runtimeContext
=
this
.
runtimeContext
;
return
boundSql
;
}
public
Set
<
String
>
getExcludeColumns
()
{
return
excludeColumns
;
}
public
void
setExcludeColumns
(
Set
<
String
>
excludeColumns
)
{
this
.
excludeColumns
=
excludeColumns
;
}
/**
* 添加SQL参数
*/
public
void
addParameter
(
Object
value
)
{
parameters
.
add
(
value
);
}
/**
* 获取要执行的SQL
*/
public
String
getSql
()
{
return
sqlOrXml
;
}
/**
* 设置要执行的SQL
*/
public
void
setSql
(
String
sql
)
{
this
.
sqlOrXml
=
sql
;
}
/**
* 获取要执行的参数
*/
public
Object
[]
getParameters
()
{
return
parameters
.
toArray
();
}
/**
* 设置要执行的参数
*/
public
void
setParameters
(
List
<
Object
>
parameters
)
{
this
.
parameters
=
parameters
;
}
public
RuntimeContext
getRuntimeContext
()
{
return
runtimeContext
;
}
/**
* 获取缓存值
*/
@SuppressWarnings
({
"unchecked"
})
private
<
T
>
T
getCacheValue
(
String
sql
,
Object
[]
params
,
Supplier
<
T
>
supplier
)
{
if
(
sqlModule
.
getCacheName
()
==
null
)
{
return
supplier
.
get
();
}
String
cacheKey
=
sqlModule
.
getSqlCache
().
buildSqlCacheKey
(
sql
,
params
);
Object
cacheValue
=
sqlModule
.
getSqlCache
().
get
(
sqlModule
.
getCacheName
(),
cacheKey
);
if
(
cacheValue
!=
null
)
{
return
(
T
)
cacheValue
;
}
T
value
=
supplier
.
get
();
sqlModule
.
getSqlCache
().
put
(
sqlModule
.
getCacheName
(),
cacheKey
,
value
,
sqlModule
.
getTtl
());
return
value
;
}
/**
* 获取缓存值
*/
@SuppressWarnings
(
"unchecked"
)
<
T
>
T
execute
(
List
<
SQLInterceptor
>
interceptors
,
Supplier
<
T
>
supplier
)
{
RequestEntity
requestEntity
=
RequestContext
.
getRequestEntity
();
interceptors
.
forEach
(
interceptor
->
interceptor
.
preHandle
(
this
,
requestEntity
));
Supplier
<
T
>
newSupplier
=
()
->
{
Object
result
;
try
{
result
=
supplier
.
get
();
for
(
SQLInterceptor
interceptor
:
interceptors
)
{
result
=
interceptor
.
postHandle
(
this
,
result
,
requestEntity
);
}
}
catch
(
Throwable
e
)
{
interceptors
.
forEach
(
interceptor
->
interceptor
.
handleException
(
this
,
e
,
requestEntity
));
throw
e
;
}
return
(
T
)
result
;
};
return
getCacheValue
(
this
.
getSql
(),
this
.
getParameters
(),
newSupplier
);
}
}
magic-api/src/main/java/org/ssssssss/magicapi/modules/db/ColumnMapperAdapter.java
0 → 100644
View file @
02897568
package
org.ssssssss.magicapi.modules.db
;
import
org.springframework.jdbc.core.RowMapper
;
import
org.ssssssss.magicapi.modules.db.provider.*
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.function.Function
;
/**
* 列名转换适配器
*
* @author mxd
*/
public
class
ColumnMapperAdapter
{
private
final
Map
<
String
,
RowMapper
<
Map
<
String
,
Object
>>>
columnMapRowMappers
=
new
HashMap
<>();
private
final
Map
<
String
,
Function
<
String
,
String
>>
rowMapColumnMappers
=
new
HashMap
<>();
private
RowMapper
<
Map
<
String
,
Object
>>
mapRowColumnMapper
;
private
Function
<
String
,
String
>
rowMapColumnMapper
;
public
ColumnMapperAdapter
()
{
setDefault
(
new
DefaultColumnMapperProvider
());
add
(
new
CamelColumnMapperProvider
());
add
(
new
PascalColumnMapperProvider
());
add
(
new
LowerColumnMapperProvider
());
add
(
new
UpperColumnMapperProvider
());
}
public
void
add
(
ColumnMapperProvider
columnMapperProvider
)
{
columnMapRowMappers
.
put
(
columnMapperProvider
.
name
(),
columnMapperProvider
.
getColumnMapRowMapper
());
rowMapColumnMappers
.
put
(
columnMapperProvider
.
name
(),
columnMapperProvider
.
getRowMapColumnMapper
());
}
public
void
setDefault
(
ColumnMapperProvider
columnMapperProvider
)
{
this
.
mapRowColumnMapper
=
columnMapperProvider
.
getColumnMapRowMapper
();
this
.
rowMapColumnMapper
=
columnMapperProvider
.
getRowMapColumnMapper
();
add
(
columnMapperProvider
);
}
public
void
setDefault
(
String
name
)
{
this
.
mapRowColumnMapper
=
getColumnMapRowMapper
(
name
);
this
.
rowMapColumnMapper
=
getRowMapColumnMapper
(
name
);
}
public
RowMapper
<
Map
<
String
,
Object
>>
getDefaultColumnMapRowMapper
()
{
return
this
.
mapRowColumnMapper
;
}
public
Function
<
String
,
String
>
getDefaultRowMapColumnMapper
()
{
return
this
.
rowMapColumnMapper
;
}
public
RowMapper
<
Map
<
String
,
Object
>>
getColumnMapRowMapper
(
String
name
)
{
return
columnMapRowMappers
.
getOrDefault
(
name
,
mapRowColumnMapper
);
}
public
Function
<
String
,
String
>
getRowMapColumnMapper
(
String
name
)
{
return
rowMapColumnMappers
.
getOrDefault
(
name
,
rowMapColumnMapper
);
}
}
magic-api/src/main/java/org/ssssssss/magicapi/modules/db/SQLModule.java
0 → 100644
View file @
02897568
package
org.ssssssss.magicapi.modules.db
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.jdbc.core.*
;
import
org.springframework.jdbc.support.GeneratedKeyHolder
;
import
org.ssssssss.magicapi.core.model.Options
;
import
org.ssssssss.magicapi.modules.DynamicModule
;
import
org.ssssssss.magicapi.modules.db.dialect.DialectAdapter
;
import
org.ssssssss.magicapi.datasource.model.MagicDynamicDataSource
;
import
org.ssssssss.magicapi.datasource.model.MagicDynamicDataSource.DataSourceNode
;
import
org.ssssssss.magicapi.core.annotation.MagicModule
;
import
org.ssssssss.magicapi.core.context.RequestContext
;
import
org.ssssssss.magicapi.core.context.RequestEntity
;
import
org.ssssssss.magicapi.modules.db.cache.SqlCache
;
import
org.ssssssss.magicapi.modules.db.dialect.Dialect
;
import
org.ssssssss.magicapi.modules.db.inteceptor.NamedTableInterceptor
;
import
org.ssssssss.magicapi.modules.db.inteceptor.SQLInterceptor
;
import
org.ssssssss.magicapi.modules.db.model.Page
;
import
org.ssssssss.magicapi.modules.db.provider.PageProvider
;
import
org.ssssssss.magicapi.modules.db.table.NamedTable
;
import
org.ssssssss.magicapi.core.interceptor.ResultProvider
;
import
org.ssssssss.magicapi.utils.ScriptManager
;
import
org.ssssssss.script.MagicScriptContext
;
import
org.ssssssss.script.annotation.Comment
;
import
org.ssssssss.script.functions.DynamicAttribute
;
import
org.ssssssss.script.parsing.ast.statement.ClassConverter
;
import
org.ssssssss.script.reflection.JavaReflection
;
import
org.ssssssss.script.runtime.RuntimeContext
;
import
java.beans.Transient
;
import
java.lang.reflect.Field
;
import
java.sql.*
;
import
java.util.*
;
import
java.util.function.Function
;
import
java.util.stream.Collectors
;
import
java.util.stream.Stream
;
/**
* 数据库查询模块
*
* @author mxd
*/
@MagicModule
(
"db"
)
public
class
SQLModule
implements
DynamicAttribute
<
SQLModule
,
SQLModule
>,
DynamicModule
<
SQLModule
>
{
static
{
try
{
Field
[]
fields
=
Types
.
class
.
getFields
();
Map
<
String
,
Integer
>
mappings
=
Stream
.
of
(
fields
)
.
collect
(
Collectors
.
toMap
(
field
->
field
.
getName
().
toLowerCase
(),
field
->
(
Integer
)
JavaReflection
.
getFieldValue
(
Types
.
class
,
field
)));
ClassConverter
.
register
(
"sql"
,
(
value
,
params
)
->
{
if
(
params
==
null
||
params
.
length
==
0
)
{
return
value
;
}
if
(
params
[
0
]
instanceof
Number
)
{
return
new
SqlParameterValue
(((
Number
)
params
[
0
]).
intValue
(),
value
);
}
String
target
=
Objects
.
toString
(
params
[
0
],
null
);
if
(
StringUtils
.
isBlank
(
target
))
{
return
value
;
}
Integer
sqlType
=
mappings
.
get
(
target
.
toLowerCase
());
return
sqlType
==
null
?
value
:
new
SqlParameterValue
(
sqlType
,
target
,
value
);
});
}
catch
(
Exception
ignored
)
{
}
}
private
MagicDynamicDataSource
dynamicDataSource
;
private
DataSourceNode
dataSourceNode
;
private
PageProvider
pageProvider
;
private
ResultProvider
resultProvider
;
private
ColumnMapperAdapter
columnMapperAdapter
;
private
DialectAdapter
dialectAdapter
;
private
RowMapper
<
Map
<
String
,
Object
>>
columnMapRowMapper
;
private
Function
<
String
,
String
>
rowMapColumnMapper
;
private
SqlCache
sqlCache
;
private
String
cacheName
;
private
List
<
SQLInterceptor
>
sqlInterceptors
;
private
List
<
NamedTableInterceptor
>
namedTableInterceptors
;
private
long
ttl
;
private
String
logicDeleteColumn
;
private
String
logicDeleteValue
;
public
SQLModule
()
{
}
public
SQLModule
(
MagicDynamicDataSource
dynamicDataSource
)
{
this
.
dynamicDataSource
=
dynamicDataSource
;
}
@Transient
public
void
setPageProvider
(
PageProvider
pageProvider
)
{
this
.
pageProvider
=
pageProvider
;
}
@Transient
public
void
setResultProvider
(
ResultProvider
resultProvider
)
{
this
.
resultProvider
=
resultProvider
;
}
@Transient
public
void
setColumnMapperProvider
(
ColumnMapperAdapter
columnMapperAdapter
)
{
this
.
columnMapperAdapter
=
columnMapperAdapter
;
}
@Transient
public
void
setDialectAdapter
(
DialectAdapter
dialectAdapter
)
{
this
.
dialectAdapter
=
dialectAdapter
;
}
@Transient
public
void
setColumnMapRowMapper
(
RowMapper
<
Map
<
String
,
Object
>>
columnMapRowMapper
)
{
this
.
columnMapRowMapper
=
columnMapRowMapper
;
}
@Transient
public
void
setRowMapColumnMapper
(
Function
<
String
,
String
>
rowMapColumnMapper
)
{
this
.
rowMapColumnMapper
=
rowMapColumnMapper
;
}
@Transient
public
void
setDynamicDataSource
(
MagicDynamicDataSource
dynamicDataSource
)
{
this
.
dynamicDataSource
=
dynamicDataSource
;
}
@Transient
public
void
setSqlInterceptors
(
List
<
SQLInterceptor
>
sqlInterceptors
)
{
this
.
sqlInterceptors
=
sqlInterceptors
;
}
@Transient
public
void
setNamedTableInterceptors
(
List
<
NamedTableInterceptor
>
namedTableInterceptors
)
{
this
.
namedTableInterceptors
=
namedTableInterceptors
;
}
@Transient
public
void
setDataSourceNode
(
DataSourceNode
dataSourceNode
)
{
this
.
dataSourceNode
=
dataSourceNode
;
}
@Transient
public
String
getCacheName
()
{
return
cacheName
;
}
@Transient
public
void
setCacheName
(
String
cacheName
)
{
this
.
cacheName
=
cacheName
;
}
@Transient
public
long
getTtl
()
{
return
ttl
;
}
@Transient
public
void
setTtl
(
long
ttl
)
{
this
.
ttl
=
ttl
;
}
@Transient
public
String
getLogicDeleteColumn
()
{
return
logicDeleteColumn
;
}
@Transient
public
void
setLogicDeleteColumn
(
String
logicDeleteColumn
)
{
this
.
logicDeleteColumn
=
logicDeleteColumn
;
}
@Transient
public
String
getLogicDeleteValue
()
{
return
logicDeleteValue
;
}
@Transient
public
void
setLogicDeleteValue
(
String
logicDeleteValue
)
{
this
.
logicDeleteValue
=
logicDeleteValue
;
}
@Transient
public
SqlCache
getSqlCache
()
{
return
sqlCache
;
}
@Transient
public
void
setSqlCache
(
SqlCache
sqlCache
)
{
this
.
sqlCache
=
sqlCache
;
}
@Transient
public
SQLModule
cloneSQLModule
()
{
SQLModule
sqlModule
=
new
SQLModule
();
sqlModule
.
setDynamicDataSource
(
this
.
dynamicDataSource
);
sqlModule
.
setDataSourceNode
(
this
.
dataSourceNode
);
sqlModule
.
setPageProvider
(
this
.
pageProvider
);
sqlModule
.
setColumnMapperProvider
(
this
.
columnMapperAdapter
);
sqlModule
.
setColumnMapRowMapper
(
this
.
columnMapRowMapper
);
sqlModule
.
setRowMapColumnMapper
(
this
.
rowMapColumnMapper
);
sqlModule
.
setSqlCache
(
this
.
sqlCache
);
sqlModule
.
setTtl
(
this
.
ttl
);
sqlModule
.
setCacheName
(
this
.
cacheName
);
sqlModule
.
setResultProvider
(
this
.
resultProvider
);
sqlModule
.
setDialectAdapter
(
this
.
dialectAdapter
);
sqlModule
.
setSqlInterceptors
(
this
.
sqlInterceptors
);
sqlModule
.
setLogicDeleteValue
(
this
.
logicDeleteValue
);
sqlModule
.
setLogicDeleteColumn
(
this
.
logicDeleteColumn
);
sqlModule
.
setNamedTableInterceptors
(
this
.
namedTableInterceptors
);
return
sqlModule
;
}
/**
* 开启事务,在一个回调中进行操作
*
* @param function 回调函数
*/
@Comment
(
"开启事务,并在回调中处理"
)
public
Object
transaction
(
@Comment
(
name
=
"function"
,
value
=
"回调函数,如:()=>{....}"
)
Function
<?,
?>
function
)
{
// 创建事务
Transaction
transaction
=
transaction
();
try
{
Object
val
=
function
.
apply
(
null
);
transaction
.
commit
();
//提交事务
return
val
;
}
catch
(
Throwable
throwable
)
{
transaction
.
rollback
();
//回滚事务
throw
throwable
;
}
}
/**
* 开启事务,手动提交和回滚
*/
@Comment
(
"开启事务,返回事务对象"
)
public
Transaction
transaction
()
{
return
new
Transaction
(
this
.
dataSourceNode
.
getDataSourceTransactionManager
());
}
/**
* 使用缓存
*
* @param cacheName 缓存名
* @param ttl 过期时间
*/
@Comment
(
"使用缓存"
)
public
SQLModule
cache
(
@Comment
(
name
=
"cacheName"
,
value
=
"缓存名"
)
String
cacheName
,
@Comment
(
name
=
"ttl"
,
value
=
"过期时间"
)
long
ttl
)
{
if
(
cacheName
==
null
)
{
return
this
;
}
SQLModule
sqlModule
=
cloneSQLModule
();
sqlModule
.
setCacheName
(
cacheName
);
sqlModule
.
setTtl
(
ttl
);
return
sqlModule
;
}
/**
* 使用缓存(采用默认缓存时间)
*
* @param cacheName 缓冲名
*/
@Comment
(
"使用缓存,过期时间采用默认配置"
)
public
SQLModule
cache
(
@Comment
(
name
=
"cacheName"
,
value
=
"缓存名"
)
String
cacheName
)
{
return
cache
(
cacheName
,
0
);
}
@Comment
(
"采用驼峰列名"
)
public
SQLModule
camel
()
{
return
columnCase
(
"camel"
);
}
@Comment
(
"采用帕斯卡列名"
)
public
SQLModule
pascal
()
{
return
columnCase
(
"pascal"
);
}
@Comment
(
"采用全小写列名"
)
public
SQLModule
lower
()
{
return
columnCase
(
"lower"
);
}
@Comment
(
"采用全大写列名"
)
public
SQLModule
upper
()
{
return
columnCase
(
"upper"
);
}
@Comment
(
"列名保持原样"
)
public
SQLModule
normal
()
{
return
columnCase
(
"default"
);
}
@Comment
(
"指定列名转换"
)
public
SQLModule
columnCase
(
String
name
)
{
SQLModule
sqlModule
=
cloneSQLModule
();
sqlModule
.
setColumnMapRowMapper
(
this
.
columnMapperAdapter
.
getColumnMapRowMapper
(
name
));
sqlModule
.
setRowMapColumnMapper
(
this
.
columnMapperAdapter
.
getRowMapColumnMapper
(
name
));
return
sqlModule
;
}
/**
* 数据源切换
*/
@Override
@Transient
public
SQLModule
getDynamicAttribute
(
String
key
)
{
SQLModule
sqlModule
=
cloneSQLModule
();
if
(
key
==
null
)
{
sqlModule
.
setDataSourceNode
(
dynamicDataSource
.
getDataSource
());
}
else
{
sqlModule
.
setDataSourceNode
(
dynamicDataSource
.
getDataSource
(
key
));
}
return
sqlModule
;
}
/**
* 查询List
*/
@Comment
(
"查询SQL,返回List类型结果"
)
public
List
<
Map
<
String
,
Object
>>
select
(
RuntimeContext
runtimeContext
,
@Comment
(
name
=
"sqlOrXml"
,
value
=
"`SQL`语句或`xml`"
)
String
sqlOrXml
)
{
return
select
(
runtimeContext
,
sqlOrXml
,
null
);
}
/**
* 查询List,并传入变量信息
*/
@Comment
(
"查询SQL,并传入变量信息,返回List类型结果"
)
public
List
<
Map
<
String
,
Object
>>
select
(
RuntimeContext
runtimeContext
,
@Comment
(
name
=
"sqlOrXml"
,
value
=
"`SQL`语句或`xml`"
)
String
sqlOrXml
,
@Comment
(
name
=
"params"
,
value
=
"变量信息"
)
Map
<
String
,
Object
>
params
)
{
return
select
(
new
BoundSql
(
runtimeContext
,
sqlOrXml
,
params
,
this
));
}
@Transient
public
List
<
Map
<
String
,
Object
>>
select
(
BoundSql
boundSql
)
{
assertDatasourceNotNull
();
return
boundSql
.
execute
(
this
.
sqlInterceptors
,
()
->
queryForList
(
boundSql
));
}
private
List
<
Map
<
String
,
Object
>>
queryForList
(
BoundSql
boundSql
)
{
List
<
Map
<
String
,
Object
>>
list
=
dataSourceNode
.
getJdbcTemplate
().
query
(
boundSql
.
getSql
(),
this
.
columnMapRowMapper
,
boundSql
.
getParameters
());
if
(
boundSql
.
getExcludeColumns
()
!=
null
)
{
list
.
forEach
(
row
->
boundSql
.
getExcludeColumns
().
forEach
(
row:
:
remove
));
}
return
list
;
}
private
void
assertDatasourceNotNull
()
{
if
(
dataSourceNode
==
null
)
{
throw
new
NullPointerException
(
"当前数据源未设置"
);
}
}
/**
* 执行update
*/
@Comment
(
"执行update操作,返回受影响行数"
)
public
int
update
(
RuntimeContext
runtimeContext
,
@Comment
(
name
=
"sqlOrXml"
,
value
=
"`SQL`语句或`xml`"
)
String
sqlOrXml
)
{
return
update
(
runtimeContext
,
sqlOrXml
,
null
);
}
/**
* 执行update,并传入变量信息
*/
@Comment
(
"执行update操作,并传入变量信息,返回受影响行数"
)
public
int
update
(
RuntimeContext
runtimeContext
,
@Comment
(
name
=
"sqlOrXml"
,
value
=
"`SQL`语句或`xml`"
)
String
sqlOrXml
,
@Comment
(
name
=
"params"
,
value
=
"变量信息"
)
Map
<
String
,
Object
>
params
)
{
return
update
(
new
BoundSql
(
runtimeContext
,
sqlOrXml
,
params
,
this
));
}
@Transient
public
int
update
(
BoundSql
boundSql
)
{
assertDatasourceNotNull
();
RequestEntity
requestEntity
=
RequestContext
.
getRequestEntity
();
sqlInterceptors
.
forEach
(
sqlInterceptor
->
sqlInterceptor
.
preHandle
(
boundSql
,
requestEntity
));
Object
value
=
dataSourceNode
.
getJdbcTemplate
().
update
(
boundSql
.
getSql
(),
boundSql
.
getParameters
());
deleteCache
(
this
.
cacheName
);
for
(
SQLInterceptor
sqlInterceptor
:
sqlInterceptors
)
{
value
=
sqlInterceptor
.
postHandle
(
boundSql
,
value
,
requestEntity
);
}
return
(
int
)
value
;
}
/**
* 插入并返回主键
*/
@Comment
(
"执行insert操作,返回插入主键"
)
public
Object
insert
(
RuntimeContext
runtimeContext
,
@Comment
(
name
=
"sqlOrXml"
,
value
=
"`SQL`语句或`xml`"
)
String
sqlOrXml
)
{
return
insert
(
runtimeContext
,
sqlOrXml
,
null
,
null
);
}
/**
* 插入并返回主键,并传入变量信息
*/
@Comment
(
"执行insert操作,并传入变量信息,返回插入主键"
)
public
Object
insert
(
RuntimeContext
runtimeContext
,
@Comment
(
name
=
"sqlOrXml"
,
value
=
"`SQL`语句或`xml`"
)
String
sqlOrXml
,
@Comment
(
name
=
"params"
,
value
=
"变量信息"
)
Map
<
String
,
Object
>
params
)
{
return
insert
(
runtimeContext
,
sqlOrXml
,
null
,
params
);
}
/**
* 插入并返回主键
*/
@Comment
(
"执行insert操作,返回插入主键"
)
public
Object
insert
(
RuntimeContext
runtimeContext
,
@Comment
(
name
=
"sqlOrXml"
,
value
=
"`SQL`语句或`xml`"
)
String
sqlOrXml
,
@Comment
(
name
=
"primary"
,
value
=
"主键列"
)
String
primary
)
{
return
insert
(
runtimeContext
,
sqlOrXml
,
primary
,
null
);
}
/**
* 插入并返回主键
*/
@Comment
(
"执行insert操作,并传入主键和变量信息,返回插入主键"
)
public
Object
insert
(
RuntimeContext
runtimeContext
,
@Comment
(
name
=
"sqlOrXml"
,
value
=
"`SQL`语句或`xml`"
)
String
sqlOrXml
,
@Comment
(
name
=
"primary"
,
value
=
"主键列"
)
String
primary
,
@Comment
(
name
=
"params"
,
value
=
"变量信息"
)
Map
<
String
,
Object
>
params
)
{
return
insert
(
new
BoundSql
(
runtimeContext
,
sqlOrXml
,
params
,
this
),
primary
);
}
void
insert
(
BoundSql
boundSql
,
MagicKeyHolder
keyHolder
)
{
assertDatasourceNotNull
();
dataSourceNode
.
getJdbcTemplate
().
update
(
con
->
{
PreparedStatement
ps
=
keyHolder
.
createPrepareStatement
(
con
,
boundSql
.
getSql
());
new
ArgumentPreparedStatementSetter
(
boundSql
.
getParameters
()).
setValues
(
ps
);
return
ps
;
},
keyHolder
);
deleteCache
(
this
.
cacheName
);
}
/**
* 插入并返回主键
*/
@Comment
(
"批量执行操作,返回受影响的行数"
)
public
int
batchUpdate
(
String
sql
,
List
<
Object
[]>
args
)
{
assertDatasourceNotNull
();
int
[]
values
=
dataSourceNode
.
getJdbcTemplate
().
batchUpdate
(
sql
,
args
);
deleteCache
(
this
.
cacheName
);
return
Arrays
.
stream
(
values
).
sum
();
}
@Transient
public
JdbcTemplate
getJdbcTemplate
()
{
assertDatasourceNotNull
();
return
dataSourceNode
.
getJdbcTemplate
();
}
@Comment
(
"删除`SQL`缓存"
)
public
SQLModule
deleteCache
(
@Comment
(
"缓存名称"
)
String
name
)
{
if
(
StringUtils
.
isNotBlank
(
name
))
{
sqlCache
.
delete
(
name
);
}
return
this
;
}
/**
* 插入并返回主键
*/
@Comment
(
"批量执行操作,返回受影响的行数"
)
public
int
batchUpdate
(
String
sql
,
int
batchSize
,
List
<
Object
[]>
args
)
{
assertDatasourceNotNull
();
int
[][]
values
=
dataSourceNode
.
getJdbcTemplate
().
batchUpdate
(
sql
,
args
,
batchSize
,
(
ps
,
arguments
)
->
{
int
colIndex
=
1
;
for
(
Object
value
:
arguments
)
{
if
(
value
instanceof
SqlParameterValue
)
{
SqlParameterValue
paramValue
=
(
SqlParameterValue
)
value
;
StatementCreatorUtils
.
setParameterValue
(
ps
,
colIndex
++,
paramValue
,
paramValue
.
getValue
());
}
else
{
StatementCreatorUtils
.
setParameterValue
(
ps
,
colIndex
++,
StatementCreatorUtils
.
javaTypeToSqlParameterType
(
value
==
null
?
null
:
value
.
getClass
()),
value
);
}
}
});
deleteCache
(
this
.
cacheName
);
int
count
=
0
;
for
(
int
[]
value
:
values
)
{
count
+=
Arrays
.
stream
(
value
).
sum
();
}
return
count
;
}
/**
* 插入并返回主键
*/
@Comment
(
"批量执行操作,返回受影响的行数"
)
public
int
batchUpdate
(
@Comment
(
name
=
"sqls"
,
value
=
"`SQL`语句"
)
List
<
String
>
sqls
)
{
assertDatasourceNotNull
();
int
[]
values
=
dataSourceNode
.
getJdbcTemplate
().
batchUpdate
(
sqls
.
toArray
(
new
String
[
0
]));
deleteCache
(
this
.
cacheName
);
return
Arrays
.
stream
(
values
).
sum
();
}
@Transient
public
Object
insert
(
BoundSql
boundSql
,
String
primary
)
{
MagicKeyHolder
keyHolder
=
new
MagicKeyHolder
(
primary
);
RequestEntity
requestEntity
=
RequestContext
.
getRequestEntity
();
sqlInterceptors
.
forEach
(
sqlInterceptor
->
sqlInterceptor
.
preHandle
(
boundSql
,
requestEntity
));
insert
(
boundSql
,
keyHolder
);
Object
value
=
keyHolder
.
getObjectKey
();
for
(
SQLInterceptor
sqlInterceptor
:
sqlInterceptors
)
{
value
=
sqlInterceptor
.
postHandle
(
boundSql
,
value
,
requestEntity
);
}
return
value
;
}
/**
* 分页查询
*/
@Comment
(
"执行分页查询,分页条件自动获取"
)
public
Object
page
(
RuntimeContext
runtimeContext
,
@Comment
(
name
=
"sqlOrXml"
,
value
=
"`SQL`语句或`xml`"
)
String
sqlOrXml
,
@Comment
(
name
=
"params"
,
value
=
"变量信息"
)
Map
<
String
,
Object
>
params
)
{
return
page
(
new
BoundSql
(
runtimeContext
,
sqlOrXml
,
params
,
this
));
}
/**
* 分页查询,并传入变量信息
*/
@Comment
(
"执行分页查询,并传入变量信息,分页条件自动获取"
)
public
Object
page
(
RuntimeContext
runtimeContext
,
@Comment
(
name
=
"sqlOrXml"
,
value
=
"`SQL`语句或`xml`"
)
String
sqlOrXml
)
{
return
page
(
runtimeContext
,
sqlOrXml
,
(
Map
<
String
,
Object
>)
null
);
}
/**
* 分页查询(手动传入limit和offset参数)
*/
@Comment
(
"执行分页查询,分页条件手动传入"
)
public
Object
page
(
RuntimeContext
runtimeContext
,
@Comment
(
name
=
"sqlOrXml"
,
value
=
"`SQL`语句或`xml`"
)
String
sqlOrXml
,
@Comment
(
name
=
"limit"
,
value
=
"限制条数"
)
long
limit
,
@Comment
(
name
=
"offset"
,
value
=
"跳过条数"
)
long
offset
)
{
return
page
(
runtimeContext
,
sqlOrXml
,
limit
,
offset
,
null
);
}
/**
* 分页查询(手动传入limit和offset参数)
*/
@Comment
(
"执行分页查询,并传入变量信息,分页条件手动传入"
)
public
Object
page
(
RuntimeContext
runtimeContext
,
@Comment
(
name
=
"sqlOrXml"
,
value
=
"`SQL`语句或`xml`"
)
String
sqlOrXml
,
@Comment
(
name
=
"limit"
,
value
=
"限制条数"
)
long
limit
,
@Comment
(
name
=
"offset"
,
value
=
"跳过条数"
)
long
offset
,
@Comment
(
name
=
"params"
,
value
=
"变量信息"
)
Map
<
String
,
Object
>
params
)
{
BoundSql
boundSql
=
new
BoundSql
(
runtimeContext
,
sqlOrXml
,
params
,
this
);
return
page
(
boundSql
,
new
Page
(
limit
,
offset
));
}
@Transient
public
Object
page
(
BoundSql
boundSql
)
{
Page
page
=
pageProvider
.
getPage
(
boundSql
.
getRuntimeContext
());
return
page
(
boundSql
,
page
);
}
@Transient
public
String
getDataSourceName
()
{
return
this
.
dataSourceNode
==
null
?
"unknown"
:
dataSourceNode
.
getName
();
}
/**
* 分页查询(手动传入分页SQL语句)
*/
@Comment
(
"执行分页查询,分页`SQL`语句手动传入"
)
public
Object
page
(
RuntimeContext
runtimeContext
,
@Comment
(
name
=
"countSqlOrXml"
,
value
=
"count语句"
)
String
countSqlOrXml
,
@Comment
(
name
=
"sqlOrXml"
,
value
=
"查询语句"
)
String
sqlOrXml
)
{
return
page
(
runtimeContext
,
countSqlOrXml
,
sqlOrXml
,
null
);
}
/**
* 分页查询(手动传入分页SQL语句)
*/
@Comment
(
"执行分页查询,并传入变量信息,分页`SQL`countSqlOrXml"
)
public
Object
page
(
RuntimeContext
runtimeContext
,
@Comment
(
name
=
"countSqlOrXml"
,
value
=
"count语句"
)
String
countSqlOrXml
,
@Comment
(
name
=
"sqlOrXml"
,
value
=
"查询语句"
)
String
sqlOrXml
,
@Comment
(
name
=
"params"
,
value
=
"变量信息"
)
Map
<
String
,
Object
>
params
)
{
int
count
=
selectInt
(
new
BoundSql
(
runtimeContext
,
countSqlOrXml
,
params
,
this
));
Page
page
=
pageProvider
.
getPage
(
runtimeContext
);
BoundSql
boundSql
=
new
BoundSql
(
runtimeContext
,
sqlOrXml
,
params
,
this
);
return
page
(
count
,
boundSql
,
page
,
null
);
}
/**
* 分页查询(手动传入count)
*/
@Comment
(
"执行分页查询,并传入变量信息,分页`SQL`count"
)
public
Object
page
(
RuntimeContext
runtimeContext
,
@Comment
(
name
=
"count"
,
value
=
"总条数"
)
int
count
,
@Comment
(
name
=
"sqlOrXml"
,
value
=
"查询语句"
)
String
sqlOrXml
,
@Comment
(
name
=
"limit"
,
value
=
"限制条数"
)
long
limit
,
@Comment
(
name
=
"offset"
,
value
=
"跳过条数"
)
long
offset
,
@Comment
(
name
=
"params"
,
value
=
"变量信息"
)
Map
<
String
,
Object
>
params
)
{
BoundSql
boundSql
=
new
BoundSql
(
runtimeContext
,
sqlOrXml
,
params
,
this
);
return
page
(
count
,
boundSql
,
new
Page
(
limit
,
offset
),
null
);
}
private
Object
page
(
int
count
,
BoundSql
boundSql
,
Page
page
,
Dialect
dialect
)
{
List
<
Map
<
String
,
Object
>>
list
=
null
;
if
(
count
>
0
)
{
if
(
dialect
==
null
)
{
dialect
=
dataSourceNode
.
getDialect
(
dialectAdapter
);
}
BoundSql
pageBoundSql
=
buildPageBoundSql
(
dialect
,
boundSql
,
page
.
getOffset
(),
page
.
getLimit
());
list
=
pageBoundSql
.
execute
(
this
.
sqlInterceptors
,
()
->
queryForList
(
pageBoundSql
));
}
RequestEntity
requestEntity
=
RequestContext
.
getRequestEntity
();
return
resultProvider
.
buildPageResult
(
requestEntity
,
page
,
count
,
list
);
}
@Transient
public
Object
page
(
BoundSql
boundSql
,
Page
page
)
{
assertDatasourceNotNull
();
Dialect
dialect
=
dataSourceNode
.
getDialect
(
dialectAdapter
);
BoundSql
countBoundSql
=
boundSql
.
copy
(
dialect
.
getCountSql
(
boundSql
.
getSql
()));
int
count
=
selectInt
(
countBoundSql
);
return
page
(
count
,
boundSql
,
page
,
dialect
);
}
/**
* 查询总条目数
*/
@Comment
(
"查询总条目数"
)
public
Integer
count
(
RuntimeContext
runtimeContext
,
@Comment
(
name
=
"sqlOrXml"
,
value
=
"`SQL`语句或`xml`"
)
String
sqlOrXml
)
{
return
count
(
runtimeContext
,
sqlOrXml
,
null
);
}
/**
* 查询总条目数
*/
@Comment
(
"查询总条目数,并传入变量信息"
)
public
Integer
count
(
RuntimeContext
runtimeContext
,
@Comment
(
name
=
"sqlOrXml"
,
value
=
"`SQL`语句或`xml`"
)
String
sqlOrXml
,
@Comment
(
name
=
"params"
,
value
=
"变量信息"
)
Map
<
String
,
Object
>
params
)
{
BoundSql
boundSql
=
new
BoundSql
(
runtimeContext
,
sqlOrXml
,
params
,
this
);
Dialect
dialect
=
dataSourceNode
.
getDialect
(
dialectAdapter
);
BoundSql
countBoundSql
=
boundSql
.
copy
(
dialect
.
getCountSql
(
boundSql
.
getSql
()));
return
selectInt
(
countBoundSql
);
}
/**
* 查询int值
*/
@Comment
(
"查询int值,适合单行单列int的结果"
)
public
Integer
selectInt
(
RuntimeContext
runtimeContext
,
@Comment
(
name
=
"sqlOrXml"
,
value
=
"`SQL`语句或`xml`"
)
String
sqlOrXml
)
{
return
selectInt
(
runtimeContext
,
sqlOrXml
,
null
);
}
/**
* 查询int值
*/
@Comment
(
"查询int值,并传入变量信息,适合单行单列int的结果"
)
public
Integer
selectInt
(
RuntimeContext
runtimeContext
,
@Comment
(
name
=
"sqlOrXml"
,
value
=
"`SQL`语句或`xml`"
)
String
sqlOrXml
,
@Comment
(
name
=
"params"
,
value
=
"变量信息"
)
Map
<
String
,
Object
>
params
)
{
return
selectInt
(
new
BoundSql
(
runtimeContext
,
sqlOrXml
,
params
,
this
));
}
@Transient
public
Integer
selectInt
(
BoundSql
boundSql
)
{
assertDatasourceNotNull
();
return
boundSql
.
execute
(
this
.
sqlInterceptors
,
()
->
dataSourceNode
.
getJdbcTemplate
().
query
(
boundSql
.
getSql
(),
new
SingleRowResultSetExtractor
<>(
Integer
.
class
),
boundSql
.
getParameters
()));
}
/**
* 查询Map
*/
@Comment
(
"查询单条结果,查不到返回null"
)
public
Map
<
String
,
Object
>
selectOne
(
RuntimeContext
runtimeContext
,
@Comment
(
name
=
"sqlOrXml"
,
value
=
"`SQL`语句或`xml`"
)
String
sqlOrXml
)
{
return
selectOne
(
runtimeContext
,
sqlOrXml
,
null
);
}
/**
* 查询Map,并传入变量信息
*/
@Comment
(
"查询单条结果,并传入变量信息,查不到返回null"
)
public
Map
<
String
,
Object
>
selectOne
(
RuntimeContext
runtimeContext
,
@Comment
(
name
=
"sqlOrXml"
,
value
=
"`SQL`语句或`xml`"
)
String
sqlOrXml
,
@Comment
(
name
=
"params"
,
value
=
"变量信息"
)
Map
<
String
,
Object
>
params
)
{
return
selectOne
(
new
BoundSql
(
runtimeContext
,
sqlOrXml
,
params
,
this
));
}
@Transient
public
Map
<
String
,
Object
>
selectOne
(
BoundSql
boundSql
)
{
assertDatasourceNotNull
();
return
boundSql
.
execute
(
this
.
sqlInterceptors
,
()
->
{
Map
<
String
,
Object
>
row
=
dataSourceNode
.
getJdbcTemplate
().
query
(
boundSql
.
getSql
(),
new
SingleRowResultSetExtractor
<>(
this
.
columnMapRowMapper
),
boundSql
.
getParameters
());
if
(
row
!=
null
&&
boundSql
.
getExcludeColumns
()
!=
null
)
{
boundSql
.
getExcludeColumns
().
forEach
(
row:
:
remove
);
}
return
row
;
});
}
/**
* 查询单行单列的值
*/
@Comment
(
"查询单行单列的值"
)
public
Object
selectValue
(
RuntimeContext
runtimeContext
,
@Comment
(
name
=
"sqlOrXml"
,
value
=
"`SQL`语句或`xml`"
)
String
sqlOrXml
)
{
return
selectValue
(
runtimeContext
,
sqlOrXml
,
null
);
}
/**
* 查询单行单列的值,并传入变量信息
*/
@Comment
(
"查询单行单列的值,并传入变量信息"
)
public
Object
selectValue
(
RuntimeContext
runtimeContext
,
@Comment
(
name
=
"sqlOrXml"
,
value
=
"`SQL`语句或`xml`"
)
String
sqlOrXml
,
@Comment
(
name
=
"params"
,
value
=
"变量信息"
)
Map
<
String
,
Object
>
params
)
{
assertDatasourceNotNull
();
BoundSql
boundSql
=
new
BoundSql
(
runtimeContext
,
sqlOrXml
,
params
,
this
);
return
boundSql
.
execute
(
this
.
sqlInterceptors
,
()
->
dataSourceNode
.
getJdbcTemplate
().
query
(
boundSql
.
getSql
(),
new
SingleRowResultSetExtractor
<>(
Object
.
class
),
boundSql
.
getParameters
()));
}
@Comment
(
"指定table,进行单表操作"
)
public
NamedTable
table
(
@Comment
(
name
=
"tableName"
,
value
=
"表名"
)
String
tableName
)
{
return
new
NamedTable
(
tableName
,
this
,
rowMapColumnMapper
,
namedTableInterceptors
);
}
private
BoundSql
buildPageBoundSql
(
Dialect
dialect
,
BoundSql
boundSql
,
long
offset
,
long
limit
)
{
String
pageSql
=
dialect
.
getPageSql
(
boundSql
.
getSql
(),
boundSql
,
offset
,
limit
);
return
boundSql
.
copy
(
pageSql
);
}
@Transient
@Override
public
SQLModule
getDynamicModule
(
MagicScriptContext
context
)
{
String
dataSourceKey
=
context
.
getString
(
Options
.
DEFAULT_DATA_SOURCE
.
getValue
());
if
(
StringUtils
.
isEmpty
(
dataSourceKey
))
return
this
;
SQLModule
newSqlModule
=
cloneSQLModule
();
newSqlModule
.
setDataSourceNode
(
dynamicDataSource
.
getDataSource
(
dataSourceKey
));
return
newSqlModule
;
}
static
class
MagicKeyHolder
extends
GeneratedKeyHolder
{
private
final
boolean
useGeneratedKeys
;
private
final
String
primary
;
public
MagicKeyHolder
()
{
this
(
null
);
}
public
MagicKeyHolder
(
String
primary
)
{
this
.
primary
=
primary
;
this
.
useGeneratedKeys
=
StringUtils
.
isBlank
(
primary
);
}
PreparedStatement
createPrepareStatement
(
Connection
connection
,
String
sql
)
throws
SQLException
{
if
(
useGeneratedKeys
)
{
return
connection
.
prepareStatement
(
sql
,
Statement
.
RETURN_GENERATED_KEYS
);
}
return
connection
.
prepareStatement
(
sql
,
new
String
[]{
primary
});
}
public
Object
getObjectKey
()
{
List
<
Map
<
String
,
Object
>>
keyList
=
getKeyList
();
if
(
keyList
.
isEmpty
())
{
return
null
;
}
Iterator
<
Object
>
keyIterator
=
keyList
.
get
(
0
).
values
().
iterator
();
Object
key
=
keyIterator
.
hasNext
()
?
keyIterator
.
next
()
:
null
;
if
(
key
!=
null
&&
"oracle.sql.ROWID"
.
equals
(
key
.
getClass
().
getName
()))
{
return
ScriptManager
.
executeExpression
(
"row.stringValue()"
,
Collections
.
singletonMap
(
"row"
,
key
));
}
return
key
;
}
}
}
magic-api/src/main/java/org/ssssssss/magicapi/modules/db/SingleRowResultSetExtractor.java
0 → 100644
View file @
02897568
package
org.ssssssss.magicapi.modules.db
;
import
org.springframework.dao.DataAccessException
;
import
org.springframework.jdbc.core.ResultSetExtractor
;
import
org.springframework.jdbc.core.RowMapper
;
import
org.springframework.jdbc.support.JdbcUtils
;
import
java.sql.ResultSet
;
import
java.sql.SQLException
;
/**
* 单行结果抽取
*
* @author mxd
*/
public
class
SingleRowResultSetExtractor
<
T
>
implements
ResultSetExtractor
<
T
>
{
private
final
boolean
singleColumn
;
private
final
RowMapper
<
T
>
mapper
;
private
final
Class
<
T
>
requiredType
;
public
SingleRowResultSetExtractor
(
RowMapper
<
T
>
mapper
)
{
this
(
mapper
,
null
,
false
);
}
public
SingleRowResultSetExtractor
(
Class
<
T
>
requiredType
)
{
this
(
null
,
requiredType
,
true
);
}
private
SingleRowResultSetExtractor
(
RowMapper
<
T
>
mapper
,
Class
<
T
>
requiredType
,
boolean
singleColumn
)
{
this
.
mapper
=
mapper
;
this
.
requiredType
=
requiredType
;
this
.
singleColumn
=
singleColumn
;
}
@Override
@SuppressWarnings
(
"unchecked"
)
public
T
extractData
(
ResultSet
rs
)
throws
SQLException
,
DataAccessException
{
if
(
rs
.
next
())
{
if
(
singleColumn
)
{
return
(
T
)
JdbcUtils
.
getResultSetValue
(
rs
,
1
,
requiredType
);
}
return
mapper
.
mapRow
(
rs
,
0
);
}
return
null
;
}
}
magic-api/src/main/java/org/ssssssss/magicapi/modules/db/Transaction.java
0 → 100644
View file @
02897568
package
org.ssssssss.magicapi.modules.db
;
import
org.springframework.jdbc.datasource.DataSourceTransactionManager
;
import
org.springframework.transaction.TransactionDefinition
;
import
org.springframework.transaction.TransactionStatus
;
import
org.springframework.transaction.support.DefaultTransactionDefinition
;
import
org.ssssssss.script.annotation.Comment
;
/**
* 事务模块
*
* @author mxd
*/
public
class
Transaction
{
private
static
final
TransactionDefinition
TRANSACTION_DEFINITION
=
new
DefaultTransactionDefinition
();
private
final
DataSourceTransactionManager
dataSourceTransactionManager
;
private
final
TransactionStatus
transactionStatus
;
public
Transaction
(
DataSourceTransactionManager
dataSourceTransactionManager
)
{
this
.
dataSourceTransactionManager
=
dataSourceTransactionManager
;
this
.
transactionStatus
=
dataSourceTransactionManager
.
getTransaction
(
TRANSACTION_DEFINITION
);
}
/**
* 回滚事务
*/
@Comment
(
"回滚事务"
)
public
void
rollback
()
{
this
.
dataSourceTransactionManager
.
rollback
(
this
.
transactionStatus
);
}
/**
* 提交事务
*/
@Comment
(
"提交事务"
)
public
void
commit
()
{
this
.
dataSourceTransactionManager
.
commit
(
this
.
transactionStatus
);
}
}
magic-api/src/main/java/org/ssssssss/magicapi/modules/db/cache/DefaultSqlCache.java
0 → 100644
View file @
02897568
package
org.ssssssss.magicapi.modules.db.cache
;
/**
* 默认SQL缓存实现
*
* @author mxd
*/
public
class
DefaultSqlCache
implements
SqlCache
{
private
final
LRUCache
cache
;
public
DefaultSqlCache
(
int
capacity
,
long
expire
)
{
this
.
cache
=
new
LRUCache
(
capacity
,
expire
);
}
@Override
public
void
put
(
String
name
,
String
key
,
Object
value
)
{
cache
.
put
(
name
,
key
,
value
);
}
@Override
public
void
put
(
String
name
,
String
key
,
Object
value
,
long
ttl
)
{
cache
.
put
(
name
,
key
,
value
,
ttl
);
}
@Override
public
Object
get
(
String
name
,
String
key
)
{
return
cache
.
get
(
name
,
key
);
}
@Override
public
void
delete
(
String
name
)
{
cache
.
delete
(
name
);
}
}
magic-api/src/main/java/org/ssssssss/magicapi/modules/db/cache/LRUCache.java
0 → 100644
View file @
02897568
package
org.ssssssss.magicapi.modules.db.cache
;
import
java.util.Iterator
;
import
java.util.LinkedHashMap
;
import
java.util.Map
;
import
java.util.concurrent.locks.ReentrantReadWriteLock
;
/**
* LRU缓存实现
*
* @author mxd
*/
public
class
LRUCache
extends
LinkedHashMap
<
String
,
LRUCache
.
ExpireNode
<
Object
>>
{
private
final
String
separator
=
":"
;
private
final
int
capacity
;
private
final
long
expire
;
private
final
ReentrantReadWriteLock
lock
=
new
ReentrantReadWriteLock
();
public
LRUCache
(
int
capacity
,
long
expire
)
{
super
((
int
)
Math
.
ceil
(
capacity
/
0.75
)
+
1
,
0.75f
,
true
);
// 容量
this
.
capacity
=
capacity
;
// 固定过期时间
this
.
expire
=
expire
;
}
public
void
put
(
String
name
,
String
key
,
Object
value
)
{
// 封装成过期时间节点
put
(
name
,
key
,
value
,
this
.
expire
);
}
public
void
put
(
String
name
,
String
key
,
Object
value
,
long
ttl
)
{
long
expireTime
=
ttl
>
0
?
(
System
.
currentTimeMillis
()
+
ttl
)
:
(
this
.
expire
>
-
1
?
System
.
currentTimeMillis
()
+
this
.
expire
:
Long
.
MAX_VALUE
);
lock
.
writeLock
().
lock
();
try
{
// 封装成过期时间节点
put
(
name
+
separator
+
key
,
new
ExpireNode
<>(
expireTime
,
value
));
}
finally
{
lock
.
writeLock
().
unlock
();
}
}
public
Object
get
(
String
name
,
String
key
)
{
key
=
name
+
separator
+
key
;
lock
.
readLock
().
lock
();
ExpireNode
<
Object
>
expireNode
;
try
{
expireNode
=
super
.
get
(
key
);
}
finally
{
lock
.
readLock
().
unlock
();
}
if
(
expireNode
==
null
)
{
return
null
;
}
// 惰性删除过期的
// if (this.expire > -1L && expireNode.expire < System.currentTimeMillis()) {
if
(
expireNode
.
expire
<
System
.
currentTimeMillis
())
{
try
{
lock
.
writeLock
().
lock
();
super
.
remove
(
key
);
}
finally
{
lock
.
writeLock
().
unlock
();
}
return
null
;
}
return
expireNode
.
value
;
}
public
void
delete
(
String
name
)
{
try
{
lock
.
writeLock
().
lock
();
Iterator
<
Map
.
Entry
<
String
,
ExpireNode
<
Object
>>>
iterator
=
super
.
entrySet
().
iterator
();
String
prefix
=
name
+
separator
;
// 清除所有key前缀为name + separator的缓存
while
(
iterator
.
hasNext
())
{
Map
.
Entry
<
String
,
ExpireNode
<
Object
>>
entry
=
iterator
.
next
();
if
(
entry
.
getKey
().
startsWith
(
prefix
))
{
iterator
.
remove
();
}
}
}
finally
{
lock
.
writeLock
().
unlock
();
}
}
@Override
protected
boolean
removeEldestEntry
(
Map
.
Entry
<
String
,
ExpireNode
<
Object
>>
eldest
)
{
if
(
this
.
expire
>
-
1L
&&
size
()
>
capacity
)
{
clean
();
}
// lru淘汰
return
size
()
>
this
.
capacity
;
}
/**
* 清理已过期的数据
*/
private
void
clean
()
{
try
{
lock
.
writeLock
().
lock
();
Iterator
<
Map
.
Entry
<
String
,
ExpireNode
<
Object
>>>
iterator
=
super
.
entrySet
().
iterator
();
long
now
=
System
.
currentTimeMillis
();
while
(
iterator
.
hasNext
())
{
Map
.
Entry
<
String
,
ExpireNode
<
Object
>>
next
=
iterator
.
next
();
// 判断是否过期
if
(
next
.
getValue
().
expire
<
now
)
{
iterator
.
remove
();
}
}
}
finally
{
lock
.
writeLock
().
unlock
();
}
}
/**
* 过期时间节点
*/
static
class
ExpireNode
<
V
>
{
long
expire
;
V
value
;
ExpireNode
(
long
expire
,
V
value
)
{
this
.
expire
=
expire
;
this
.
value
=
value
;
}
}
}
magic-api/src/main/java/org/ssssssss/magicapi/modules/db/cache/SqlCache.java
0 → 100644
View file @
02897568
package
org.ssssssss.magicapi.modules.db.cache
;
import
org.ssssssss.magicapi.utils.MD5Utils
;
import
java.util.Arrays
;
/**
* SQL缓存接口
*
* @author mxd
*/
public
interface
SqlCache
{
/**
* 计算key
*/
default
String
buildSqlCacheKey
(
String
sql
,
Object
[]
params
)
{
return
MD5Utils
.
encrypt
(
sql
+
":"
+
Arrays
.
toString
(
params
));
}
/**
* 存入缓存
*
* @param name 名字
* @param key key
* @param value 值
*/
void
put
(
String
name
,
String
key
,
Object
value
);
/**
* 存入缓存
*
* @param name 名字
* @param key key
* @param value 值
* @param ttl 有效期
*/
void
put
(
String
name
,
String
key
,
Object
value
,
long
ttl
);
/**
* 获取缓存
*
* @param name 名字
* @param key key
*/
<
T
>
T
get
(
String
name
,
String
key
);
/**
* 删除缓存
*
* @param name 名字
*/
void
delete
(
String
name
);
}
magic-api/src/main/java/org/ssssssss/magicapi/modules/db/dialect/ClickhouseDialect.java
0 → 100644
View file @
02897568
package
org.ssssssss.magicapi.modules.db.dialect
;
/**
* ClickHouse方言
*
* @author mxd
*/
public
class
ClickhouseDialect
extends
MySQLDialect
{
@Override
public
boolean
match
(
String
jdbcUrl
)
{
return
jdbcUrl
.
contains
(
":clickhouse:"
);
}
}
magic-api/src/main/java/org/ssssssss/magicapi/modules/db/dialect/DB2Dialect.java
0 → 100644
View file @
02897568
package
org.ssssssss.magicapi.modules.db.dialect
;
import
org.ssssssss.magicapi.modules.db.BoundSql
;
/**
* DB2方言
*
* @author mxd
*/
public
class
DB2Dialect
implements
Dialect
{
@Override
public
boolean
match
(
String
jdbcUrl
)
{
return
jdbcUrl
.
contains
(
":db2:"
);
}
@Override
public
String
getPageSql
(
String
sql
,
BoundSql
boundSql
,
long
offset
,
long
limit
)
{
boundSql
.
addParameter
(
offset
+
1
);
boundSql
.
addParameter
(
offset
+
limit
);
return
"SELECT * FROM (SELECT TMP_PAGE.*,ROWNUMBER() OVER() AS ROW_ID FROM ( \n"
+
sql
+
"\n ) AS TMP_PAGE) TMP_PAGE WHERE ROW_ID BETWEEN ? AND ?"
;
}
}
magic-api/src/main/java/org/ssssssss/magicapi/modules/db/dialect/Dialect.java
0 → 100644
View file @
02897568
package
org.ssssssss.magicapi.modules.db.dialect
;
import
org.ssssssss.magicapi.modules.db.BoundSql
;
import
java.sql.Connection
;
import
java.sql.SQLException
;
import
java.util.regex.Pattern
;
/**
* 数据库方言接口
*
* @author mxd
*/
public
interface
Dialect
{
Pattern
REPLACE_ORDER_BY
=
Pattern
.
compile
(
"order\\s+by\\s+[^,\\s]+(\\s+asc|\\s+desc)?(\\s*,\\s*[^,\\s]+(\\s+asc|\\s+desc)?)*"
,
Pattern
.
CASE_INSENSITIVE
|
Pattern
.
MULTILINE
);
/**
* 根据jdbcUrl匹配
*
* @param jdbcUrl jdbc链接
* @return 是否匹配
*/
default
boolean
match
(
String
jdbcUrl
)
{
return
false
;
}
/**
* 根据Connection匹配
*
* @param connection jdbc连接
* @return 是否匹配
* @throws SQLException 匹配失败时抛出的异常
*/
default
boolean
match
(
Connection
connection
)
throws
SQLException
{
return
match
(
connection
.
getMetaData
().
getURL
());
}
/**
* 获取查总数的sql
*
* @param sql 原始SQL
* @return 分页 count SQL
*/
default
String
getCountSql
(
String
sql
)
{
return
"select count(1) from ( \n"
+
REPLACE_ORDER_BY
.
matcher
(
sql
).
replaceAll
(
""
)
+
"\n ) count_"
;
}
/**
* 获取分页sql
*
* @param sql 原始SQL
* @param boundSql boundSql对象
* @param offset 跳过条数
* @param limit 限制条数
* @return 返回分页SQL
*/
String
getPageSql
(
String
sql
,
BoundSql
boundSql
,
long
offset
,
long
limit
);
}
magic-api/src/main/java/org/ssssssss/magicapi/modules/db/dialect/DialectAdapter.java
0 → 100644
View file @
02897568
package
org.ssssssss.magicapi.modules.db.dialect
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
java.sql.Connection
;
import
java.sql.SQLException
;
import
java.util.ArrayList
;
import
java.util.List
;
/**
* 方言适配器
*
* @author mxd
*/
public
class
DialectAdapter
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
DialectAdapter
.
class
);
private
final
List
<
Dialect
>
dialectList
=
new
ArrayList
<>();
public
DialectAdapter
()
{
add
(
new
MySQLDialect
());
add
(
new
OracleDialect
());
add
(
new
PostgreSQLDialect
());
add
(
new
ClickhouseDialect
());
add
(
new
DB2Dialect
());
add
(
new
SQLServerDialect
());
add
(
new
SQLServer2005Dialect
());
add
(
new
DmDialect
());
add
(
new
KingbaseSQLDialect
());
}
public
void
add
(
Dialect
dialect
)
{
this
.
dialectList
.
add
(
0
,
dialect
);
}
public
Dialect
getDialectFromConnection
(
Connection
connection
)
{
for
(
Dialect
dialect
:
dialectList
)
{
try
{
if
(
dialect
.
match
(
connection
))
{
return
dialect
;
}
}
catch
(
SQLException
e
)
{
logger
.
debug
(
"方言{}匹配失败"
,
dialect
,
e
);
}
}
logger
.
warn
(
"magic-api在{}中无法获取dialect"
,
connection
);
return
null
;
}
}
magic-api/src/main/java/org/ssssssss/magicapi/modules/db/dialect/DmDialect.java
0 → 100644
View file @
02897568
package
org.ssssssss.magicapi.modules.db.dialect
;
import
org.ssssssss.magicapi.modules.db.BoundSql
;
/**
* @description: 达梦数据库方言
* @author: qijiantuoluowang
* @create: 2020-12-09 19:33
**/
public
class
DmDialect
implements
Dialect
{
@Override
public
boolean
match
(
String
jdbcUrl
)
{
return
jdbcUrl
.
contains
(
":dm:"
);
}
@Override
public
String
getPageSql
(
String
sql
,
BoundSql
boundSql
,
long
offset
,
long
limit
)
{
limit
=
(
offset
>=
1
)
?
(
offset
+
limit
)
:
limit
;
boundSql
.
addParameter
(
limit
);
boundSql
.
addParameter
(
offset
);
return
"SELECT * FROM ( SELECT TMP.*, ROWNUM ROW_ID FROM ( \n"
+
sql
+
"\n ) TMP WHERE ROWNUM <= ? ) WHERE ROW_ID > ?"
;
}
}
magic-api/src/main/java/org/ssssssss/magicapi/modules/db/dialect/KingbaseSQLDialect.java
0 → 100644
View file @
02897568
package
org.ssssssss.magicapi.modules.db.dialect
;
import
org.ssssssss.magicapi.modules.db.BoundSql
;
/**
* 人大金仓kingbase方言
*
* @author is_lixy@163.com
*/
public
class
KingbaseSQLDialect
implements
Dialect
{
@Override
public
boolean
match
(
String
jdbcUrl
)
{
return
jdbcUrl
.
contains
(
":kingbase8:"
);
}
@Override
public
String
getPageSql
(
String
sql
,
BoundSql
boundSql
,
long
offset
,
long
limit
)
{
boundSql
.
addParameter
(
limit
);
boundSql
.
addParameter
(
offset
);
return
sql
+
"\n limit ? offset ?"
;
}
}
magic-api/src/main/java/org/ssssssss/magicapi/modules/db/dialect/MySQLDialect.java
0 → 100644
View file @
02897568
package
org.ssssssss.magicapi.modules.db.dialect
;
import
org.ssssssss.magicapi.modules.db.BoundSql
;
/**
* mysql 方言
*
* @author mxd
*/
public
class
MySQLDialect
implements
Dialect
{
@Override
public
boolean
match
(
String
jdbcUrl
)
{
return
jdbcUrl
.
contains
(
":mysql:"
)
||
jdbcUrl
.
contains
(
":mariadb:"
)
||
jdbcUrl
.
contains
(
":cobar:"
);
}
@Override
public
String
getPageSql
(
String
sql
,
BoundSql
boundSql
,
long
offset
,
long
limit
)
{
boundSql
.
addParameter
(
offset
);
boundSql
.
addParameter
(
limit
);
return
sql
+
"\n limit ?,?"
;
}
}
magic-api/src/main/java/org/ssssssss/magicapi/modules/db/dialect/OracleDialect.java
0 → 100644
View file @
02897568
package
org.ssssssss.magicapi.modules.db.dialect
;
import
org.ssssssss.magicapi.modules.db.BoundSql
;
/**
* Oracle方言
*
* @author mxd
*/
public
class
OracleDialect
implements
Dialect
{
@Override
public
boolean
match
(
String
jdbcUrl
)
{
return
jdbcUrl
.
contains
(
":oracle:"
);
}
@Override
public
String
getPageSql
(
String
sql
,
BoundSql
boundSql
,
long
offset
,
long
limit
)
{
limit
=
(
offset
>=
1
)
?
(
offset
+
limit
)
:
limit
;
boundSql
.
addParameter
(
limit
);
boundSql
.
addParameter
(
offset
);
return
"SELECT * FROM ( SELECT TMP.*, ROWNUM ROW_ID FROM ( \n"
+
sql
+
"\n ) TMP WHERE ROWNUM <= ? ) WHERE ROW_ID > ?"
;
}
}
magic-api/src/main/java/org/ssssssss/magicapi/modules/db/dialect/PostgreSQLDialect.java
0 → 100644
View file @
02897568
package
org.ssssssss.magicapi.modules.db.dialect
;
import
org.ssssssss.magicapi.modules.db.BoundSql
;
/**
* PostgreSQL 方言
*
* @author mxd
*/
public
class
PostgreSQLDialect
implements
Dialect
{
@Override
public
boolean
match
(
String
jdbcUrl
)
{
return
jdbcUrl
.
contains
(
":postgresql:"
)
||
jdbcUrl
.
contains
(
":greenplum:"
);
}
@Override
public
String
getPageSql
(
String
sql
,
BoundSql
boundSql
,
long
offset
,
long
limit
)
{
boundSql
.
addParameter
(
limit
);
boundSql
.
addParameter
(
offset
);
return
sql
+
"\n limit ? offset ?"
;
}
}
magic-api/src/main/java/org/ssssssss/magicapi/modules/db/dialect/SQLServer2005Dialect.java
0 → 100644
View file @
02897568
package
org.ssssssss.magicapi.modules.db.dialect
;
import
org.apache.commons.lang3.StringUtils
;
import
org.ssssssss.magicapi.modules.db.BoundSql
;
/**
* SQLServer2005 方言
*
* @author mxd
*/
public
class
SQLServer2005Dialect
implements
Dialect
{
@Override
public
boolean
match
(
String
jdbcUrl
)
{
return
jdbcUrl
.
contains
(
":sqlserver:"
);
}
@Override
public
String
getPageSql
(
String
sql
,
BoundSql
boundSql
,
long
offset
,
long
limit
)
{
StringBuilder
pagingBuilder
=
new
StringBuilder
();
String
orderby
=
getOrderByPart
(
sql
);
String
distinctStr
=
""
;
String
loweredString
=
sql
.
toLowerCase
();
String
sqlPartString
=
sql
;
if
(
loweredString
.
trim
().
startsWith
(
"select"
))
{
int
index
=
6
;
if
(
loweredString
.
startsWith
(
"select distinct"
))
{
distinctStr
=
"DISTINCT "
;
index
=
15
;
}
sqlPartString
=
sqlPartString
.
substring
(
index
);
}
pagingBuilder
.
append
(
sqlPartString
);
// if no ORDER BY is specified use fake ORDER BY field to avoid errors
if
(
StringUtils
.
isEmpty
(
orderby
))
{
orderby
=
"ORDER BY CURRENT_TIMESTAMP"
;
}
StringBuilder
result
=
new
StringBuilder
();
result
.
append
(
"WITH query AS (SELECT "
)
.
append
(
distinctStr
)
.
append
(
"TOP 100 PERCENT "
)
.
append
(
" ROW_NUMBER() OVER ("
)
.
append
(
orderby
)
.
append
(
") as __row_number__, "
)
.
append
(
pagingBuilder
)
.
append
(
") SELECT * FROM query WHERE __row_number__ BETWEEN ? AND ?"
)
.
append
(
" ORDER BY __row_number__"
);
boundSql
.
addParameter
(
offset
+
1
);
boundSql
.
addParameter
(
offset
+
limit
);
return
result
.
toString
();
}
private
String
getOrderByPart
(
String
sql
)
{
String
loweredString
=
sql
.
toLowerCase
();
int
orderByIndex
=
loweredString
.
indexOf
(
"order by"
);
if
(
orderByIndex
!=
-
1
)
{
// if we find a new "order by" then we need to ignore
// the previous one since it was probably used for a subquery
return
sql
.
substring
(
orderByIndex
);
}
else
{
return
""
;
}
}
}
magic-api/src/main/java/org/ssssssss/magicapi/modules/db/dialect/SQLServerDialect.java
0 → 100644
View file @
02897568
package
org.ssssssss.magicapi.modules.db.dialect
;
import
org.ssssssss.magicapi.modules.db.BoundSql
;
/**
* SQL Server 方言
*
* @author mxd
*/
public
class
SQLServerDialect
implements
Dialect
{
@Override
public
boolean
match
(
String
jdbcUrl
)
{
return
jdbcUrl
.
contains
(
":sqlserver2012:"
);
}
@Override
public
String
getPageSql
(
String
sql
,
BoundSql
boundSql
,
long
offset
,
long
limit
)
{
boundSql
.
addParameter
(
offset
);
boundSql
.
addParameter
(
limit
);
return
sql
+
"\n OFFSET ? ROWS FETCH NEXT ? ROWS ONLY"
;
}
}
magic-api/src/main/java/org/ssssssss/magicapi/modules/db/inteceptor/DefaultSqlInterceptor.java
0 → 100644
View file @
02897568
package
org.ssssssss.magicapi.modules.db.inteceptor
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.ssssssss.magicapi.core.context.RequestEntity
;
import
org.ssssssss.magicapi.modules.db.BoundSql
;
import
org.ssssssss.magicapi.modules.db.inteceptor.SQLInterceptor
;
import
java.util.Arrays
;
import
java.util.stream.Collectors
;
/**
* 默认打印SQL实现
*
* @author mxd
*/
public
class
DefaultSqlInterceptor
implements
SQLInterceptor
{
private
void
handleLog
(
BoundSql
boundSql
,
RequestEntity
requestEntity
){
Logger
logger
=
LoggerFactory
.
getLogger
(
requestEntity
==
null
?
"Unknown"
:
requestEntity
.
getMagicScriptContext
().
getScriptName
());
String
parameters
=
Arrays
.
stream
(
boundSql
.
getParameters
()).
map
(
it
->
{
if
(
it
==
null
)
{
return
"null"
;
}
return
it
+
"("
+
it
.
getClass
().
getSimpleName
()
+
")"
;
}).
collect
(
Collectors
.
joining
(
", "
));
String
dataSourceName
=
boundSql
.
getSqlModule
().
getDataSourceName
();
logger
.
info
(
"执行SQL:{}"
,
boundSql
.
getSql
().
trim
());
if
(
dataSourceName
!=
null
)
{
logger
.
info
(
"数据源:{}"
,
dataSourceName
);
}
if
(
parameters
.
length
()
>
0
)
{
logger
.
info
(
"SQL参数:{}"
,
parameters
);
}
}
@Override
public
Object
postHandle
(
BoundSql
boundSql
,
Object
result
,
RequestEntity
requestEntity
)
{
handleLog
(
boundSql
,
requestEntity
);
return
result
;
}
@Override
public
void
handleException
(
BoundSql
boundSql
,
Throwable
throwable
,
RequestEntity
requestEntity
)
{
handleLog
(
boundSql
,
requestEntity
);
}
}
Prev
1
…
9
10
11
12
13
14
15
16
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment