Skip to content

deleteDeployment

Flowable 7.1.0 摘要:删除指定的流程定义部署及其相关资源。

方法签名与说明

void deleteDeployment(String deploymentId)

删除指定的部署。如果该部署下的流程定义有正在运行的流程实例,删除操作会失败。

Parameters:

  • deploymentId - 部署ID,不能为null

Throws:

  • FlowableObjectNotFoundException - 当部署不存在时
  • FlowableException - 当存在运行中的流程实例时

void deleteDeployment(String deploymentId, boolean cascade)

删除指定的部署。如果cascade为true,会级联删除所有相关的流程实例(包括运行中的)和历史数据。

Parameters:

  • deploymentId - 部署ID,不能为null
  • cascade - 是否级联删除相关数据

常见使用场景

1. 清理测试数据

在测试环境中,删除测试用的流程定义部署。

2. 流程下线

某个业务流程不再使用,需要将其从系统中移除。

3. 错误部署修正

部署了错误的流程定义,需要删除后重新部署。

Kotlin + Spring Boot 调用示例

示例1:安全删除部署(不级联)

kotlin
import org.flowable.engine.RepositoryService
import org.flowable.engine.RuntimeService
import org.springframework.stereotype.Service

@Service
class SafeDeploymentDeletionService(
    private val repositoryService: RepositoryService,
    private val runtimeService: RuntimeService
) {
    
    /**
     * 安全删除部署(检查是否有运行中的实例)
     * 企业场景:流程下线前,确保没有正在执行的流程实例
     */
    fun safeDeleteDeployment(deploymentId: String): Boolean {
        // 获取部署信息
        val deployment = repositoryService.createDeploymentQuery()
            .deploymentId(deploymentId)
            .singleResult()
            ?: throw IllegalArgumentException("部署不存在: $deploymentId")
        
        println("准备删除部署: ${deployment.name} (${deployment.id})")
        
        // 检查是否有运行中的流程实例
        val processDefinitions = repositoryService.createProcessDefinitionQuery()
            .deploymentId(deploymentId)
            .list()
        
        val hasRunningInstances = processDefinitions.any { pd ->
            val count = runtimeService.createProcessInstanceQuery()
                .processDefinitionId(pd.id)
                .count()
            count > 0
        }
        
        if (hasRunningInstances) {
            println("删除失败:该部署下有正在运行的流程实例")
            return false
        }
        
        // 安全删除
        repositoryService.deleteDeployment(deploymentId, false)
        println("部署删除成功")
        return true
    }
}

示例2:强制删除部署(级联删除)

kotlin
import org.flowable.engine.RepositoryService
import org.springframework.stereotype.Service

@Service
class ForceDeploymentDeletionService(
    private val repositoryService: RepositoryService
) {
    
    /**
     * 强制删除部署(级联删除所有数据)
     * 企业场景:测试环境清理,或流程紧急下线
     */
    fun forceDeleteDeployment(deploymentId: String) {
        val deployment = repositoryService.createDeploymentQuery()
            .deploymentId(deploymentId)
            .singleResult()
            ?: throw IllegalArgumentException("部署不存在")
        
        println("警告:将强制删除部署及所有相关数据")
        println("部署名称: ${deployment.name}")
        println("部署ID: ${deployment.id}")
        
        // 级联删除所有相关数据
        repositoryService.deleteDeployment(deploymentId, true)
        
        println("部署已强制删除")
    }
}

示例3:批量删除旧版本部署

kotlin
import org.flowable.engine.RepositoryService
import org.springframework.stereotype.Service

@Service
class DeploymentCleanupService(
    private val repositoryService: RepositoryService
) {
    
    /**
     * 清理旧版本的流程定义
     * 企业场景:保留最新N个版本,删除更早的版本节省空间
     */
    fun cleanupOldVersions(processDefinitionKey: String, keepVersions: Int = 3) {
        // 获取所有版本的流程定义
        val allVersions = repositoryService.createProcessDefinitionQuery()
            .processDefinitionKey(processDefinitionKey)
            .orderByProcessDefinitionVersion()
            .desc()
            .list()
        
        if (allVersions.size <= keepVersions) {
            println("版本数不超过保留数量,无需清理")
            return
        }
        
        // 需要删除的版本
        val versionsToDelete = allVersions.drop(keepVersions)
        
        println("将删除 ${versionsToDelete.size} 个旧版本")
        
        versionsToDelete.forEach { pd ->
            try {
                println("删除版本 V${pd.version}, 部署ID: ${pd.deploymentId}")
                repositoryService.deleteDeployment(pd.deploymentId, false)
            } catch (e: Exception) {
                println("删除失败: ${e.message}")
            }
        }
    }
}

示例4:删除部署前的数据统计

kotlin
import org.flowable.engine.RepositoryService
import org.flowable.engine.RuntimeService
import org.flowable.engine.HistoryService
import org.springframework.stereotype.Service

data class DeploymentDeletionReport(
    val deploymentId: String,
    val deploymentName: String,
    val processDefinitionCount: Int,
    val runningInstanceCount: Long,
    val historicInstanceCount: Long,
    val canSafeDelete: Boolean
)

