Spring JDBC最佳實踐(3)

spring jdbc包提供了JdbcTemplate和它的兩個兄弟SimpleJdbcTemplate和NamedParameterJdbcTemplate,咱們能夠先從JdbcTemplate入手,領略一下這個類的便利和優雅。
一、使用JdbcTemplate進行數據訪問:
初始化JdbcTemplate
初始化JdbcTemplate很容易,只須要向它的構造方法傳入它所使用的DataSource即可以。若是使用Jakarta Commons DBCP,那麼初始化代碼以下所示:
BasicDataSource dataSource = new BasicDataSource();
		dataSource.setDriverClassName("com.mysql.jdbc.Driver");
		dataSource.setUrl("jdbc:mysql://localhost/mysql?characterEncoding=gb2312");
		dataSource.setUsername("***");
		dataSource.setPassword("***");
		JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);

也能夠經過無參的構造方法構造JdbcTemplate,而後經過setDataSource(DataSource dataSource)來設置其dataSource。
上述這種方法是經過編碼的方式構造JdbcTemplate,若是應用程序使用spring的IOC容器,其初始化工做即可移植到容器的配置文件當中:
java

<!-- dataSource -->
	<bean id="dataSource"
		class="org.apache.commons.dbcp.BasicDataSource"
		destroy-method="close">
		
		<property name="driverClassName">
			<value>com.mysql.jdbc.Driver</value>
		</property>
		<property name="url" value="jdbc:mysql://localhost:3306/oa?characterEncoding=gb2312" />
		<property name="username" value="root" />
		<property name="password" value="root" />
		<property name="maxActive" value="100" />
		<property name="maxIdle" value="30" />
		<property name="maxWait" value="1000" />
		<property name="defaultAutoCommit" value="true" />
		<property name="removeAbandoned" value="true" />
	</bean>
	<!-- jdbcTemplate -->
	<bean id="jdbc"
		class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource">
			<ref bean="dataSource" />
		</property>
	</bean>

以後,想把jdbcTemplate注入到哪一個bean均可以,初始化好了JdbcTemplate之後,即可以大施拳腳了!

使用JdbcTemplate查詢數據:
JdbcTemplate針對數據查詢提供了多個重載的模板方法,咱們能夠根據須要選用不一樣的模板方法。若是查詢很簡單,僅僅是傳入相應的SQL或者是相關的參數,而後取得一個結果,那麼咱們能夠用以下的一組便利的模板方法:
mysql

public int queryForInt(String sql)

public int queryForInt(String sql, Object[] args)

public int queryForInt(String sql, Object[] args)

public long queryForLong(String sql)

public long queryForLong(String sql, Object[] args)

public long queryForLong(String sql, Object[] args, int[] argTypes)

public Object queryForObject(String sql, Class requiredType)

public Object queryForObject(String sql, Object[] args, int[] argTypes, Class requiredType)

public Object queryForObject(String sql, Object[] args, int[] argTypes, RowMapper rowMapper)

public Object queryForObject(String sql, Object[] args, Class requiredType)

public Object queryForObject(String sql, Object[] args, RowMapper rowMapper)

public Object queryForObject(String sql, RowMapper rowMapper)

注意:這些針對的resultset返回的必須是一行記錄,不然會出錯!
 若是查詢的結果包含一列數字型的結果,或者使用了SQL函數,或者其它的單列的結果,那麼即可以直接經過這組便利的模板方法進行查詢:
int postId = jdbcTemplate.queryForInt("SELECT POSTID FROM USERS WHERE USERNAME=?",new String[]{"jason"});
		System.out.println(postId);
		long userCount = jdbcTemplate.queryForLong("SELECT COUNT(*) FROM USERS");
		System.out.println(userCount);
		String nickname = (String)jdbcTemplate.queryForObject("SELECT USERNAME1 FROM USERS WHERE USERNAME='jason'", String.class);
		System.out.println(nickname);
		Map singleUser = jdbcTemplate.queryForMap("SELECT * FROM USERS WHERE USERNAME = 'jason'");
		System.out.println(singleUser);

queryForMap與其它的方法的不一樣之處在於它的查詢的結果以java.util.Map的形式返回,Map的鍵對應查詢的表的列的名字,Map的值對應鍵所在的列的值。 spring

若是查詢的結果返回多行,而咱們又不在意他們是否擁有較強的約束類型,那麼能夠用如下的模板方法:sql

public List queryForList(String sql)

public List queryForList(String sql, Object[] args)
public List queryForList(String sql, Object[] args, int[] argTypes)

