• NamedParameterJdbcTemplate使用详解


    一、什么是NamedParameterJdbcTemplate

    NamedParameterJdbcTemplate类拓展了JdbcTemplate类,对JdbcTemplate类进行了封装从而支持**具名参数特性**。

    什么是具名参数?
    SQL 按名称(以冒号开头)⽽不是按位置进⾏指定。

    例如:

    • 传统的jdbcTemplate的SQL语句定义,通过问号进行占位,如下:
     private final String QUERY_SQL = "INSERT INTO T_USER(username,password) VALUES(?,?)";
    
    • 1
    • NamedParameterJdbcTemplate的吗具名参数定义SQL语句:
    private final String QUERY_SQL = "INSERT INTO T_USER(username,password) VALUES(:username,:password)";
    
    • 1

    NamedParameterJdbcTemplate主要提供以下三类方法:execute方法、query及queryForXXX方法、update及batchUpdate方法。

    二、准备工作

    1、创建工程

    2、添加Maven依赖

    
    		<dependency>
    			<groupId>org.springframework.bootgroupId>
    			<artifactId>spring-boot-starter-jdbcartifactId>
    		dependency>
    
    
    		<dependency>
    			<groupId>mysqlgroupId>
    			<artifactId>mysql-connector-javaartifactId>
    			<scope>runtimescope>
    		dependency>
    
    
    		<dependency>
    			<groupId>org.projectlombokgroupId>
    			<artifactId>lombokartifactId>
    			<optional>trueoptional>
    		dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    另外:jdbc依赖也可以换成

    
    		<dependency>
    			<groupId>org.springframeworkgroupId>
    			<artifactId>spring-jdbcartifactId>
    			<version>5.0.9.RELEASEversion>
    		dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3、yaml配置

    #MySql8.0
    spring:
      datasource:
        driverClassName: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/数据库名?useSSL=false&characterEncoding=utf-8&useUnicode=true&serverTimezone=Asia/Shanghai
        username: 数据库用户名
        password: 数据库密码
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    4、数据库结构

    注意:数据库的id主键设置成自动递增,所以添加的时候不用考虑id
    在这里插入图片描述

    5、JavaBean实体

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class TUser implements Serializable {
    
        private Integer id;
        private String username;
        private String password;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    三、实际使用

    1.支持的类

    (1)SqlParameterSource

    可以使用SqlParameterSource实现具名参数,默认实现有 :

    1. MapSqlParameterSource,只是封装了java.util.Map
    2. BeanPropertySqlParameterSource封装了一个JavaBean对象,通过JavaBean对象属性设置具名参数值
    3. EmptySqlParameterSource 一个空的SqlParameterSource ,占位使用

    (2)RowMapper

    这个接口为了实现sql查询结果和对象间的转换,可以自己实现,也可以使用系统实现,主要实现类有:

    1. SingleColumnRowMapper,sql结果为一个单列的数据,如List , List,String,Integer等
    2. BeanPropertyRowMapper,sql结果匹配到对象 List< XxxVO> , XxxVO

    2、插入/修改/删除数据,使用update方法

    (1)Map作为参数

    API: int update(String sql, Map paramMap)

     	@Autowired
        private NamedParameterJdbcTemplate template;
        
        //添加数据
    		Map<String,Object> map = new HashMap<>();
            map.put("username","刘亦菲");
            map.put("password","4983ghh");
            template.update("INSERT INTO T_USER(username,password) VALUES(:username,:password)",map);
            
     //修改数据
    Map<String,Object> map = new HashMap<>();
    map.put("username","刘诗诗");
    map.put("password","ewgg");
    map.put("id",4);
    template.update("UPDATE T_USER SET USERNAME = :username,PASSWORD = :password WHERE ID = :id",map);
    
    //        删除数据
    Map<String,Object> map = new HashMap<>();
    map.put("id",4);
    template.update("DELETE FROM T_USER WHERE ID = :id",map);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    (2)BeanPropertySqlParameterSource作为参数

    API: int update(String sql, SqlParameterSource paramSource)

    1. 创建参数DTO
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class ConditionDTO {
    
        private String password;
    
        private String username;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    1. 给DTO属性传入数据并作为参数传入
    ConditionDTO conditionDTO = new ConditionDTO();
    conditionDTO.setUsername("成龙");
    conditionDTO.setPassword("2432tgh");
    
    BeanPropertySqlParameterSource beanParam = new BeanPropertySqlParameterSource(conditionDTO);
    template.update("INSERT INTO T_USER(username,password) VALUES(:username,:password)",beanParam);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    注意:用BeanPropertySqlParameterSource作为参数的时候,可以将参数DTO属性存值单独出来一个方法,这样可以解耦,代码维护相对轻松。如下:

    private ConditionDTO getConditionDTO() {
            ConditionDTO conditionDTO = new ConditionDTO();
            conditionDTO.setUsername("成龙");
            conditionDTO.setPassword("2432tgh");
            return conditionDTO;
        }
    
    BeanPropertySqlParameterSource beanParam = new BeanPropertySqlParameterSource(getConditionDTO());
    template.update("INSERT INTO T_USER(username,password) VALUES(:username,:password)",beanParam);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    (3)MapSqlParameterSource 作为参数

    API: int update(String sql, SqlParameterSource paramSource)

    MapSqlParameterSource mapSql = new MapSqlParameterSource();
    mapSql.addValue("username","李连杰")
          .addValue("password","huewrgowrei");
    template.update("INSERT INTO T_USER(username,password) VALUES(:username,:password)",mapSql);
    
    • 1
    • 2
    • 3
    • 4

    3、查询

    (1)返回单行单列数据

    注意:单行单列不是单独的一行或者单独的一列数据,单列单行是只有一个数据,如下:
    在这里插入图片描述
    API: public < T > T queryForObject(String sql, Map paramMap, Class requiredType)

    API: public < T > T queryForObject(String sql, SqlParameterSource paramSource, Class requiredType)

    Integer count = template.queryForObject(
                    "SELECT COUNT(*) FROM T_USER", new HashMap<>(), Integer.class);
    
    • 1
    • 2

    使用EmptySqlParameterSource

    String username = template.queryForObject( "SELECT USERNAME FROM T_USER WHERE ID = 4", EmptySqlParameterSource.INSTANCE, String.class); 
    
    • 1

    (2)返回 (多行)单列 数据

    多行单列形式:

    在这里插入图片描述

    API: public < T> List< T> queryForList(String sql, Map paramMap, Class< T > elementType)

    API: public < T> List< T> queryForList(String sql, SqlParameterSource paramSource, Class< T> elementType)

    List< String> nameList = template.queryForList("SELECT USERNAME FROM T_USER", new HashMap<>(), String.class);
    nameList.forEach(System.out::println);
    
    • 1
    • 2

    控制台打印结果:

    在这里插入图片描述

    (3)返回单行数据

    解释:数据库中的一行数据对应的就是java中的一个bean实体

    API:public < T> T queryForObject(String sql, Map< String, ?> paramMap, RowMapper< T>rowMapper)

    API: public < T> T queryForObject(String sql, SqlParameterSource paramSource, RowMapper< T> rowMapper)

    //BeanPropertyRowMapper会把下划线转化为驼峰属性
    TUser user = template.queryForObject(
                    "SELECT * FROM T_USER LIMIT 1", new HashMap<>(), new BeanPropertyRowMapper<TUser>(TUser.class));
    System.out.println("查询出来的user是:"+user);
    
    • 1
    • 2
    • 3
    • 4

    (4)返回Map形式的单行数据

    API: public Map< String, Object> queryForMap(String sql, Map< String, ?> paramMap)

    API: public Map< String, Object> queryForMap(String sql, SqlParameterSource paramSource)

     @RequestMapping("/querySingleTwo")
        public Map testQueryForObjectTwo() {
            Map< String, Object> userMap = template.queryForMap("SELECT * FROM T_USER LIMIT 1", new HashMap<>());
            System.out.println(userMap);
            return userMap;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    postman返回结果:
    在这里插入图片描述

    (5)返回多行数据

    API: public < T> List< T> query(String sql, Map< String, ?> paramMap, RowMapper< T> rowMapper)
    API: public < T> List< T> query(String sql, SqlParameterSource paramSource, RowMapper< T> rowMapper)
    API: public < T> List< T> query(String sql, RowMapper< T> rowMapper)

    	@RequestMapping("/querySingleTwo")
        public List< TUser> testQueryForObjectTwo() {
            List< TUser> userList = template.query(
                    "SELECT * FROM T_USER",
                    new BeanPropertyRowMapper<>(TUser.class)
            );
            return userList;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    postman返回结果:

    [
        {
            "id": 1,
            "username": "admin",
            "password": "admin"
        },
        {
            "id": 2,
            "username": "abc",
            "password": "123"
        },
        {
            "id": 3,
            "username": "abcd",
            "password": "1234"
        },
        {
            "id": 4,
            "username": "abcde",
            "password": "12345"
        },
        {
            "id": 109,
            "username": "刘亦菲",
            "password": "4983ghh"
        },
        {
            "id": 110,
            "username": "刘亦菲",
            "password": "4983ghh"
        },
        {
            "id": 111,
            "username": "成龙",
            "password": "2432tgh"
        },
        {
            "id": 112,
            "username": "李连杰",
            "password": "huewrgowrei"
        }
    ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    (6)返回多行数据(Map)

    API: public List< Map< String, Object>> queryForList(String sql, Map< String, ?> paramMap)
    API: public List< Map< String, Object>> queryForList(String sql, SqlParameterSource paramSource)

    	@RequestMapping("/querySingleTwo")
        public  List<Map<String, Object>> testQueryForObjectTwo() {
            List<Map<String, Object>> mapList = template.queryForList(
                    "SELECT * FROM T_USER", new HashMap<>());
            return mapList;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    postman返回结果:

    [
        {
            "id": 1,
            "username": "admin",
            "password": "admin"
        },
        {
            "id": 2,
            "username": "abc",
            "password": "123"
        },
        {
            "id": 3,
            "username": "abcd",
            "password": "1234"
        },
        {
            "id": 4,
            "username": "abcde",
            "password": "12345"
        },
        {
            "id": 109,
            "username": "刘亦菲",
            "password": "4983ghh"
        },
        {
            "id": 110,
            "username": "刘亦菲",
            "password": "4983ghh"
        },
        {
            "id": 111,
            "username": "成龙",
            "password": "2432tgh"
        },
        {
            "id": 112,
            "username": "李连杰",
            "password": "huewrgowrei"
        }
    ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    4、获取新增的主键

    NamedParameterJdbcTemplate还新增了KeyHolder类,使⽤它我们可以获得主键,类似Mybatis中的useGeneratedKeys。

    代码示例:

     @RequestMapping("/querySingleTwo")
        public int testQueryForObjectTwo() {
            String sql = "INSERT INTO T_USER(username,password) VALUES(:username,:password)";
            ConditionDTO conditionDTO = new ConditionDTO("r43g", "呼呼");
            SqlParameterSource sqlParameterSource = new BeanPropertySqlParameterSource(conditionDTO);
            KeyHolder keyHolder = new GeneratedKeyHolder();
            template.update(sql, sqlParameterSource, keyHolder);
            int k = keyHolder.getKey().intValue();
            System.out.println("主键值是:"+k);
            return k;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    返回结果就是新增的主键。

    5、批量操作 batchUpdate

    方法源码:

    在这里插入图片描述

    (1)批量添加

    SqlParameterSource[] 参数为例
    		List<TUser> list = new ArrayList<>();
            TUser tUser1 = new TUser();
            tUser1.setPassword("t7493857vd");
            tUser1.setUsername("给会儿");
    
            TUser tUser2 = new TUser();
            tUser2.setPassword("erwghrthey");
            tUser2.setUsername("国瑞");
    
            list.add(tUser1);
            list.add(tUser2);
    
            SqlParameterSource[] batch = SqlParameterSourceUtils.createBatch(list.toArray());
    
            template.batchUpdate("INSERT INTO T_USER(username,password) VALUES(:username,:password)",batch);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    (2)批量更新

    		List<TUser> list = new ArrayList<>();
            TUser tUser1 = new TUser();
            tUser1.setPassword("eryg");
            tUser1.setUsername("个人谈话人");
            tUser1.setId(109);
    
            TUser tUser2 = new TUser();
            tUser2.setPassword("我二哥");
            tUser2.setUsername("个羊肉汤");
            tUser1.setId(110);
    
            TUser tUser3 = new TUser();
            tUser3.setPassword("gerhr6");
            tUser3.setUsername("反倒是规范");
            tUser3.setId(111);
    
            list.add(tUser1);
            list.add(tUser2);
            list.add(tUser3);
    
            SqlParameterSource[] batch = SqlParameterSourceUtils.createBatch(list.toArray());
    
            template.batchUpdate("UPDATE T_USER SET USERNAME = :username,PASSWORD = :password WHERE ID = :id",batch);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    (3)批量删除

    		List<TUser> list = new ArrayList<>();
            TUser tUser1 = new TUser();
            tUser1.setId(109);
    
            TUser tUser2 = new TUser();
            tUser2.setId(112);
    
            TUser tUser3 = new TUser();
            tUser3.setId(113);
    
            list.add(tUser1);
            list.add(tUser2);
            list.add(tUser3);
    
            SqlParameterSource[] batch = SqlParameterSourceUtils.createBatch(list.toArray());
    
            template.batchUpdate("DELETE FROM T_USER WHERE ID = :id",batch);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    拓展连接:jdbcTemplate使用详解

  • 相关阅读:
    讲解 CSS 过渡和动画 — transition/animation (很全面)
    mapreduce序列化(Hadoop)
    okcc呼叫中心的的录音功能
    算法刷题第九天:广度优先搜索 / 深度优先搜索--3
    算法之数组篇
    STM32配置看门狗
    2022 lineCTF WEB复现WriteUp
    Go结构体&接口&反射
    使用Windbg排查线程死锁引起的连不上服务器问题
    Python3.10动态修改Windows系统(win10/win11)本地IP地址(静态IP)
  • 原文地址:https://blog.csdn.net/m0_58680865/article/details/126901687