Flowable 6.6.0 BPMN使用者指南 - 17 高階用例 - 17.5 執行自定義SQL(Execute custom SQL)
《Flowable 6.6.0 BPMN使用者指南》
1. 入門
2. 配置
3 The Flowable API
4 Flowable 6.6.0 BPMN使用者指南 - (4)Spring整合
5 Spring Boot
6 部署
7 BPMN 2.0簡介
8 BPMN 2.0的構造
9 表單(Forms)
10 流程例項遷移
11 JPA
12 歷史(History)
13 身份管理(Identity management)
14 REST API
15 CDI整合
16 LDAP整合
17 高階用例
- 17.1 非同步執行器(Async Executor)
- 17.2 與流程解析掛鉤(Hooking into process parsing)
- 17.3 用於高併發的UUID ID生成器
- 17.4 多租戶(Multitenancy)
- 17.5 執行自定義SQL(Execute custom SQL)
- 17.6 採用ProcessEngineConfigurator 進行高階的流程引擎配置
- 17.7 高階查詢API:執行時和歷史任務查詢之間的無縫切換
- 17.8 重寫標準SessionFactory實現自定義身份管理
- 17.9 啟用安全的BPMN 2.0 xml
- 17.10 事件日誌記錄(Event logging)
- 17.11 禁用批量插入(Disabling bulk inserts)
- 17.12 安全指令碼(Secure Scripting)
- 17.13 日誌記錄會話[實驗性]
有關Flowable的更多文件,參見:
17.5 執行自定義SQL(Execute custom SQL)
The Flowable API allows for interacting with the database using a high level API. For example, for retrieving data the Query API and the Native Query API are powerful in its usage. However, for some use cases they might not be flexible enough. The following section describes how a completely custom SQL statement (select, insert, update and delete are possible) can be executed against the Flowable data store, but completely within the configured Process Engine (and thus levering the transaction setup for example).
To define custom SQL statements, the Flowable engine leverages the capabilities of its underlying framework, MyBatis. More info can be read in the MyBatis user guide.
Flowable API允許使用高階API(high level API)與資料庫互動。例如,對於檢索資料,Query API和Native Query API的用法非常強大。然而,對於某些用例,它們可能不夠靈活。以下部分描述如何針對可流動資料儲存執行完全自定義的SQL語句(可以查詢、插入、更新和刪除),但完全在配置的流程引擎中執行(例如,還可以利用事務設定)。
為了定義定製的SQL語句,Flowable引擎利用其底層框架MyBatis的功能。更多資訊可在MyBatis使用者指南(in the MyBatis user guide)中閱讀。
17.5.1 基於註解的對映語句(Annotation based Mapped Statements)
The first thing to do when using Annotation based Mapped Statements, is to create a MyBatis mapper class. For example, suppose that for some use case not the whole task data is needed, but only a small subset of it. A Mapper that could do this, looks as follows:
使用基於註解的對映語句(Annotation based Mapped Statements)時,首先要做的是建立一個MyBatis對映器類。例如,假設對於某些用例,不需要整個任務資料,而只需要其中的一小部分。以下Mapper可以做到:
public interface MyTestMapper {
@Select("SELECT ID_ as id, NAME_ as name, CREATE_TIME_ as createTime FROM ACT_RU_TASK")
List<Map<String, Object>> selectTasks();
}
This mapper must be provided to the Process Engine configuration as follows:
此對映器必須提供給流程引擎配置,如下所示:
...
<property name="customMybatisMappers">
<set>
<value>org.flowable.standalone.cfg.MyTestMapper</value>
</set>
</property>
...
Notice that this is an interface. The underlying MyBatis framework will make an instance of it that can be used at runtime. Also notice that the return value of the method is not typed, but a list of maps (which corresponds to the list of rows with column values). Typing is possible with the MyBatis mappers if wanted.
To execute the query above, the managementService.executeCustomSql method must be used. This method takes in a CustomSqlExecution instance. This is a wrapper that hides the internal bits of the engine otherwise needed to make it work.
Unfortunately, Java generics make it a bit less readable than it could have been. The two generic types below are the mapper class and the return type class. However, the actual logic is simply to call the mapper method and return its results (if applicable).
注意這是一個介面。底層MyBatis框架將生成一個可以在執行時使用的例項。還要注意,該方法的返回值不是型別化的,而是一個對映列表(對應於具有列值的行的列表)。如果需要的話,可以MyBatis對映器可以型別化(Typing)。
若要執行上述查詢,則必須使用managementService.executeCustomSql 方法。此方法接受一個CustomSqlExecution 例項。這是一個包裝器,它隱藏了使之工作的引擎的內部部分資訊。
不幸的是,Java泛型使得它的可讀性比原來的要低一些。下面的兩個泛型型別是對映器類(mapper class)和返回型別類(return type class)。然而,實際的邏輯只是呼叫對映器方法並返回其結果(如果適用)。
CustomSqlExecution<MyTestMapper, List<Map<String, Object>>> customSqlExecution =
new AbstractCustomSqlExecution<MyTestMapper, List<Map<String, Object>>>(MyTestMapper.class) {
public List<Map<String, Object>> execute(MyTestMapper customMapper) {
return customMapper.selectTasks();
}
};
List<Map<String, Object>> results = managementService.executeCustomSql(customSqlExecution);
The Map entries in the list above will only contain id, name and create time in this case and not the full task object.
Any SQL is possible when using the approach above. Another more complex example:
在本例中,上面列表中的Map條目只包含id、name和create time,而沒有包含完整的task物件。
使用上述方法時,可以使用任何SQL。另一個更復雜的例子:
@Select({
"SELECT task.ID_ as taskId, variable.LONG_ as variableValue FROM ACT_RU_VARIABLE variable",
"inner join ACT_RU_TASK task on variable.TASK_ID_ = task.ID_",
"where variable.NAME_ = #{variableName}"
})
List<Map<String, Object>> selectTaskWithSpecificVariable(String variableName);
Using this method, the task table will be joined with the variables table. Only where the variable has a certain name is retained, and the task id and the corresponding numerical value is returned.
For a working example on using Annotation based Mapped Statements check the unit test org.flowable.standalone.cfg.CustomMybatisMapperTest and other classes and resources in folders src/test/java/org/flowable/standalone/cfg/ and src/test/resources/org/flowable/standalone/cfg/
使用此方法,任務表將與變數表聯接。只有在變數具有特定名稱的情況下才會保留,並返回任務id和相應的數值。
有關使用基於註解的對映語句的工作示例,請檢查單元測試org.flowable.standalone.cfg.CustomMybatisMapperTest以及src/test/java/org/flowable/standalone/cfg/和src/test/resources/org/flowable/standalone/cfg/資料夾中的其他類和資源
17.5.2 基於XML的對映語句(XML based Mapped Statements)
When using XML based Mapped Statements, statements are defined in XML files. For the use case where not the whole task data is needed, but only a small subset of it. The XML file can look as follows:
使用基於XML的對映語句時,語句是在XML檔案中定義的。對於不需要整個任務資料的用例,只需要其中一小部分資料。XML檔案可以如下所示:
<mapper namespace="org.flowable.standalone.cfg.TaskMapper">
<resultMap id="customTaskResultMap" type="org.flowable.standalone.cfg.CustomTask">
<id property="id" column="ID_" jdbcType="VARCHAR"/>
<result property="name" column="NAME_" jdbcType="VARCHAR"/>
<result property="createTime" column="CREATE_TIME_" jdbcType="TIMESTAMP" />
</resultMap>
<select id="selectCustomTaskList" resultMap="customTaskResultMap">
select RES.ID_, RES.NAME_, RES.CREATE_TIME_ from ACT_RU_TASK RES
</select>
</mapper>
Results are mapped to instances of org.flowable.standalone.cfg.CustomTask class which can look as follows:
結果對映到org.flowable.standalone.cfg.CustomTask類,如下所示:
public class CustomTask {
protected String id;
protected String name;
protected Date createTime;
public String getId() {
return id;
}
public String getName() {
return name;
}
public Date getCreateTime() {
return createTime;
}
}
Mapper XML files must be provided to the Process Engine configuration as follows:
對映器XML檔案必須提供給流程引擎配置,如下所示:
...
<property name="customMybatisXMLMappers">
<set>
<value>org/flowable/standalone/cfg/custom-mappers/CustomTaskMapper.xml</value>
</set>
</property>
...
The statement can be executed as follows:
語句的執行方式如下:
List<CustomTask> tasks = managementService.executeCommand(new Command<List<CustomTask>>() {
@SuppressWarnings("unchecked")
@Override
public List<CustomTask> execute(CommandContext commandContext) {
return (List<CustomTask>) commandContext.getDbSqlSession().selectList("selectCustomTaskList");
}
});
For uses cases that require more complicated statements, XML Mapped Statements can be helpful. Since Flowable uses XML Mapped Statements internally, it’s possible to make use of the underlying capabilities.
Suppose that for some use case the ability to query attachments data is required based on id, name, type, userId, etc! To fulfill the use case a query class AttachmentQuery that extends org.flowable.engine.impl.AbstractQuery can be created as follows:
對於需要更復雜語句的用例,XML對映語句可能很有用。由於Flowable在內部使用XML對映語句,所以可以使用底層功能。
假設對於某些用例,需要根據id、name、type、userId等查詢附件資料!為了實現這個用例,查詢類AttachmentQuery 擴充套件org.flowable.engine.impl.AbstractQuery,可以按如下方式建立:
public class AttachmentQuery extends AbstractQuery<AttachmentQuery, Attachment> {
protected String attachmentId;
protected String attachmentName;
protected String attachmentType;
protected String userId;
public AttachmentQuery(ManagementService managementService) {
super(managementService);
}
public AttachmentQuery attachmentId(String attachmentId){
this.attachmentId = attachmentId;
return this;
}
public AttachmentQuery attachmentName(String attachmentName){
this.attachmentName = attachmentName;
return this;
}
public AttachmentQuery attachmentType(String attachmentType){
this.attachmentType = attachmentType;
return this;
}
public AttachmentQuery userId(String userId){
this.userId = userId;
return this;
}
@Override
public long executeCount(CommandContext commandContext) {
return (Long) commandContext.getDbSqlSession()
.selectOne("selectAttachmentCountByQueryCriteria", this);
}
@Override
public List<Attachment> executeList(CommandContext commandContext, Page page) {
return commandContext.getDbSqlSession()
.selectList("selectAttachmentByQueryCriteria", this);
}
Note that when extending AbstractQuery extended classes should pass an instance of ManagementService to super constructor and methods executeCount and executeList need to be implemented to call the mapped statements.
The XML file containing the mapped statements can look as follows:
請注意,在擴充套件AbstractQuery 時,擴充套件類應該將ManagementService 的例項傳遞給超級建構函式(super constructor),並且需要實現executeCount 和executeList 方法來呼叫對映的語句。
包含對映語句的XML檔案可以如下所示:
<mapper namespace="org.flowable.standalone.cfg.AttachmentMapper">
<select id="selectAttachmentCountByQueryCriteria" parameterType="org.flowable.standalone.cfg.AttachmentQuery" resultType="long">
select count(distinct RES.ID_)
<include refid="selectAttachmentByQueryCriteriaSql"/>
</select>
<select id="selectAttachmentByQueryCriteria" parameterType="org.flowable.standalone.cfg.AttachmentQuery" resultMap="org.flowable.engine.impl.persistence.entity.AttachmentEntity.attachmentResultMap">
${limitBefore}
select distinct RES.* ${limitBetween}
<include refid="selectAttachmentByQueryCriteriaSql"/>
${orderBy}
${limitAfter}
</select>
<sql id="selectAttachmentByQueryCriteriaSql">
from ${prefix}ACT_HI_ATTACHMENT RES
<where>
<if test="attachmentId != null">
RES.ID_ = #{attachmentId}
</if>
<if test="attachmentName != null">
and RES.NAME_ = #{attachmentName}
</if>
<if test="attachmentType != null">
and RES.TYPE_ = #{attachmentType}
</if>
<if test="userId != null">
and RES.USER_ID_ = #{userId}
</if>
</where>
</sql>
</mapper>
Capabilities such as pagination, ordering, table name prefixing are available and can be used in the statements (since the parameterType is a subclass of AbstractQuery). Note that to map results the predefined org.flowable.engine.impl.persistence.entity.AttachmentEntity.attachmentResultMap resultMap can be used.
Finally, the AttachmentQuery can be used as follows:
分頁、排序、表名字首等功能都是可用的,可以在語句中使用(因為parameterType是AbstractQuery的一個子類)。請注意,要對映結果,可以使用預定義的org.flowable.engine.impl.persistence.entity.AttachmentEntity.attachmentResultMap resultMap。
最後,AttachmentQuery 的用法如下:
....
// Get the total number of attachments
long count = new AttachmentQuery(managementService).count();
// Get attachment with id 10025
Attachment attachment = new AttachmentQuery(managementService).attachmentId("10025").singleResult();
// Get first 10 attachments
List<Attachment> attachments = new AttachmentQuery(managementService).listPage(0, 10);
// Get all attachments uploaded by user kermit
attachments = new AttachmentQuery(managementService).userId("kermit").list();
....
For working examples on using XML Mapped Statements check the unit test org.flowable.standalone.cfg.CustomMybatisXMLMapperTest and other classes and resources in folders src/test/java/org/flowable/standalone/cfg/ and src/test/resources/org/flowable/standalone/cfg/
使用XML對映語句的示例可檢查位於src/test/java/org/flowable/standalone/cfg/和src/test/resources/org/flowable/standalone/cfg/資料夾中的單元測試org.flowable.standalone.cfg.CustomMybatisXMLMapperTest 以及其他類和資源。
相關文章
- Flowable 6.6.0 BPMN使用者指南 - 17 高階用例 - 17.7 高階查詢API:執行時和歷史任務查詢之間的無縫切換API
- Flowable 6.6.0 BPMN使用者指南 -9 表單 - 9.1 表單定義
- Flowable 6.6.0 BPMN使用者指南-(2)配置 - 2.9 作業執行器/2.10 作業執行器啟用
- Flowable 6.6.0 BPMN使用者指南 - (5)Spring Boot - 5.9 Flowable Auto-configuration類 5.10 Flowable StartersSpring Boot
- Flowable 6.6.0 BPMN使用者指南-(2)配置 - 2.18.4 向流程定義增加偵聽器
- Flowable 6.6.0 BPMN使用者指南-(1)入門 - 1.4.1 設定REST應用程式REST
- Flowable 6.6.0BPMN使用者指南(第二部分)BPMN 2.0的構造
- Flowable 6.6.0 BPMN使用者指南 - (5)Spring Boot - 5.11 使用Liquibase 5.12 進一步閱讀Spring BootUI
- Custom Post Types [2.1.14] - WordPress高階自定義外掛
- 疑問:mybatis如何自定義SQL執行時長MyBatisSQL
- 用mysqlslap壓測自定義sqlMySql
- 17.Sql是如何執行的SQL
- .Net 7 高階玩法,自定義一個CLR執行時
- PostgreSQL:高階 SQLSQL
- 自定義xunit測試用例的執行順序
- 自定義註解例項實現SQL語句生成SQL
- SQL高階查詢SQL
- SQL 高階語法 MERGE INTOSQL
- MyBatis SQL執行MyBatisSQL
- PHP執行sqlPHPSQL
- [ORACLE] SQL執行OracleSQL
- Oracle - 執行過的SQL、正在執行的SQL、消耗資源最多的SQLOracleSQL
- Spark SQL使用簡介(2)--UDF(使用者自定義函式)SparkSQL函式
- 實現MyBatisPlus自定義sql注入器MyBatisSQL
- sql-server高階查詢SQLServer
- 用 Explain 命令分析 MySQL 的 SQL 執行AIMySql
- 【SQL】17 SQL 檢視(Views)、SQL Date 函式、SQL NULL 值、SQLView函式Null
- peewee 執行原生 sqlSQL
- Sql執行順序SQL
- Flowable 6.6.0表單配置 - FormEngineConfiguration beanORMBean
- oracle學習筆記(十七) PL/SQL高階應用Oracle筆記SQL
- oracle查詢sql執行耗時、執行時間、sql_idOracleSQL
- sql中select列有自定義函式 dblinkSQL函式
- 單據列表呼叫自定義SQL函式SQL函式
- 小書MybatisPlus第3篇-自定義SQLMyBatisSQL
- Mybatis-plus核心功能-自定義SQLMyBatisSQL
- 用PostgreSQL執行檔案中的SQL程式SQL
- SQL 執行 - 執行器最佳化SQL