Spring Boot JDBC Template插入带默认值的SQL Server非空列方案问询
解决方案
Spring JDBC Template本身没有专门处理这类默认值列插入的独立库函数,但Spring JDBC模块原生提供了SimpleJdbcInsert工具类,完全适配你的场景,无需手动拼接SQL,也不需要应用层维护数据库默认值逻辑。
前置修正
首先需要把Dto中的基础类型改为包装类型,否则未显式赋值时基本类型会有默认值(比如int默认是0),无法区分「用户未传值」和「用户传了0值」两种场景:
public class ProductSalesDto { ... // 改为Integer包装类,未赋值时为null public Integer customerId; ... }
实现步骤
- 初始化SimpleJdbcInsert
在Dao层构造方法中一次性初始化插入工具,指定操作的表名即可,无需重复初始化:
@Repository public class ProductSalesDao { private final SimpleJdbcInsert insertProductSales; // 构造注入JdbcTemplate public ProductSalesDao(JdbcTemplate jdbcTemplate) { this.insertProductSales = new SimpleJdbcInsert(jdbcTemplate) .withTableName("ProductSales"); // 如果需要返回自增主键,可追加配置:.usingGeneratedKeyColumns("主键列名") } }
- 执行插入逻辑
插入时仅把Dto中非null的字段加入参数Map,SimpleJdbcInsert会自动生成仅包含传入字段的INSERT语句,未传入的字段自动使用数据库配置的默认值:
public void addProductSales(ProductSalesDto dto) { Map<String, Object> params = new HashMap<>(); // 仅非null字段加入参数 if (dto.customerId != null) { params.put("CustomerId", dto.customerId); } if (dto.totalAmount != null) { params.put("TotalAmount", dto.totalAmount); } // 其余列同理按规则添加 // 执行插入 insertProductSales.execute(params); // 若需要获取自增主键,改用如下代码: // Number key = insertProductSales.executeAndReturnKey(params); // int id = key.intValue(); }
优化(适配50+列的场景)
如果列数太多手动判断非null太繁琐,可以写个通用反射工具方法,自动扫描Dto所有非null字段转换为参数Map,不用逐列写判断逻辑:
// 通用Dto转参数Map方法,驼峰字段名自动转数据库大驼峰列名,可根据自己的命名规则调整 private Map<String, Object> dtoToParams(Object dto) throws IllegalAccessException { Map<String, Object> params = new HashMap<>(); for (Field field : dto.getClass().getDeclaredFields()) { field.setAccessible(true); Object value = field.get(dto); if (value != null) { // 这里按你的列名规则转换,比如小驼峰customerId转成CustomerId,或者下划线格式CUSTOMER_ID String columnName = CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, field.getName()); params.put(columnName, value); } } return params; }
注:CaseFormat是Guava提供的命名转换工具类,不想引入Guava可以自行实现简单的驼峰转目标格式的逻辑
使用工具方法后插入逻辑可以简化为:
public void addProductSales(ProductSalesDto dto) throws IllegalAccessException { insertProductSales.execute(dtoToParams(dto)); }
内容的提问来源于stack exchange,提问作者mattsmith5
相关产品推荐
相关产品推荐

