MyBatis-Plus 3.5+ 整合达梦数据库实战:从踩坑到填坑的完整配置流程
达梦数据库作为国产数据库的代表之一,在企业级应用中越来越常见。然而,当它与MyBatis-Plus这一流行的ORM框架结合使用时,开发者往往会遇到各种兼容性问题。本文将带你从零开始,一步步完成SpringBoot项目中MyBatis-Plus与达梦数据库的整合,并解决那些令人头疼的"坑"。
1. 环境准备与基础配置
在开始之前,确保你已经准备好以下环境:
- JDK 1.8+
- SpringBoot 2.3+
- MyBatis-Plus 3.5+
- 达梦数据库7+
1.1 依赖配置
首先,在pom.xml中添加必要的依赖:
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.3</version> </dependency> <dependency> <groupId>com.dameng</groupId> <artifactId>DmJdbcDriver18</artifactId> <version>1.8</version> </dependency>注意:达梦JDBC驱动版本建议使用18及以上,后续会解释原因
1.2 数据源配置
在application.yml中配置达梦数据库连接:
spring: datasource: driver-class-name: dm.jdbc.driver.DmDriver url: jdbc:dm://localhost:5236/your_database username: your_username password: your_password2. MyBatis-Plus核心配置
2.1 SQL注入器配置
达梦数据库与MySQL在语法上存在差异,需要自定义SQL注入器:
@Configuration public class MybatisPlusConfig { @Bean public MybatisPlusSqlInjector mybatisPlusSqlInjector() { return new MybatisPlusSqlInjector() { @Override public List<AbstractMethod> getMethodList(Class<?> mapperClass) { List<AbstractMethod> methodList = super.getMethodList(mapperClass); // 移除不兼容的方法 methodList.removeIf(method -> method instanceof InsertBatchSomeColumn); return methodList; } }; } }2.2 分页插件配置
达梦数据库的分页语法特殊,需要自定义分页插件:
@Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.DM) { @Override protected String concatOrderBy(String originalSql, List<OrderItem> orderList) { // 达梦特有的ORDER BY处理逻辑 return super.concatOrderBy(originalSql, orderList); } }); return interceptor; }3. 常见问题与解决方案
3.1 saveBatch方法不兼容问题
MyBatis-Plus的批量插入方法saveBatch在达梦数据库中可能无法正常工作,这是因为生成的SQL包含换行符。解决方案是自定义批量插入方法:
public class CustomBaseMapper<T> extends BaseMapper<T> { @Insert("<script>" + "INSERT INTO ${tableName} " + "<foreach collection='columns' item='column' open='(' separator=',' close=')'>" + "${column}" + "</foreach> " + "VALUES " + "<foreach collection='dataList' item='item' separator=','>" + "<foreach collection='columns' item='column' open='(' separator=',' close=')'>" + "#{item.${column}}" + "</foreach>" + "</foreach>" + "</script>") int batchInsert(@Param("tableName") String tableName, @Param("columns") List<String> columns, @Param("dataList") List<T> dataList); }3.2 事务内查询问题
在使用dmjdbc17驱动时,可能会遇到事务内保存后立即查询不到数据的问题。这是达梦7的一个已知问题,解决方案是:
- 升级JDBC驱动到18+版本
- 或者在事务方法上添加
@Transactional(isolation = Isolation.READ_COMMITTED)
@Transactional(isolation = Isolation.READ_COMMITTED) public void saveAndQuery(Entity entity) { mapper.insert(entity); Entity result = mapper.selectById(entity.getId()); // 现在可以正常查询到结果 }3.3 主键返回问题
达梦数据库在使用批量插入时可能无法正确返回主键ID。解决方案是使用达梦特有的序列:
-- 首先创建序列 CREATE SEQUENCE SEQ_TABLE_ID INCREMENT BY 1 START WITH 1;然后在实体类中配置:
@TableId(value = "ID", type = IdType.INPUT) private Long id;在Mapper XML中使用:
<insert id="insertBatch" parameterType="java.util.List"> <selectKey keyProperty="id" resultType="long" order="BEFORE"> SELECT SEQ_TABLE_ID.NEXTVAL FROM DUAL </selectKey> INSERT INTO TABLE_NAME (ID, COLUMN1, COLUMN2) VALUES <foreach collection="list" item="item" separator=","> (#{item.id}, #{item.column1}, #{item.column2}) </foreach> </insert>4. 高级配置与优化
4.1 大字段与聚集主键冲突
达梦7.15+版本中,聚集主键和大字段(TEXT等)不能共存。解决方案有:
修改数据库配置(需要重启):
- 找到
dm.ini文件 - 修改
PK_WITH_CLUSTER=0 - 重启达梦服务
- 找到
建表时使用非聚集主键:
CREATE TABLE EXAMPLE ( ID BIGINT NOT NULL PRIMARY KEY NONCLUSTER, CONTENT TEXT, -- 其他字段 );- 对于已存在的表:
-- 先删除聚集主键约束 ALTER TABLE EXAMPLE DROP CONSTRAINT CONSTRAINT_NAME; -- 添加非聚集主键 ALTER TABLE EXAMPLE ADD CONSTRAINT PK_EXAMPLE PRIMARY KEY NONCLUSTER(ID);4.2 日志分析与SQL优化
配置MyBatis日志,方便排查问题:
logging: level: com.yourpackage.mapper: debug常见SQL兼容性问题处理:
- LIMIT语法:达梦使用
TOP或ROWNUM而非LIMIT - 日期函数:使用
SYSDATE而非NOW() - 字符串连接:使用
||而非CONCAT()
4.3 性能优化建议
- 批量操作大小控制在100-500条/次
- 复杂查询使用存储过程
- 合理设置连接池参数:
spring: datasource: hikari: maximum-pool-size: 20 connection-timeout: 30000 idle-timeout: 600000 max-lifetime: 18000005. 实战案例:用户管理系统集成
让我们通过一个完整的用户管理模块来实践上述配置:
5.1 实体类定义
@Data @TableName("SYS_USER") public class User { @TableId(value = "ID", type = IdType.INPUT) private Long id; private String username; private String password; @TableField(fill = FieldFill.INSERT) private Date createTime; @TableField(fill = FieldFill.INSERT_UPDATE) private Date updateTime; }5.2 Mapper接口
public interface UserMapper extends CustomBaseMapper<User> { // 自定义批量插入方法 int batchInsertUsers(@Param("list") List<User> users); }5.3 Service实现
@Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService { @Override @Transactional(isolation = Isolation.READ_COMMITTED) public boolean saveBatchUsers(List<User> users) { // 使用自定义批量插入方法 return baseMapper.batchInsertUsers(users) > 0; } // 其他业务方法... }5.4 控制器示例
@RestController @RequestMapping("/users") public class UserController { @Autowired private UserService userService; @PostMapping("/batch") public Result batchAdd(@RequestBody List<User> users) { boolean success = userService.saveBatchUsers(users); return success ? Result.success() : Result.fail(); } // 其他API... }在完成这些配置后,你的SpringBoot项目应该能够顺畅地使用MyBatis-Plus操作达梦数据库了。记住,当遇到问题时,查看生成的SQL日志通常是解决问题的第一步。