{"record":{"id":"792965530137eaff","repo":"flowable/flowable-engine","slug":"no-update-statement-for-updatedobject-getclass","errorCode":null,"errorMessage":"no update statement for ${updatedObject.getClass()} in the ibatis mapping files","messagePattern":"no update statement for (.+?) in the ibatis mapping files","errorType":"exception","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/db/DbSqlSession.java","lineNumber":615,"sourceCode":"        \n        if (!bulkUpdateOperations.isEmpty()) {\n            bulkUpdateOperations.forEach(this::flushBulkUpdate);\n        }\n\n        if (!updatedObjects.isEmpty()) {\n            updatedObjects.forEach(this::flushUpdateEntity);\n        }\n\n        updatedObjects.clear();\n        bulkUpdateOperations.clear();\n    }\n\n    protected void flushUpdateEntity(Entity updatedObject) {\n        String updateStatement = dbSqlSessionFactory.getUpdateStatement(updatedObject);\n        updateStatement = dbSqlSessionFactory.mapStatement(updateStatement);\n\n        if (updateStatement == null) {\n            throw new FlowableException(\"no update statement for \" + updatedObject.getClass() + \" in the ibatis mapping files\");\n        }\n\n        LOGGER.debug(\"updating: {}\", updatedObject);\n\n        int updatedRecords = sqlSession.update(updateStatement, updatedObject);\n        if (updatedRecords == 0) {\n            throw new FlowableOptimisticLockingException(updatedObject + \" was updated by another transaction concurrently\");\n        }\n\n        // See https://activiti.atlassian.net/browse/ACT-1290\n        if (updatedObject instanceof HasRevision) {\n            ((HasRevision) updatedObject).setRevision(((HasRevision) updatedObject).getRevisionNext());\n        }\n    }\n\n    protected void flushBulkUpdate(BulkUpdateOperation bulkUpdateOperation) {\n        // Bulk update\n        bulkUpdateOperation.execute(sqlSession);","sourceCodeStart":597,"sourceCodeEnd":633,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/db/DbSqlSession.java#L597-L633","documentation":"Thrown by DbSqlSession.flushUpdateEntity when the update statement resolved for the entity's class is null after mapping. The persistence framework could not find an ibatis update statement for the entity about to be updated during command flush.","triggerScenarios":"Flushing a dirty entity whose class has no update statement registered in DbSqlSessionFactory (getUpdateStatement returns null), typically a custom entity whose MyBatis mapper lacks the update statement or whose mapping file was not loaded.","commonSituations":"Custom Entity implementations without a full mapper XML; stale/partial mapping configuration after an upgrade; entity class renamed so statement lookup keys no longer match.","solutions":["Add the update statement to the entity's ibatis mapping XML (matching the name DbSqlSessionFactory.getUpdateStatement expects).","Register the update statement name in DbSqlSessionFactory for the entity class.","Confirm the mapping file is included in the MyBatis configuration/mapper locations.","Check the entity class identity is the one the mappings were generated for (no duplicate/custom subclass)."],"exampleFix":"// before\n<update id=\"updateMyEntity\">...</update> // missing -> statement resolves to null\n// after\n<update id=\"updateMyEntity\" parameterType=\"...\">UPDATE MY_ENTITY SET ... WHERE ID_ = #{id}</update>","handlingStrategy":"validation","validationCode":"String stmt = dbSqlSessionFactory.getBulkInsertStatement(MyEntityImpl.class);\nif (stmt == null || dbSqlSessionFactory.mapStatement(stmt) == null) {\n  throw new IllegalStateException(\"Register bulk insert statement for \" + MyEntityImpl.class);\n}","typeGuard":null,"tryCatchPattern":"try { flushBulkInsert(entities, MyEntityImpl.class); }\ncatch (FlowableException e) { if (e.getMessage().startsWith(\"no insert statement\")) { /* fix mapping / register statement */ } throw e; }","preventionTips":["When adding a custom entity, copy the full mapper XML of a similar built-in entity including bulk insert.","Add a startup test that flushes each entity type once against an in-memory DB.","Keep all flowable module versions aligned so statement registries and mappings match.","Name statements consistently and register them explicitly in DbSqlSessionFactory."],"tags":["database","ibatis","persistence","missing-statement"],"backgroundTag":"internal-invariant-violation","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}