queryForList()方法根據傳入的sql以及相應的參數執行查詢,將查詢的結果以java.util.List的形式返回,返回的java.util.List中的每一個元素都是java.lang.Map類型,分別對應結果集中的一行,Map的鍵對應每列的列名,Map的值對應當前列名對應的值.apache

若是這些還不足以知足咱們的須要,那麼咱們能夠本身定義回調接口
用於查詢的回調接口有如下三種:
org.springframework.jdbc.core.ResultSetExtractor,它是屬於JdbcTemplate內部使用的Callback接口,相對於下面的兩個接口,這個接口擁有更多的控制權,由於在使用它的時候,咱們須要自行的處理ResultSet,該接口的定義以下:
app

package org.springframework.jdbc.core;

import java.sql.ResultSet;
import java.sql.SQLException;

import org.springframework.dao.DataAccessException;

public interface ResultSetExtractor {

	
	Object extractData(ResultSet rs) throws SQLException, DataAccessException;

}

咱們能夠將處理的結果以任意的形式包裝後返回

org.springframework.jdbc.core.RowCallbackHandler 相對於ResultSetExtractor,它只關注單行結果的處理,處理的結果能夠根據須要存放在當前的RowCallbackHandler,或者使用JdbcTemplate中,固然,這徹底看我的喜愛,接口定義以下:
ide

package org.springframework.jdbc.core;

import java.sql.ResultSet;
import java.sql.SQLException;

public interface RowCallbackHandler {

	void processRow(ResultSet rs) throws SQLException;

} 

org.springframework.jdbc.core.RowMapper  它是 ResultSetExtractor的精簡版,功能相似於 RowCallbackHandler,也是隻關注當行結果的處理。不過它的返回的結果會有 ResultSetExtractor實現類進行組合。RowMapper的接口定義以下:
package org.springframework.jdbc.core;

import java.sql.ResultSet;
import java.sql.SQLException;

public interface RowMapper {

     Object mapRow(ResultSet rs, int rowNum) throws SQLException; 

}

爲了說明這三種回調接口的使用方法,咱們暫時設置以下的場景: 假設咱們有一表users,裏面有userid,username,userpwd三個字段,咱們爲此創建了一個JavaBean:函數

package com.google.spring.jdbc;

public class UserBean
{
	private Integer userId;
	private String username;
	private String userpwd;
	public Integer getUserId()
	{
		return userId;
	}
	public void setUserId(Integer userId)
	{
		this.userId = userId;
	}
	public String getUsername()
	{
		return username;
	}
	public void setUsername(String username)
	{
		this.username = username;
	}
	public String getUserpwd()
	{
		return userpwd;
	}
	public void setUserpwd(String userpwd)
	{
		this.userpwd = userpwd;
	}
	
}

使用自定義的ResultSetExtractor,能夠以下進行處理:post

List users = (List)jdbcTemplate.query("SELECT * FROM USERS WHERE USERNAME LIKE '%n%'", new ResultSetExtractor()
		{
			
			@Override
			public Object extractData(ResultSet rs) throws SQLException,
					DataAccessException
			{
				List users = new ArrayList();
				while(rs.next())
				{
					UserBean userBean = new UserBean();
					userBean.setUserId(rs.getInt("userId"));
					userBean.setUsername(rs.getString("username"));
					userBean.setUserpwd(rs.getString("userpwd"));
					users.add(userBean);
				}
				return users;
			}
		});
		System.out.println(users);

使用RowMapper,可進行以下的處理:ui

List users = jdbcTemplate.query("SELECT * FROM USERS WHERE USERNAME LIKE '%n%'", new RowMapper()
		{
			
			@Override
			public Object mapRow(ResultSet rs, int rowNum) throws SQLException
			{
				UserBean userBean = new UserBean();
				userBean.setUserId(rs.getInt("userId"));
				userBean.setUsername(rs.getString("username"));
				userBean.setUserpwd(rs.getString("userpwd"));
				return userBean;
			}
		});
		System.out.println(users.size());

使用RowCallbackHandler可進行以下的處理:

final List users = new ArrayList();
		jdbcTemplate.query("SELECT * FROM USERS WHERE USERNAME LIKE '%n%'", new RowCallbackHandler()
		{
			
			@Override
			public void processRow(ResultSet rs) throws SQLException
			{
				UserBean userBean = new UserBean();
				userBean.setUserId(rs.getInt("userId"));
				userBean.setUsername(rs.getString("username"));
				userBean.setUserpwd(rs.getString("userpwd"));
				users.add(userBean);
			}
		});
		System.out.println(users.size());

使用這三種接口的差異以下:

相關文章
相關標籤/搜索