当前位置: 首页 > news >正文

NamedParameterJdbcTemplate 使用方法及介绍

NamedParameterJdbcTemplate是 Spring 框架中用于数据库操作的核心类之一,它拓展了JdbcTemplate,通过封装实现命名参数特性,相比传统占位符?,命名参数可读性和维护性更强,能有效避免参数顺序混淆问题。

一、核心支持类

1. SqlParameterSource 实现类

  • MapSqlParameterSource:简单封装java.util.Map,可通过addValue方法添加参数,也能基于现有Map构建,如new MapSqlParameterSource(paramMap) 。
  • BeanPropertySqlParameterSource:封装 JavaBean 对象,依据对象属性值为命名参数赋值,适用于参数来自对象属性的场景。
  • EmptySqlParameterSource:为空的SqlParameterSource,常用于占位,如查询语句无实际参数时使用EmptySqlParameterSource.INSTANCE。

2. RowMapper 接口实现类

  • SingleColumnRowMapper:用于处理单列数据查询结果,将查询结果映射为List<String>、Integer等单列数据类型。
  • BeanPropertyRowMapper:可将查询结果匹配到对象,如List<XxxVO>,且会自动将数据库字段的下划线命名转换为驼峰命名属性。

二、数据库操作方法

1. 插入 / 修改 / 删除数据(update 及 batchUpdate 方法)

  • 使用 Map 作为参数:通过int update(String sql, Map<String, ?> paramMap)方法,在Map中以键值对形式设置参数,键对应 SQL 语句中的命名参数,如:

Map<String, Object> paramMap = new HashMap<>();

paramMap.put("id", UUID.randomUUID().toString());

paramMap.put("name", "小明");

template.update(

    "insert into student(id,name) values (:id,:name)",

    paramMap

);

  • 使用 BeanPropertySqlParameterSource 作为参数:借助int update(String sql, SqlParameterSource paramSource),将 JavaBean 封装为BeanPropertySqlParameterSource传入,示例如下:

StudentDTO dto=new StudentDTO();

dto.setId(UUID.randomUUID().toString());

dto.setName("小红");

template.update("insert into student(id,name) values (:id,:name)",

                new BeanPropertySqlParameterSource(dto));

  • 使用 MapSqlParameterSource 作为参数:同样通过int update(String sql, SqlParameterSource paramSource),可链式调用addValue添加参数,或基于现有Map构建:

MapSqlParameterSource mapSqlParameterSource = new MapSqlParameterSource()

       .addValue("id", UUID.randomUUID().toString())

       .addValue("name", "小王");

template.update("insert into student(id,name) values (:id,:name)",mapSqlParameterSource);

2. 查询数据(query 及 queryForXXX 方法)

  • 返回单行单列数据:有public < T > T queryForObject(String sql, Map<String, ?> paramMap, Class<T> requiredType)和public < T > T queryForObject(String sql, SqlParameterSource paramSource, Class<T> requiredType)两种形式,可传入Map、SqlParameterSource,如:

Integer count = template.queryForObject(

                "select count(*) from student", new HashMap<>(), Integer.class);

  • 返回(多行)单列数据:使用public < T> List< T> queryForList(String sql, Map<String, ?> paramMap, Class< T > elementType) 或public < T> List< T> queryForList(String sql, SqlParameterSource paramSource, Class< T> elementType) ,如:

List<String> namelist = template.queryForList("select name from student", new HashMap<>(), String.class);

  • 返回单行数据:public < T> T queryForObject(String sql, Map< String, ?> paramMap, RowMapper< T>rowMapper)和public < T> T queryForObject(String sql, SqlParameterSource paramSource, RowMapper< T> rowMapper) ,搭配RowMapper实现对象映射:

Student  stu = template.queryForObject(

                "select * from student limit 1", new HashMap<>(), new BeanPropertyRowMapper<Student>(Student.class));

  • 返回 Map 形式的单行数据:通过public Map< String, Object> queryForMap(String sql, Map< String, ?> paramMap)和public Map< String, Object> queryForMap(String sql, SqlParameterSource paramSource) ,将单行结果映射为Map 。
  • 返回多行数据:包括public < T> List< T> query(String sql, Map< String, ?> paramMap, RowMapper< T> rowMapper)等三个重载方法,根据需求传入参数和RowMapper;public List< Map< String, Object>> queryForList(String sql, Map< String, ?> paramMap) 等方法则返回多行数据的Map集合。

三、使用建议

在实际开发中,推荐优先使用NamedParameterJdbcTemplate替代JdbcTemplate 。若仍需使用JdbcTemplate,可通过NamedParameterJdbcTemplate#getJdbcOperations()获取。同时,由于查询结果为Map的 API 在数据类型处理上存在局限性,不建议频繁使用此类 API,以免后期维护成本增加。

以上详细介绍了NamedParameterJdbcTemplate的使用方法。若你在实践中遇到问题,或希望了解某类操作的更多细节,欢迎随时与我交流。

四、完整例子

