{"record":{"id":"aeee564c93304668","repo":"baomidou/mybatis-plus","slug":"environment-declaration-requires-a-transactionfact","errorCode":null,"errorMessage":"Environment declaration requires a TransactionFactory.","messagePattern":"Environment declaration requires a TransactionFactory\\.","errorType":"exception","errorClass":"BuilderException","httpStatus":null,"severity":"error","filePath":"mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/MybatisXMLConfigBuilder.java","lineNumber":346,"sourceCode":"        DatabaseIdProvider databaseIdProvider = (DatabaseIdProvider) resolveClass(type).getDeclaredConstructor()\n            .newInstance();\n        databaseIdProvider.setProperties(properties);\n        Environment environment = configuration.getEnvironment();\n        if (environment != null) {\n            String databaseId = databaseIdProvider.getDatabaseId(environment.getDataSource());\n            configuration.setDatabaseId(databaseId);\n        }\n    }\n\n    private TransactionFactory transactionManagerElement(XNode context) throws Exception {\n        if (context != null) {\n            String type = context.getStringAttribute(\"type\");\n            Properties props = context.getChildrenAsProperties();\n            TransactionFactory factory = (TransactionFactory) resolveClass(type).getDeclaredConstructor().newInstance();\n            factory.setProperties(props);\n            return factory;\n        }\n        throw new BuilderException(\"Environment declaration requires a TransactionFactory.\");\n    }\n\n    private DataSourceFactory dataSourceElement(XNode context) throws Exception {\n        if (context != null) {\n            String type = context.getStringAttribute(\"type\");\n            Properties props = context.getChildrenAsProperties();\n            DataSourceFactory factory = (DataSourceFactory) resolveClass(type).getDeclaredConstructor().newInstance();\n            factory.setProperties(props);\n            return factory;\n        }\n        throw new BuilderException(\"Environment declaration requires a DataSourceFactory.\");\n    }\n\n    private void typeHandlersElement(XNode context) {\n        if (context == null) {\n            return;\n        }\n        for (XNode child : context.getChildren()) {","sourceCodeStart":328,"sourceCodeEnd":364,"githubUrl":"https://github.com/baomidou/mybatis-plus/blob/bf67d907478c724120bf76292da54abf9e73c2b3/mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/MybatisXMLConfigBuilder.java#L328-L364","documentation":"Thrown by transactionManagerElement when an <environment> declaration in mybatis-config.xml has no <transactionManager> child (the XNode passed in is null). Every environment must pair a TransactionFactory with a DataSourceFactory; a missing transaction manager makes the environment unusable, so configuration parsing fails.","triggerScenarios":"<environment id=\"dev\"><dataSource ...>...</dataSource></environment> with no <transactionManager type=\"JDBC\"/> element; or an empty <transactionManager/> that XPath resolves to null.","commonSituations":"Hand-editing the config and deleting the transactionManager block; merging environment snippets and dropping the element; beginners copying a partial example from tutorials.","solutions":["Add <transactionManager type=\"JDBC\"/> (or MANAGED, or a custom TransactionFactory alias) inside the <environment>.","Ensure element order and nesting follow the DTD: environment > transactionManager, dataSource.","In Spring/Spring Boot apps, prefer omitting <environments> entirely and letting Spring's DataSourceTransactionManager manage transactions."],"exampleFix":"<!-- before -->\n<environment id=\"dev\">\n  <dataSource type=\"POOLED\">...</dataSource>\n</environment>\n\n<!-- after -->\n<environment id=\"dev\">\n  <transactionManager type=\"JDBC\"/>\n  <dataSource type=\"POOLED\">...</dataSource>\n</environment>","handlingStrategy":"validation","validationCode":"// ensure each <environment> has a <transactionManager>\norg.w3c.dom.NodeList envs = doc.getElementsByTagName(\"environment\");\nfor (int i = 0; i < envs.getLength(); i++) {\n    org.w3c.dom.Element env = (org.w3c.dom.Element) envs.item(i);\n    if (env.getElementsByTagName(\"transactionManager\").getLength() == 0)\n        throw new IllegalStateException(\"environment \" + env.getAttribute(\"id\") + \" lacks transactionManager\");\n}","typeGuard":null,"tryCatchPattern":"Catch BuilderException 'Environment declaration requires a TransactionFactory.' at startup; add the element named by the message and rebuild — deterministic, not retryable.","preventionTips":["Use the DTD/IDE autocomplete for environment structure.","In Spring apps, drop <environments> and use Spring-managed transactions."],"tags":["mybatis","mybatis-plus","xml-config","environment","transaction"],"backgroundTag":null,"analyzedSha":"bf67d907478c724120bf76292da54abf9e73c2b3","analyzedAt":"2026-08-14T15:17:09.543Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}