Spring Boot数据持久化之NamedParameterJdbcTemplate

本文介绍了Spring Boot中使用NamedParameterJdbcTemplate进行数据持久化的操作,包括插入、更新、删除和查询。详细讲解了如何使用Map、BeanPropertySqlParameterSource、MapSqlParameterSource作为参数,并展示了不同类型的查询结果转换,如单行单列、多行单列、单行多列、多行多列数据,以及实体对象和对象列表的映射。最后强调了使用NamedParameterJdbcTemplate的优势和注意事项。

在Spring Boot项目中如果想使用NamedParameterJdbcTemplate,则需要在pom.xml文件中引入下述依赖:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-jdbc</artifactId>
	<version>2.5.5</version>
</dependency>

<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
	<version>5.1.47</version>
</dependency>

application.yml文件中数据库连接配置如下:

server:
  port: 9999
#数据库配置
spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/work?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai&useSSL=false
    username: xxx
    password: xxx
    driver-class-name: com.mysql.jdbc.Driver

数据库中user表的结构如下:

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `name` varchar(10) DEFAULT NULL COMMENT '姓名',
  `age` varchar(2) DEFAULT NULL COMMENT '年龄',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

表数据实体为:

import lombok.Data;

@Data
public class UserDto {

    private String id;
    private String name;
    private String age;
}

上述准备工作做完以后,接下来我们先来介绍一下NamedParameterJdbcTemplate相关的两个支持接口SqlParameterSourceRowMapper

SqlParameterSource接口的实现是用来作为命名参数设值,默认实现类有:

1.MapSqlParameterSource实现比较简单,只是封装了java.util.Map

2.BeanPropertySqlParameterSource封装了一个JavaBean对象,通过JavaBean对象属性来决定命名参数的值

3.EmptySqlParameterSource是一个空的SqlParameterSource ,常用来占位使用

RowMapper接口为了实现sql查询结果和对象间的转换,其主要实现类有:

1.SingleColumnRowMapper,sql结果为一个单列的数据

2.BeanPropertyRowMapper,sql结果匹配到对象

接下来我们就可以进行NamedParameterJdbcTemplate的使用测试,修改、插入和删除使用update方法:

1.使用Map作为参数进行插入操作

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;

import java.util.HashMap;
import java.util.Map;

@SpringBootTest
public class DemoTests {

    @Autowired
    private NamedParameterJdbcTemplate namedParameterJdbcTemplate;

    @Test
    public void test1(){
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("name", "孙七");
        paramMap.put("age", 20);
        namedParameterJdbcTemplate.update(
                "insert into user(name,age) values (:name,:age)",
                paramMap
        );
    }
}

2.使用Map作为参数进行修改操作

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;

import java.util.HashMap;
import java.util.Map;

@SpringBootTest
public class DemoTests {

    @Autowired
    private NamedParameterJdbcTemplate namedParameterJdbcTemplate;

    @Test
    public void test1(){
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("name", "孙七");
        paramMap.put("age", 19);
        namedParameterJdbcTemplate.update(
                "update user set name=:name,age=:age where id=1",
                paramMap
        );
    }
}

3.使用Map作为参数进行删除操作

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;

import java.util.HashMap;
import java.util.Map;

@SpringBootTest
public class DemoTests {

    @Autowired
    private NamedParameterJdbcTemplate namedParameterJdbcTemplate;

    @Test
    public void test1(){
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("name", "孙七");
        paramMap.put("age", 19);
        namedParameterJdbcTemplate.update(
                "delete from user where name=:name and age=:age",
                paramMap
        );
    }
}

4.使用BeanPropertySqlParameterSource作为参数进行插入操作

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;

@SpringBootTest
public class DemoTests {

    @Autowired
    private NamedParameterJdbcTemplate namedParameterJdbcTemplate;

    @Test
    public void test1(){
        UserDto dto=new UserDto();//这个DTO为传入数据
        dto.setName("周八");
        dto.setAge("20");
        namedParameterJdbcTemplate.update("insert into user(name,age) values (:name,:age)",
                new BeanPropertySqlParameterSource(dto));
    }
}

5.使用MapSqlParameterSource作为参数进行插入操作

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;

import java.util.HashMap;
import java.util.Map;

@SpringBootTest
public class DemoTests {

    @Autowired
    private NamedParameterJdbcTemplate namedParameterJdbcTemplate;

    @Test
    public void test1(){
        //第一种:直接使用MapSqlParameterSource作为参数
        //MapSqlParameterSource mapSqlParameterSource = new MapSqlParameterSource()
        //        .addValue("name", "吴九")
        //        .addValue("age", 22);
        //第二种:直接使用MapSqlParameterSource作为参数
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("name", "冯十");
        paramMap.put("age", 19);
        MapSqlParameterSource mapSqlParameterSource = new MapSqlParameterSource(paramMap);
        namedParameterJdbcTemplate.update("insert into user(name,age) values (:name,:age)",
                mapSqlParameterSource);
    }
}

 下面为使用NamedParameterJdbcTemplate进行的查询操作的示例