import org.springframework.jdbc.core.BeanPropertyRowMapper;import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;import org.springframework.jdbc.datasource.DriverManagerDataSource;import java.util.*;public class NamedParameterJdbcTemplateExample {private static NamedParameterJdbcTemplate template;static {// 配置数据源DriverManagerDataSource dataSource = new DriverManagerDataSource();dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");dataSource.setUrl("jdbc:mysql://localhost:3306/test");dataSource.setUsername("root");dataSource.setPassword("password");// 初始化NamedParameterJdbcTemplatetemplate = new NamedParameterJdbcTemplate(dataSource);}public static void main(String[] args) {// 1. 插入数据 - 使用Map作为参数insertWithMap();// 2. 插入数据 - 使用BeanPropertySqlParameterSource作为参数insertWithBean();// 3. 查询单行单列数据Integer count = getCount();System.out.println("学生总数: " + count);// 4. 查询多行单列数据List<String> names = getNames();System.out.println("所有学生姓名: " + names);// 5. 查询单行数据Student student = getStudent();System.out.println("查询单个学生: " + student);// 6. 查询多行数据List<Student> students = getAllStudents();System.out.println("所有学生: " + students);// 7. 更新数据updateStudent();System.out.println("更新后所有学生: " + getAllStudents());// 8. 删除数据deleteStudent();System.out.println("删除后所有学生: " + getAllStudents());}// 1. 插入数据 - 使用Map作为参数private static void insertWithMap() {Map<String, Object> paramMap = new HashMap<>();paramMap.put("id", UUID.randomUUID().toString());paramMap.put("name", "小明");paramMap.put("age", 33);paramMap.put("homeAddress", "乐山");paramMap.put("birthday", new Date());template.update("insert into student(id,name,age,home_address,birthday) values (:id,:name,:age,:homeAddress,:birthday)",paramMap);}// 2. 插入数据 - 使用BeanPropertySqlParameterSource作为参数private static void insertWithBean() {StudentDTO dto = new StudentDTO();dto.setId(UUID.randomUUID().toString());dto.setName("小红");dto.setHomeAddress("成都");template.update("insert into student(id,name,home_address) values (:id,:name,:homeAddress)",new BeanPropertySqlParameterSource(dto));}// 3. 查询单行单列数据private static Integer getCount() {return template.queryForObject("select count(*) from student",new HashMap<>(),Integer.class);}// 4. 查询多行单列数据private static List<String> getNames() {return template.queryForList("select name from student",new HashMap<>(),String.class);}// 5. 查询单行数据private static Student getStudent() {return template.queryForObject("select * from student limit 1",new HashMap<>(),new BeanPropertyRowMapper<>(Student.class));}// 6. 查询多行数据private static List<Student> getAllStudents() {return template.query("select * from student",new BeanPropertyRowMapper<>(Student.class));}// 7. 更新数据private static void updateStudent() {MapSqlParameterSource params = new MapSqlParameterSource().addValue("age", 25).addValue("name", "小明");template.update("update student set age = :age where name = :name",params);}// 8. 删除数据private static void deleteStudent() {MapSqlParameterSource params = new MapSqlParameterSource().addValue("name", "小明");template.update("delete from student where name = :name",params);}// 学生DTO类public static class StudentDTO {private String id;private String name;private String homeAddress;// getter和setter方法public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getHomeAddress() {return homeAddress;}public void setHomeAddress(String homeAddress) {this.homeAddress = homeAddress;}}// 学生实体类public static class Student {private String id;private String name;private Integer age;private String homeAddress;private Date birthday;// getter和setter方法public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public String getHomeAddress() {return homeAddress;}public void setHomeAddress(String homeAddress) {this.homeAddress = homeAddress;}public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday = birthday;}@Overridepublic String toString() {return "Student{" +"id='" + id + '\'' +", name='" + name + '\'' +", age=" + age +", homeAddress='" + homeAddress + '\'' +", birthday=" + birthday +'}';}}}

http://www.lqws.cn/news/202663.html

相关文章:

  • Readest(电子书阅读器) v0.9.53
  • Python爬虫-爬取各省份各年份高考分数线数据,进行数据分析
  • 使用 C/C++ 和 OpenCV 提取图像的感兴趣区域 (ROI)
  • Mysql批处理写入数据库
  • Opencv查找图形形状的重要API讲解
  • Cursor实现用excel数据填充word模版的方法
  • C#报价系统陈列展示成本核算系统项目管理系统纸品非纸品报价软件
  • linux 用户态时间性能优化工具perf/strace/gdb/varlind/gprof
  • 让DeepSeek写2025年高考作文
  • qiankun微前端 主应用vue3+vite、子应用vue3+vite
  • 使用 C++/OpenCV 创建动态流星雨特效 (实时动画)
  • ngx_stream_geo_module在传输层实现高性能 IP Region 路由
  • 学习STC51单片机30(芯片为STC89C52RCRC)
  • 【论文阅读笔记】《A survey on deep learning approaches for text-to-SQL》
  • 以SMMUv2为例,使用Trace32可视化操作SMMU的常用命令详解
  • 深入理解 Agent 与 LLM 的区别:从智能体到语言模型
  • 反向传播的核心是什么:计算损失函数对可训练参数的梯度=== 损失函数能通过计算图连接到可训练参数
  • 快速运行Dify前端,无需搭建后端环境
  • CADisplayLink、NSTimer、GCD定时器
  • 变幻莫测:CoreData 中 Transformable 类型面面俱到(一)
  • opencv_stereoRectify源码解析
  • 客户端和服务器已成功建立 TCP 连接【输出解析】
  • Clahs——问题解决:软件所有节点均超时
  • 能上Nature封面的idea!强化学习+卡尔曼滤波
  • C++之STL--list
  • 智能客服路由实战之RunnableBranch条件分支
  • 复旦联合百度发布Hallo4:让AI肖像“活”起来!新型扩散框架实现高保真音频驱动动画生成!
  • Python 函数全攻略:函数进阶(生成器、闭包、内置函数、装饰器、推导式)
  • AI大模型:(二)3.2 Llama-Factory微调训练deepseek-r1实践
  • 微前端架构下的B端页面设计:模块化与跨团队协作的终极方案