此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Framework 6.2.0spring-doc.cadn.net.cn

将 JDBC作建模为 Java 对象

org.springframework.jdbc.objectpackage 包含允许您访问 数据库。例如,您可以运行查询 并将结果作为列表返回,其中包含具有关系 映射到业务对象属性的列数据。您也可以运行 stored 过程并运行 Update、Delete 和 Insert 语句。spring-doc.cadn.net.cn

许多 Spring 开发人员认为,下面描述的各种 RDBMS作类 (除了StoredProcedure类)可以经常 替换为 StraightJdbcTemplate调用。通常,编写 DAO 更简单 方法,该方法在JdbcTemplate直接(而不是 将查询封装为完整的类)。spring-doc.cadn.net.cn

但是,如果您通过使用 RDBMS作类获得可衡量的值, 您应该继续使用这些类。spring-doc.cadn.net.cn

理解SqlQuery

SqlQuery是封装 SQL 查询的可重用、线程安全的类。子 必须实现newRowMapper(..)方法提供RowMapper实例,该实例可以 通过迭代ResultSet即创建 在执行查询期间。这SqlQuery类很少直接使用,因为 这MappingSqlQuerysubclass 为 将行映射到 Java 类。扩展的其他实现SqlQueryMappingSqlQueryWithParametersUpdatableSqlQuery.spring-doc.cadn.net.cn

MappingSqlQuery

MappingSqlQuery是一个可重用的查询,其中具体子类必须实现 抽象mapRow(..)方法将提供的每一行ResultSet转换为 object 指定类型。以下示例显示了一个自定义查询,该查询将 数据来自t_actorActor类:spring-doc.cadn.net.cn

public class ActorMappingQuery extends MappingSqlQuery<Actor> {

	public ActorMappingQuery(DataSource ds) {
		super(ds, "select id, first_name, last_name from t_actor where id = ?");
		declareParameter(new SqlParameter("id", Types.INTEGER));
		compile();
	}

	@Override
	protected Actor mapRow(ResultSet rs, int rowNumber) throws SQLException {
		Actor actor = new Actor();
		actor.setId(rs.getLong("id"));
		actor.setFirstName(rs.getString("first_name"));
		actor.setLastName(rs.getString("last_name"));
		return actor;
	}
}

该类扩展了MappingSqlQuery参数化为Actor类型。构造函数 对于此 Customer 查询,需要一个DataSource作为唯一的参数。在这个 构造函数,您可以使用DataSource和 SQL 应该运行该 API 以检索此查询的行。此 SQL 用于 创建一个PreparedStatement,因此它可以包含任何参数的占位符 在执行期间传入。您必须使用declareParameter方法传入SqlParameter.这SqlParameter采用 name,JDBC 类型 如java.sql.Types.定义所有参数后,您可以调用compile()方法,以便可以准备语句并在以后运行。这个类是 线程安全的,因此,只要这些实例是在 DAO 初始化后,它们可以作为实例变量保留并重复使用。以下内容 example 演示如何定义此类:spring-doc.cadn.net.cn

private ActorMappingQuery actorMappingQuery;

@Autowired
public void setDataSource(DataSource dataSource) {
	this.actorMappingQuery = new ActorMappingQuery(dataSource);
}

public Actor getActor(Long id) {
	return actorMappingQuery.findObject(id);
}

前面示例中的方法检索具有id作为 only 参数。由于我们只想返回一个对象,因此我们将findObject方便 方法与id作为参数。如果我们有一个返回 list 对象并获取额外的参数,我们将使用execute方法,该方法接受作为 vararg 传入的参数值数组。以下内容 example 显示了这样的方法:spring-doc.cadn.net.cn

public List<Actor> searchForActors(int age, String namePattern) {
	return actorSearchMappingQuery.execute(age, namePattern);
}

SqlUpdate

