一、什么是具名参数
在经典的 JDBC 用法中, SQL 参数是用占位符 ? 表示,并且受到位置的限制。定位参数的问题在于, 一旦参数的顺序发生变化, 就必须改变参数绑定。
在 Spring JDBC 框架中, 绑定 SQL 参数的另一种选择是使用具名参数(named parameter)。
具名参数只在 NamedParameterJdbcTemplate 中得到支持。
NamedParameterJdbcTemplate类拓展了JdbcTemplate类,可以使用全部jdbcTemplate方法。
NamedParameterJdbcTemplate主要提供以下三类方法:execute方法、query及queryForXXX方法、update及batchUpdate方法。
NamedParameterJdbcTemplate可以使用DataSource或JdbcTemplate 对象作为构造器参数初始化。
二、常用API传入参数类型介绍
NamedParameterJdbcTemplate类为命名参数设值有两种方式:java.util.Map 、RowMapper 和 SqlParameterSource。
1. Map
就是一个hash表,好处是可以根据参数名传参,paramMap.put("sqlparamName",value)。
2. RowMapper rowMapper
这个接口为了实现sql查询结果和对象间的转换,可以自己实现,也可以使用系统实现,主要实现类有:
- SingleColumnRowMapper ,sql结果为一个单列的数据,如List
, List ,String,Integer等 - BeanPropertyRowMapper, sql结果匹配到对象 List< XxxVO> , XxxVO
3. SqlParameterSource
其作用和Map一样,就是为sql中的条件参数赋值,默认实现有 :
- MapSqlParameterSource实现非常简单,只是封装了java.util.Map。
- BeanPropertySqlParameterSource封装了一个JavaBean对象,通过JavaBean对象属性来决定命名参数的值。
- EmptySqlParameterSource 一个空的SqlParameterSource ,常用来占位使用。
//BeanPropertySqlParameterSource传参方式 SqlParameterSource sps = new BeanPropertySqlParameterSource(javaBean); //MapSqlParameterSource传参方式 SqlParameterSource sps = new MapSqlParameterSource(); //保证参数名和key相同 sps.addValue("key",value);
三、API介绍
1. 查询
(1) 返回单行单列数据
public < T > T queryForObject(String sql, Map
public < T > T queryForObject(String sql, SqlParameterSource paramSource, Class
Integer count = template.queryForObject("select count(*) from student", new HashMap<>(), Integer.class); String name = template.queryForObject( "select name from student where home_address limit 1 ", EmptySqlParameterSource.INSTANCE, String.class);
(2) 返回 (多行)单列 数据
public < T> List< T> queryForList(String sql, Map
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);
(3) 返回单行数据
public < T> T queryForObject(String sql, Map< String, ?> paramMap, RowMapper< T>rowMapper)
public < T> T queryForObject(String sql, SqlParameterSource paramSource, RowMapper< T> rowMapper)
Student stu = template.queryForObject( "select * from student limit 1", new HashMap<>(), new BeanPropertyRowMapper(Student.class)); //BeanPropertyRowMapper会把下划线转化为驼峰属性 //结果对象可比实际返回字段多或者少
注意:这两个API也可以使用SingleColumnRowMapper返回单行单列数据
String name = template.queryForObject( "select name from student limit 1", EmptySqlParameterSource.INSTANCE, new SingleColumnRowMapper<>(String.class));
(4) 返回Map形式的单行数据
public Map< String, Object> queryForMap(String sql, Map< String, ?> paramMap)
public Map< String, Object> queryForMap(String sql, SqlParameterSource paramSource)
Map< String, Object> studentMap = template.queryForMap("select * from student limit 1", new HashMap<>());
public < T> List< T> query(String sql, Map< String, ?> paramMap, RowMapper< T> rowMapper) public < T> List< T> query(String sql, SqlParameterSource paramSource, RowMapper< T> rowMapper) public < T> List< T> query(String sql, RowMapper< T> rowMapper)
(5) 返回多行数据
public < T> List< T> query(String sql, Map< String, ?> paramMap, RowMapper< T> rowMapper)
public < T> List< T> query(String sql, SqlParameterSource paramSource, RowMapper< T> rowMapper)
public < T> List< T> query(String sql, RowMapper< T> rowMapper)
List< Student> studentList = template.query( "select * from student", new BeanPropertyRowMapper<>(Student.class) );
同理,也可以使用SingleColumnRowMapper返回单行列表List< String>,List< Integer>等。
(6) 返回多行数据(Map)
public List< Map< String, Object>> queryForList(String sql, Map< String, ?> paramMap)
public List< Map< String, Object>> queryForList(String sql, SqlParameterSource paramSource)
List
2. 插入/修改/删除数据,使用updateXXX方法
(1) 使用Map作为参数
int update(String sql, Map
MapparamMap = 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) 使用SqlParameterSource作为参数
int update(String sql, SqlParameterSource paramSource)
//使用 BeanPropertySqlParameterSource作为参数 StudentDTO dto=new StudentDTO();//这个DTO为传入数据 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)); //使用MapSqlParameterSource 作为参数 MapSqlParameterSource mapSqlParameterSource = new MapSqlParameterSource() .addValue("id", UUID.randomUUID().toString()) .addValue("name", "小王") .addValue("homeAddress", "美国"); template.update("insert into student(id,name,home_address) values (:id,:name,:homeAddress)",mapSqlParameterSource);
四、总结
- 开发中尽量使用NamedParameterJdbcTemplate代替JdbcTemplate,如果想使用JdbcTemplate,也可以通过NamedParameterJdbcTemplate#getJdbcOperations()获取
- 不建议使用查询结构为Map的API