Spring Boot JDBC 参数别名 SQL(NamedParameterJdbcTemplate)

Posted catoop

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Boot JDBC 参数别名 SQL(NamedParameterJdbcTemplate)相关的知识,希望对你有一定的参考价值。

在 SpringBoot 中基本的 jdbc 连接操作数据库,可以详见《Spring Boot JDBC 连接数据库》 ,本文简述在 SQL 中使用别名参数。

上文我们使用 JdbcTemplate 来操作数据库SQL,在 SQL 语句中传递参数使用 ?号占位代替,这样就要求我们参数集合和问号个数及顺序必须保持一致。

除此之外,Spring 还提供了另外一种可以为参数定义别名来为 SQL 提供参数的方式,就是使用 NamedParameterJdbcTemplate 类取代 JdbcTemplate 来操作 SQL,使用方法如下文所述。

使用

pom 依赖依旧是 spring-boot-starter-jdbc

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

Java 测试用例代码如下:

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.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.util.Assert;

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

@SpringBootTest
class Demo1SpringJdbcApplicationTests 

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Autowired
    private NamedParameterJdbcTemplate namedParameterJdbcTemplate;

    @Test
    void contextLoads() 
        Map<String, Object> resMap1 = jdbcTemplate.queryForMap("select * from config_info where id = ?",
                new Object[]"1");

        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("id", "1");
        Map<String, Object> resMap2 = namedParameterJdbcTemplate.queryForMap(
                "select * from config_info where id = :id", paramMap);

        Assert.isTrue(resMap1.get("id").equals(resMap2.get("id")), "Fail");
    


spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=test123

总结就是添加相关依赖,然后配置 properties 文件的数据源,最后直接注入 NamedParameterJdbcTemplate 就可以使用了。


如果是某项目使用的原生 Spring 框架,没有使用 springboot 自动配置,在尝试直接注入 NamedParameterJdbcTemplate 时发现 spring 容器中没有该类对象时。则可以通过自行构造对象的方法来实例化对象,可以使用 dataSource 参数和 jdbcTemplate 参数构造 NamedParameterJdbcTemplate 对象。

代码如下示例:

    @Bean
    @ConditionalOnMissingBean
    public NamedParameterJdbcTemplate crateNamedParameterJdbcTemplate(DataSource dataSource)
        return new NamedParameterJdbcTemplate(dataSource);
    

或者

    @Bean
    @ConditionalOnMissingBean
    public NamedParameterJdbcTemplate crateNamedParameterJdbcTemplate(JdbcTemplate jdbcTemplate)
        return new NamedParameterJdbcTemplate(jdbcTemplate);
    

然后就可以注入 NamedParameterJdbcTemplate 使用了。

这种在SQL中使用别名的方式,对参数的顺序和个数就没有这么严格的要求了,你只需要保证你SQL中使用的所有别名在参数Map中一定存在即可,参数Map中的内容可以多于SQL中变量的实际需求。

关于SQL IN 条件

对于 SQL 条件有 IN 的语句,NamedParameterJdbcTemplate 的支持要比问号方式友好的多,问号参数方式在遇到 in 条件时,需要 append 很多问号,然后参数也要对应上,in 的个数越多看起来越崩溃。

NamedParameterJdbcTemplate 把条件中的 IN 看做是一个完整的变量,直接又通透,如下代码示例:

    @Autowired
    private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
    
	@Override
	public List<ConfigInfo> selectItemByIds(String itemIds) 
		Map<String,Object> paramMap = new HashMap<String, Object>();
		try 
			String sql = "SELECT * FROM config_info WHERE id IN(:itemIds)";
			paramMap.put("itemIds", Arrays.asList(itemIds.split(",")));
			return namedParameterJdbcTemplate.query(sql,paramMap, new BeanPropertyRowMapper<ConfigInfo>(ConfigInfo.class));
		 catch (DataAccessException e) 
			return null;
		
	

(ENG)

以上是关于Spring Boot JDBC 参数别名 SQL(NamedParameterJdbcTemplate)的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Spring Boot 项目中使用 Log4jdbc 记录 SQL 查询、它们的参数和结果?

spring boot: spring boot+jdbctemplate+sql server

Spring Boot Mybatis使用

Spring Boot Mybatis使用

Spring Boot Mybatis使用

记一次Spring Boot 配置多ElasticSearch-sql 数据源,按照参数动态切换