SqlUpdateclass 封装 SQL 更新。与查询一样,更新对象是 可重复使用,并且与所有RdbmsOperation类,则 Update 可以有参数,并且是 在 SQL 中定义。此类提供了许多update(..)方法类似于execute(..)查询对象的方法。这SqlUpdateclass 是具体的。可以是 subclassed — 例如,添加自定义更新方法。 但是,您不必将SqlUpdate类,因为它可以通过设置 SQL 和声明参数来轻松参数化。 以下示例创建一个名为execute:spring-doc.cadn.net.cn

import java.sql.Types;
import javax.sql.DataSource;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.object.SqlUpdate;

public class UpdateCreditRating extends SqlUpdate {

	public UpdateCreditRating(DataSource ds) {
		setDataSource(ds);
		setSql("update customer set credit_rating = ? where id = ?");
		declareParameter(new SqlParameter("creditRating", Types.NUMERIC));
		declareParameter(new SqlParameter("id", Types.NUMERIC));
		compile();
	}

	/**
	 * @param id for the Customer to be updated
	 * @param rating the new value for credit rating
	 * @return number of rows updated
	 */
	public int execute(int id, int rating) {
		return update(rating, id);
	}
}

StoredProcedure

StoredProcedureclass 是一个abstractRDBMS 对象抽象的超类 存储过程。spring-doc.cadn.net.cn

继承的sqlproperty 是 RDBMS 中存储过程的名称。spring-doc.cadn.net.cn

要为StoredProcedure类中,您可以使用SqlParameter或一个 的子类。您必须在构造函数中指定参数名称和 SQL 类型。 如下面的代码片段所示:spring-doc.cadn.net.cn

new SqlParameter("in_id", Types.NUMERIC),
new SqlOutParameter("out_first_name", Types.VARCHAR),

SQL 类型是使用java.sql.Types常数。spring-doc.cadn.net.cn

第一行(带有SqlParameter) 声明 IN 参数。您可以使用 IN 参数 对于存储过程调用和使用SqlQuery及其 子类(包括理解SqlQuery).spring-doc.cadn.net.cn

第二行(带有SqlOutParameter) 声明out参数,以便在 stored procedure 调用。还有一个SqlInOutParameterInOut参数 (提供invalue 添加到过程,并且还返回一个值)。spring-doc.cadn.net.cn

in参数,除了名称和 SQL 类型之外,您还可以指定 数字数据的 scale 或自定义数据库类型的 type name。为out参数 您可以提供RowMapper要处理从REF光标。 另一个选项是指定SqlReturnType,允许您定义自定义 返回值的处理。spring-doc.cadn.net.cn

简单 DAO 的下一个示例使用StoredProcedure调用函数 (sysdate()),它包含在任何 Oracle 数据库中。使用存储过程 功能,您必须创建一个扩展StoredProcedure.在这个 示例中,StoredProcedureclass 是一个内部类。但是,如果您需要重用StoredProcedure,则可以将其声明为 top level 类。此示例没有输入 参数,但输出参数使用SqlOutParameter类。这execute()方法运行该过程并提取 从结果返回的日期Map.结果Map为每个声明的 output 参数(在本例中,只有一个)使用参数名称作为键。 下面的清单显示了我们的自定义 StoredProcedure 类:spring-doc.cadn.net.cn

import java.sql.Types;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.SqlOutParameter;
import org.springframework.jdbc.object.StoredProcedure;

public class StoredProcedureDao {

	private GetSysdateProcedure getSysdate;

	@Autowired
	public void init(DataSource dataSource) {
		this.getSysdate = new GetSysdateProcedure(dataSource);
	}

	public Date getSysdate() {
		return getSysdate.execute();
	}

	private class GetSysdateProcedure extends StoredProcedure {

		private static final String SQL = "sysdate";

		public GetSysdateProcedure(DataSource dataSource) {
			setDataSource(dataSource);
			setFunction(true);
			setSql(SQL);
			declareParameter(new SqlOutParameter("date", Types.DATE));
			compile();
		}