@Service
class DeploymentAnalysisService(
    private val repositoryService: RepositoryService,
    private val runtimeService: RuntimeService,
    private val historyService: HistoryService
) {
    
    /**
     * 分析部署删除的影响
     * 企业场景:删除前评估影响范围
     */
    fun analyzeDeploymentDeletion(deploymentId: String): DeploymentDeletionReport {
        val deployment = repositoryService.createDeploymentQuery()
            .deploymentId(deploymentId)
            .singleResult()
            ?: throw IllegalArgumentException("部署不存在")
        
        val processDefinitions = repositoryService.createProcessDefinitionQuery()
            .deploymentId(deploymentId)
            .list()
        
        var totalRunningInstances = 0L
        var totalHistoricInstances = 0L
        
        processDefinitions.forEach { pd ->
            val running = runtimeService.createProcessInstanceQuery()
                .processDefinitionId(pd.id)
                .count()
            
            val historic = historyService.createHistoricProcessInstanceQuery()
                .processDefinitionId(pd.id)
                .count()
            
            totalRunningInstances += running
            totalHistoricInstances += historic
        }
        
        return DeploymentDeletionReport(
            deploymentId = deployment.id,
            deploymentName = deployment.name,
            processDefinitionCount = processDefinitions.size,
            runningInstanceCount = totalRunningInstances,
            historicInstanceCount = totalHistoricInstances,
            canSafeDelete = totalRunningInstances == 0L
        )
    }
    
    /**
     * 打印删除报告
     */
    fun printDeletionReport(deploymentId: String) {
        val report = analyzeDeploymentDeletion(deploymentId)
        
        println("""
            === 部署删除影响分析 ===
            部署名称: ${report.deploymentName}
            流程定义数: ${report.processDefinitionCount}
            运行中实例: ${report.runningInstanceCount}
            历史实例数: ${report.historicInstanceCount}
            可安全删除: ${if (report.canSafeDelete) "是" else "否"}
            
            ${if (!report.canSafeDelete) 
                "警告:有${report.runningInstanceCount}个运行中的实例,删除将失败或导致流程中断" 
            else 
                "可以安全删除"}
        """.trimIndent())
    }
}

示例5:部署管理REST API

kotlin
import org.flowable.engine.RepositoryService
import org.springframework.web.bind.annotation.*

@RestController
@RequestMapping("/api/deployments")
class DeploymentManagementController(
    private val repositoryService: RepositoryService
) {
    
    /**
     * 删除部署
     */
    @DeleteMapping("/{deploymentId}")
    fun deleteDeployment(
        @PathVariable deploymentId: String,
        @RequestParam(defaultValue = "false") cascade: Boolean
    ): Map<String, Any> {
        
        return try {
            repositoryService.deleteDeployment(deploymentId, cascade)
            
            mapOf(
                "success" to true,
                "message" to "部署删除成功",
                "cascade" to cascade
            )
        } catch (e: Exception) {
            mapOf(
                "success" to false,
                "message" to "部署删除失败: ${e.message}",
                "cascade" to cascade
            )
        }
    }
}

注意事项

1. 数据完整性

  • 不使用cascade时,如果有运行中的实例,删除会失败
  • 使用cascade=true会删除所有相关数据,包括历史记录,操作不可逆

2. 级联删除影响

  • 级联删除会删除:流程定义、流程实例、任务、变量、历史数据等
  • 谨慎使用cascade=true,特别是生产环境

3. 版本管理

  • 删除部署会删除该部署下的所有流程定义版本
  • 如果流程定义有多个版本分布在不同部署中,只会删除当前部署的版本

4. 权限控制

  • 删除部署是高危操作,应严格控制权限
  • 建议记录删除操作日志

5. 生产环境建议

  • 生产环境应使用挂起而非删除
  • 如必须删除,应先停止所有流程实例

相关 API

  • RepositoryService.deleteDeployment() - 删除部署
  • RepositoryService.createDeploymentQuery() - 查询部署
  • RepositoryService.suspendProcessDefinitionById() - 挂起流程定义(推荐替代删除)
  • RuntimeService.deleteProcessInstance() - 删除流程实例

最佳实践

1. 先挂起后删除

kotlin
fun safeDeleteProcess(processDefinitionKey: String) {
    // 先挂起流程定义,阻止新实例启动
    repositoryService.suspendProcessDefinitionByKey(processDefinitionKey)
    
    // 等待现有实例完成
    // ...
    
    // 最后删除部署
    val pd = repositoryService.createProcessDefinitionQuery()
        .processDefinitionKey(processDefinitionKey)
        .latestVersion()
        .singleResult()
    
    repositoryService.deleteDeployment(pd.deploymentId, false)
}

2. 软删除(仅做标记)

kotlin
// 使用流程类别标记为已删除,而不是真正删除
repositoryService.setDeploymentCategory(deploymentId, "DELETED")

本文档说明

  • 基于 Flowable 7.1.0 版本编写
  • 所有示例均可直接在 Spring Boot + Kotlin 项目中使用
  • 示例场景来自真实企业应用,具有实际参考价值