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");



        // 初始化NamedParameterJdbcTemplate

        template = 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;

        }



        @Override

        public String toString() {

            return "Student{" +

                    "id='" + id + '\'' +

                    ", name='" + name + '\'' +

                    ", age=" + age +

                    ", homeAddress='" + homeAddress + '\'' +

                    ", birthday=" + birthday +

                    '}';

        }

    }

}

本文章已经生成可运行项目
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

awei0916

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值