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());

使用这三种接口的差异以下:

相关文章
相关标签/搜索