		public Date execute() {
			// the 'sysdate' sproc has no input parameters, so an empty Map is supplied...
			Map<String, Object> results = execute(new HashMap<String, Object>());
			Date sysdate = (Date) results.get("date");
			return sysdate;
		}
	}

}

以下示例StoredProcedure有两个输出参数(在本例中为 Oracle REF cursors):spring-doc.cadn.net.cn

import java.util.HashMap;
import java.util.Map;
import javax.sql.DataSource;
import oracle.jdbc.OracleTypes;
import org.springframework.jdbc.core.SqlOutParameter;
import org.springframework.jdbc.object.StoredProcedure;

public class TitlesAndGenresStoredProcedure extends StoredProcedure {

	private static final String SPROC_NAME = "AllTitlesAndGenres";

	public TitlesAndGenresStoredProcedure(DataSource dataSource) {
		super(dataSource, SPROC_NAME);
		declareParameter(new SqlOutParameter("titles", OracleTypes.CURSOR, new TitleMapper()));
		declareParameter(new SqlOutParameter("genres", OracleTypes.CURSOR, new GenreMapper()));
		compile();
	}

	public Map<String, Object> execute() {
		// again, this sproc has no input parameters, so an empty Map is supplied
		return super.execute(new HashMap<String, Object>());
	}
}

请注意declareParameter(..)方法 用于TitlesAndGenresStoredProcedureconstructor 的RowMapperimplementation 实例。这是一种非常方便和强大的重用现有 功能性。接下来的两个示例提供了这两个RowMapper实现。spring-doc.cadn.net.cn

TitleMapper类映射一个ResultSet更改为Titledomain 对象 提供的ResultSet如下:spring-doc.cadn.net.cn

import java.sql.ResultSet;
import java.sql.SQLException;
import com.foo.domain.Title;
import org.springframework.jdbc.core.RowMapper;

public final class TitleMapper implements RowMapper<Title> {

	public Title mapRow(ResultSet rs, int rowNum) throws SQLException {
		Title title = new Title();
		title.setId(rs.getLong("id"));
		title.setName(rs.getString("name"));
		return title;
	}
}

GenreMapper类映射一个ResultSet更改为Genredomain 对象 提供的ResultSet如下:spring-doc.cadn.net.cn

import java.sql.ResultSet;
import java.sql.SQLException;
import com.foo.domain.Genre;
import org.springframework.jdbc.core.RowMapper;

public final class GenreMapper implements RowMapper<Genre> {

	public Genre mapRow(ResultSet rs, int rowNum) throws SQLException {
		return new Genre(rs.getString("name"));
	}
}

将参数传递给其 定义,您可以编写一个强类型的execute(..)方法,该 委托给 untypedexecute(Map)方法,如下例所示:spring-doc.cadn.net.cn

import java.sql.Types;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.sql.DataSource;
import oracle.jdbc.OracleTypes;
import org.springframework.jdbc.core.SqlOutParameter;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.object.StoredProcedure;

public class TitlesAfterDateStoredProcedure extends StoredProcedure {

	private static final String SPROC_NAME = "TitlesAfterDate";
	private static final String CUTOFF_DATE_PARAM = "cutoffDate";

	public TitlesAfterDateStoredProcedure(DataSource dataSource) {
		super(dataSource, SPROC_NAME);
		declareParameter(new SqlParameter(CUTOFF_DATE_PARAM, Types.DATE);
		declareParameter(new SqlOutParameter("titles", OracleTypes.CURSOR, new TitleMapper()));
		compile();
	}

	public Map<String, Object> execute(Date cutoffDate) {
		Map<String, Object> inputs = new HashMap<String, Object>();
		inputs.put(CUTOFF_DATE_PARAM, cutoffDate);
		return super.execute(inputs);
	}
}

APP信息