1.返回单行单列数据

特别提示此处EmptySqlParameterSource就是属于一个占位操作,没有任何意义

@Test
public void test1(){
    Integer count1 = namedParameterJdbcTemplate.queryForObject("select count(*) from user", new HashMap<>(), Integer.class);
    //单行单列
    Integer count2 = namedParameterJdbcTemplate.queryForObject( "select count(*) from user", EmptySqlParameterSource.INSTANCE, Integer.class);
    System.out.println(count1);
    System.out.println(count2);
}

执行上述代码,其输出结果为:

3
3

使用SingleColumnRowMapper返回单行单列数据:

@Test
public void test1(){
    String name = namedParameterJdbcTemplate.queryForObject(
            "select name from user limit 1", EmptySqlParameterSource.INSTANCE, new SingleColumnRowMapper<>(String.class));
    System.out.println(name);
}

执行上述代码,其输出结果为:

周八

2.返回多行单列数据

@Test
public void test1(){
    List<String> namelist = namedParameterJdbcTemplate.queryForList("select name from user", EmptySqlParameterSource.INSTANCE, String.class);
    System.out.println(namelist);
}

执行上述代码,其输出结果为:

[周八, 吴九, 冯十]

使用SingleColumnRowMapper也可以返回多行单列数据:

@Test
public void test1(){
    List<String> list = namedParameterJdbcTemplate.query("select name from user", EmptySqlParameterSource.INSTANCE,new SingleColumnRowMapper<>(String.class));
    System.out.println(list);
}

执行上述代码,其输出结果为:

[周八, 吴九, 冯十]

3.返回结果为单行多列

返回Map形式的单行数据

@Test
public void test1(){
    Map<String, Object> studentMap = namedParameterJdbcTemplate.queryForMap("select * from user limit 1", new HashMap<>());
    //Map<String, Object> studentMap = namedParameterJdbcTemplate.queryForMap("select * from user limit 1", EmptySqlParameterSource.INSTANCE);
    System.out.println(studentMap);
}

执行上述代码,其输出结果:

{id=2, name=周八, age=20}

4.返回结果为多行多列

返回Map形式的多行多列数据

@Test
public void test1(){
    // 返回多行数据(Map)
     List<Map<String, Object>> mapList = namedParameterJdbcTemplate.queryForList(
            "select * from user ", new HashMap<>());
    //List<Map<String, Object>> mapList = namedParameterJdbcTemplate.queryForList(
    //        "select * from user ", EmptySqlParameterSource.INSTANCE);
    System.out.println(mapList);
}

 执行上述代码,其输出结果为:

[{id=2, name=周八, age=20}, {id=3, name=吴九, age=22}, {id=4, name=冯十, age=19}]

5.返回结果为一个实体对象

@Test
public void test1(){
     UserDto userDto = namedParameterJdbcTemplate.queryForObject("select * from user limit 1",EmptySqlParameterSource.INSTANCE,new BeanPropertyRowMapper<>(UserDto.class));
     System.out.println(userDto);
}

执行上述代码,其输出结果为:

UserDto(id=2, name=周八, age=20)

6.返回结果为一个实体对象列表

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.namedparam.EmptySqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;

import java.util.HashMap;
import java.util.List;


@SpringBootTest
public class DemoTests {

    @Autowired
    private NamedParameterJdbcTemplate namedParameterJdbcTemplate;

    @Test
    public void test1(){
        // 返回多行数据
        //List<UserDto> list = namedParameterJdbcTemplate.query("select * from user", new BeanPropertyRowMapper<>(UserDto.class));
        //List<UserDto> list = namedParameterJdbcTemplate.query("select * from user", new HashMap<>(),new BeanPropertyRowMapper<>(UserDto.class));
        List<UserDto> list = namedParameterJdbcTemplate.query("select * from user", EmptySqlParameterSource.INSTANCE,new BeanPropertyRowMapper<>(UserDto.class));
        System.out.println(list);
    }
}

执行上述代码,其输出结果为:

[UserDto(id=2, name=周八, age=20), UserDto(id=3, name=吴九, age=22), UserDto(id=4, name=冯十, age=19)]

总结:

1.开发中尽量使用NamedParameterJdbcTemplate代替JdbcTemplate,如果想使用JdbcTemplate,也可以通过NamedParameterJdbcTemplate#getJdbcOperations()获取

List<Map<String, Object>> list = namedParameterJdbcTemplate.getJdbcOperations().queryForList("select * from user");
System.out.println(list);

执行上述代码,其输出结果为:

[{id=2, name=周八, age=20}, {id=3, name=吴九, age=22}, {id=4, name=冯十, age=19}]

2.不建议使用查询结果为Map的API

3.NamedParameterJdbcTemplate类拓展了JdbcTemplate类,对JdbcTemplate类进行了封装从而支持命名参数特性。NamedParameterJdbcTemplate主要提供以下三类方法:query、queryForXXX方法、update方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值