原文地址http://www.voidcn.com/article/p-cwqegtpg-hx.html
在使用JdbcTemplate時,一般傳參都是用的?來綁定參數,但是對於某種情況就不適用了,例如Sql中如果存在IN,那么寫SQL的時候就會比較麻煩,例如,咱們要查ID在某個范圍內的數據,一般情況下咱們這么寫:
List<String> ids = new ArrayList<String>(); ids.add("id1"); ids.add("id2"); ids.add("id3"); String sql = "SELECT * FROM TEST WHERE ID IN("; for(int i = 0; i<ids.size();i++){ sql+="?"; if(i!=ids.size()){ sql+=","; } } sql+=")"; List result = getJdbcTemplate.queryForList(sql, ids.toArray());
這里需要提到的類就是NamedParameterJdbcTemplate,他是Spring給開發者提供的一個基於JdbcTemplate的類,他支持命名參數特性。包含了JdbcTemplate中的大部分方法,主要有三類:execute方法、query及queryForXXX方法、update及batchUpdate方法。
咱們可以看一個由NamedParameterJdbcTemplate完成的上述例子:
List<String> ids = new ArrayList<String>(); ids.add("id1"); ids.add("id2"); ids.add("id3"); String sql = "SELECT * FROM TEST WHERE ID IN(:ids)"; Map params = new HashMap(); params.addValue("ids", ids); NamedParameterJdbcTemplate jdbcTemplate = null; jdbcTemplate = new NamedParameterJdbcTemplate(getJdbcTemplate()); List reslut = jdbcTemplate.query(sql, params);
可以看到Sql中的參數可以用 :[name] 的方式書寫,在執行之前,所有的參數可以放在一個Map中,key為Sql中的參數名,這樣的話,就簡化了咱們自己拼寫Sql的工作量。
其實,這只是NamedParameterJdbcTemplate的好處之一,另一個好處就是,對於同一個參數,多次出現在一條sql中時,也很好處理。
例如咱們要查一個數據,傳入的時間參數要在字段F1和字段F2之間。那么可以這么寫:
String sql = "SELECT * FROM TEST WHERE F1>:time and F2<:time"; Map params = new HashMap(); params.addValue("time", new Date()); NamedParameterJdbcTemplate jdbcTemplate = null; jdbcTemplate = new NamedParameterJdbcTemplate(getJdbcTemplate()); List reslut = jdbcTemplate.query(sql, params);
上面咱們利用NamedParameterJdbcTemplate查詢時,是將所有參數放入到了一個Map中,其實NamedParameterJdbcTemplate為咱們提供的參數模型不止Map。還有SqlParameterSource和BeanPropertySqlParameterSource。
其中SqlParameterSource和咱們用Map一樣,他只是對Map進行了封裝。
而BeanPropertySqlParameterSource封裝了一個JavaBean對象,通過JavaBean對象屬性來決定命名參數的值。
例如咱們創建了一個Bean。
public class User { private int id; private String userName; private String password; //省略getter和setter }
現在驗證一個登錄信息是否正確:
public boolean login(String userName,String password){ NamedParameterJdbcTemplate namedParameterJdbcTemplate = null; namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(getJdbcTemplate()); User user = new User(); model.setUserName("jialeens"); model.setPassword("hehe"); String sql = "SELECT COUNT(1) FROM USER WHERE USERNAME=:userName AND PASSWORD=:password"; SqlParameterSource paramSource = new BeanPropertySqlParameterSource(user); int size = namedParameterJdbcTemplate.queryForInt(sql, paramSource); return size==1; }
可以看到,傳入的參數是一個對象Bean,Sql在執行時,會根據Sql中的參數名去獲取對應Bean中的屬性。
NamedParameterJdbcTemplate內部包含了一個JdbcTemplate,所以JdbcTemplate能做的事情NamedParameterJdbcTemplate都能干; NamedParameterJdbcTemplate相對於JdbcTemplate主要增加了參數可以命名的功能。
public Object queryForObject(String sql, Map paramMap, RowMapper rowMapper)
public Object queryForObject(String sql, SqlParameterSource paramSource, RowMapper rowMapper)
SqlParameterSource的兩個主要實現MapSqlParameterSource
和BeanPropertySqlParameterSource
public int update(String sql, SqlParameterSource paramSource, KeyHolder generatedKeyHolder)保存數據獲得主鍵。
public class NamedJdbcTemplate { // JdbcTemplate是線程安全的 static JdbcTemplate jdbc = new JdbcTemplate(JdbcUtils.getDataSource()); static NamedParameterJdbcTemplate named = new NamedParameterJdbcTemplate( JdbcUtils.getDataSource()); public static void main(String[] args) { User user=new User(); user.setMoney(10); user.setId(2); // System.out.println(findUser(user)); System.out.println(findUser1(user)); } static void addUser(User user){ String sql = "insert into user(name,birthday, money) values (:name,:birthday,:money) ";//:后的命名要與列名一致 SqlParameterSource ps=new BeanPropertySqlParameterSource(user);//從user中取出數據,與sql語句中一一對應將數據換進去 KeyHolder keyHolder=new GeneratedKeyHolder(); named.update(sql, ps, keyHolder); int id=keyHolder.getKey().intValue();//獲得主鍵 user.setId(id); //Map map=keyholder.getKeys();//這樣可以得到聯合主鍵的值 //keyholder.getKeyList();//這樣可以得到一些主主鍵值,若一次添加好幾條記錄 } static User findUser1(User user) { String sql = "select id, name, money, birthday from user where money>:money and id<:id"; SqlParameterSource ps=new BeanPropertySqlParameterSource(user); Object u=named.queryForObject(sql, ps, new BeanPropertyRowMapper(User.class)); return (User) u; } static User findUser(User user) { String sql = "select id, name, money, birthday from user where money>:m and id<:id"; Object[] args = new Object[] {user.getName(),user.getMoney(),user.getId() }; Map params=new HashMap(); params.put("m", user.getMoney()); params.put("id", user.getId()); Object u=named.queryForObject(sql, params, new BeanPropertyRowMapper(User.class)); return (User) u; }