博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring学习进阶(四) Spring JDBC
阅读量:7077 次
发布时间:2019-06-28

本文共 21661 字,大约阅读时间需要 72 分钟。

Spring JDBC是Spring所提供的持久层技术。主要目的是降低使用JDBC API的门槛,以一种更直接,更简洁的方式使用JDBC API。在Spring JDBC里用户仅需要做哪些比不可少的事,而将资源获取,Statement创建,异常处理,资源释放等繁杂而乏味的工作交交给Spring. 一、使用Spring JDBC 使用JDBC编写数据库的时候,由于JDBC API过于底层,开发者不但需要编写数据操作代码,还需要编写获得JDBC连接、异常处理、释放资源等。而Spring JDBC通过模板和回调机制大大降低了使用JDBC的复杂度,借助JdbcTemplate用户只需要编写实际操作的代码就可以了、 1、使用JdbcTemplate创建一张表 DriverManagerDataSource ds=new DriverManagerDataSource(); //创建数据源 ds.setDriverClassName(com.mysql.jdbc.Driver); ds.setUrl("jdbc://localhost:3309/sampledb"); ds.setUsername("root"); ds.setPassword("1234"); JdbcTemplate jdbcTemplate=new JdbcTemplate();//生成一个JdbcTemplate的实例 jdbc.setDataSource(ds); String sql="create table t_user(user_id int primary key,user_name varchar(60))";//创建一张表 jdbcTemplate.execute(sql); 在上述中,使用DriverManagerDataSource创建一个数据源,紧接着,创建了一个JdbcTemplate对象,然后使用该对象执行SQL语句。JdbcTemplate是线程安全的所有的DAO都共享一个JdbcTemplate实例。因此上述中创建数据源和生成JdbcTemplate都可以在Spring配置文件中统一定义了。 2、在DAO中使用JdbcTemplate @Repository public class  ViewSpaceDao {
@Autowired private JdbcTemplate jdbcTemplate; public void initDb() {
String sql = "create table t_user(user_id int primary key,user_name varchar(60))"; jdbcTemplate.execute(sql); }} 在Spring配置文件中定义JdbcTemplate并注入每个DAO中。
在Spring配置文件中配置DAO一般分为4个步骤: 1)定义DataSource 2)定义JdbcTemplate 3)声明一个抽象的Bean,以便所有DAO复用配置JdbcTemplate属性的配置 4)配置具体的DAO 实战经验: Spring几乎为所有的模板类都提供相应的支持类,与JdbcTemplate对应的支持类为JdbcDaoSupport.JdbcDaoSupport内部定义了JdbcTemplate的成员变量,开发者可以通过扩展JdbcDaoSupport定义自己的Dao,但是随着Bean的注解配置逐渐成为主流配置方式。这种方法便不再可用,因为直接继承JdbcDaoSupport无法对JdbcTemplate成员变量应用@Autowired注解,所以,一般是自己定义一个BaseDao,在BaseDao中定义JdbcTemplate成员变量,并使用@Autowired注解。还会在BaseDao中定义一些通用的功能,如声明JdbcTemplate,分页查询等、 二、基本的数据操作 数据库的增删改查以及存储过程调用时最基本的数据库操作,JdbcTemplate提供了众多的方法,通过JdbcTemplate用户可以用最简单的方法完成这些数据操作。 1、更改数据 JdbcTemplate提供了若干update()方法,允许用户对数据表记录进行更改和删除操作。 @Repository public class ViewSpaceDao {
@Autowired private JdbcTemplate jdbcTemplate; public void addViewSpace(final ViewSpace viewSpace) {
final String sql = "INSERT INTO t_view_space(space_name,description,address) VALUES(?,?,?)"; Object[] params = new Object[] { viewSpace.getSpaceName(),viewSpace.getDescription(),viewSpace.getAddress() }; // 方式1 jdbcTemplate.update(sql, params);} } JdbcTemplate在内部通过PreparedStatement执行SQL语句,左移可以使用绑定参数的SQL语句。在sql中?代表一个占位符,而param中的是用于填充占位符的参数数组,在最后直接通过int update(String sql,Object[]args)方法进行表数据的更新 通过update(String sql,Object[]args)方法为SQL语句的占位符绑定参数时,并没有显示指定对应字段的数据类型。Spring直接让PreparedStatement进行猜测。更好的方法是使用int update(String sql,Object[]args,int[]argTypes)显示指定每个占位符所对应的字段数据类型 此时上述的 jdbcTemplate.update(sql, params);}就会变为jdbcTemplate.update(sql, params,new int[]{Types.VARCHAR,Types.VARCHAR}); 除了以上的两个update()方法,JdbcTemplate还提供了以下几个功能相似的重载方法 int update(String sql):为不带占位符的SQL语句所提供的方法 int update(String sql,Object...args):使用不定参数的方法 int update(String sql,PreparedStatementSetterpss):PreparedStatementSetter是一个回调接口,他定义了一个void setValues(PreparedStatement ps)接口方法。JdbcTemplate使用SQL语句创建出PreparedStatement实例后,将调用接口执行绑定参数的操作。 jdbcTemplate.update(sql, new PreparedStatementSetter() { public void setValues(PreparedStatement ps) throws SQLException { ps.setString(1,forum.getForumName()); ps.setString(2, forum.getForumDesc()); } }); int update(PreparedStatementCreator psc):这也是一个回调接口,他负责创建一个PreparedStatement实例,该接口回调定义了一个PreparedStatement createPrepareStatement(Connection con)方法 KeyHolder keyHolder = new GeneratedKeyHolder(); jdbcTemplate.update(new PreparedStatementCreator() {
public PreparedStatement createPreparedStatement(Connection conn) throws SQLException {
PreparedStatement ps = conn.prepareStatement(sql); ps.setString(1, viewSpace.getSpaceName()); ps.setString(2, viewSpace.getDescription()); ps.setString(3, viewSpace.getAddress()); return ps; } }, keyHolder); viewSpace.setSpaceId(keyHolder.getKey().intValue()); protected int update(PreparedStatementCreator psc,PreparedStatementSetter pss):联合使用PreparedStatementCreator和PreparedStatementSetter回调。 2、返回数据库的表自增主键值 用户经常使用数据的自增字段作为表主键,即主键值不在应用层产生,而是在新增记录时数据库产生。 当新增记录时允许将数据库自动产生的主键值绑定到Statement或PreparedStatement中,使用Statement时,可以通过如下方法绑定主键值。 int executeUpdate(String sql,int autoGenerateKeys) 也可以通过Connection创建绑定自增值的PreparedStatement PreparedStatement prepareStatement(String sql,int autoGenerateKeys) 当autoGeneratedKeys参数设置为Statement.RETURN_GENERATED_KEYS值时即可绑定数据库产生的主键值,设置为Statement._NO_GENERATED_KEYS不绑定主键值 Statement stmt=conn.createStatement(); String sql="INSERT INTO T_VIEW(space_name,description)VALUES('拨浪鼓','国家级旅游度假区')"; stmt.executeUpdate(sql,Statement.RETURN_GENERATED_KEYS);//指定绑定自增主键值 if(rs.next()){int key=rs.getInt();}//获取对应的表自增主键值 3、批量更改数据 public int[] batchUpdate(String[]sql):多条SQL语句组成一个数组,该方法以批量方式执行这些SQL语句,Spring在内部使用JDBC提供的批量更新API完成操作,如果底层的Jdbc Driver不支持批量更新操作,Spring将采用逐条更新的方式模拟批量更新 int[] batchUpdate(String sql,BatcgPreparedStatementSetter pss):使用本方法对于统一结构的带参SQL语句多次进行数据更次年操作。通过BatchPreparedStatementSETTER回调接口进行批量参数的绑定工作。而BatchPreparedStatementSetter又定义了两个方法 int getBatchSize():指定本批次的大小 void setValues(PreparedStatement ps ,int i):为指定的PreparedStatement设置参数 public void addViewSpaces(final List
viewSpaces) {
final String sql = "INSERT INTO t_view_space(space_name,description,address) VALUES(?,?,?)"; jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
public int getBatchSize() {
return viewSpaces.size(); } public void setValues(PreparedStatement ps, int index) throws SQLException {
ViewSpace viewSpace = viewSpaces.get(index); ps.setString(1, viewSpace.getSpaceName()); ps.setString(2, viewSpace.getDescription()); ps.setString(3, viewSpace.getAddress()); } }); jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
public int getBatchSize() {
return viewSpaces.size(); } public void setValues(PreparedStatement ps, int index) throws SQLException {
ViewSpace viewSpace = viewSpaces.get(index); ps.setString(1, viewSpace.getSpaceName()); ps.setString(2, viewSpace.getDescription()); ps.setString(3, viewSpace.getAddress()); } }); } BatchPreparedStatementSetter是一次性批量提交数据,而不会分批提交,getBatchSize()是整批的大小,所以,如果希望一个LIST钟的数据通过BatchPreparedStatementSETTER批量更新到数据库中getBatchSize()就应该设置为List的大小。 4、数据查询 使用RowCallbackHandler处理结果集 Spring提供了org.springframework.jdbc.core.RowCallbackHandler回调接口,通过该接口可以定义如何从结果集中获取数据。该接口只有一个方法void processRow(ResultSet rs) throw SQLException.Spring会遍历结果集,对结果集中的每一行调用RowCallbackHandler回调接口处理数据,所以我们无须调用ResultSet的next()方法,而只是定义如何获取结果行中的数据的逻辑就可以了。 示例:通过id获取数据 public ViewSpace getViewSpace(final int spaceId) {
String sql = "SELECT space_name,description,address FROM t_view_space WHERE space_id=?"; final ViewSpace viewSpace = new ViewSpace(); jdbcTemplate.query(sql, new Object[] { spaceId }, new RowCallbackHandler() {//将结果集数据航中的数据抽取到viewSpace对象中 public void processRow(ResultSet rs) throws SQLException {
viewSpace.setSpaceId(spaceId); viewSpace.setSpaceName(rs.getString("space_name")); viewSpace.setDescription(rs.getString("description")); viewSpace.setAddress(rs.getString("address")); } }); return viewSpace; } 示例:返回多条数据 public List
getViewSpaces(final int fromId, final int toId) {
String sql = "SELECT space_id, SPACE_NAME,description,address FROM t_view_space WHERE space_id between ? and ?"; // 方法1:使用RowCallbackHandler接口 final List
viewSpaces = new ArrayList
(); jdbcTemplate.query(sql,new Object[]{fromId,toId},new RowCallbackHandler(){ public void processRow(ResultSet rs) throws//将结果集中的数据映射到List中 SQLException {
viewSpace = new ViewSpace(); viewSpace.setSpaceId(rs.getInt("space_id")); viewSpace.setSpaceName(rs.getString("space_name")); viewSpace.setDescription(rs.getString("description")); viewSpace.setAddress(rs.getString("address")); viewSpaces.add(viewSpace); }}); return forums; } 5、查询单值数据 如果查询的结果仅有一个值,可以用更简单的方式获得结果的值。JdbcTemplate为获取结果集的单值数据提供了3个方法,分别用于获取int long 的单值,其他类型的单值以Object类型返回。 int类型的单值查询接口: int queryForInt(String sql) int queryForInt(String sql,Object...args) int queryForInt(String sql,Object[]args,int[]argTypes) 示例: public int getViewSpaceNum(){
String sql="select count(*) from t_view_space "; return getJdbcTemplate。queryForInt(sql); } long类型的单值查询接口: long queryForLongString sql) long queryForLong(String sql,Object...args) long queryForLong(String sql,Object[]args,int[]argTypes) 其他类型的单值查询接口:
queryForObject(String sql,Class
requiredType)
queryForObject(String sql,Object[]args,Class
requiredType)
queryForObject(String sql,Object[]args,int[]argTypes,Class
requiredType)
queryForObject(String sql,Object[]args,int[]argTypes,RowMapper
rowMapper)
queryForObject(String sql,Object[]args,RowMapper
rowMapper)
queryForObject(String sql,RowMapper
rowMapper) 6、调用存储过程 JdbcTemplate提供了两个调用存储过程的接口方法 1)
T execute(String callString,CallableStatementCallback
action) 用户同callString参数指定调用存储过程的SQL语句。第二个参数CallableStatementCallback
是一个回调接口,该接口只有一个方法T DoInCallableStatement(CallableStatement cs)影虎可以在该方法中进行输入参数绑定,输出参数注册一级返回数据处理等操作 2)
T execute(CallableStatementCreator csc,CallableStatementCallback
action) 该接口方法使用CallableStatementCreator创建CallableStatement,CallableStatementCreator定义了一个方法:CallableStatement createCallableStatement(Connection con),他使用Connection实例创建CallableStatement对象。CallableStatementCallable
负责处理存储过程的返回结果。 Spring提供了创建CallableStatementCreator的工厂类CallableStatementCreatorFactory,通过该工厂类可以简化CallableStatementCreator的实例的创建工作。 例如创建一个存出过场一个入参in_space_id一个出参out_num public int getViewPointNum(final int spaceId){ String sql="{call P_GET_VIEW_POINT_NUM(?,?)}";//调用存储过程的SQL语句 Integet num=jdbcTemplate.execute(sql,new CallableStatementCallback
(){ public Integer doInCallableStatement(CallableStatement cs) throws SQLException,DataAccessException{ cs.setInt(1,spaceId);//绑定入参 cs.registerOutParameter(2,Types.INTEGER);//注册输出参数 cs.execute(); return cs.getInt(2); }//获取输出参数的值 }); return num; } 或者: public int getSpaceViewPointNum(final int spaceId) { String sql = "{call P_GET_VIEW_POINT_NUM(?,?)}"; CallableStatementCreatorFactory fac = new CallableStatementCreatorFactory(sql);//以一个SQL语句为入参创建CallableStatementCreator工厂实例 fac.addParameter(new SqlParameter("spaceId", Types.INTEGER));//设置存储过程的入参 fac.addParameter(new SqlOutParameter("pointNum", Types.INTEGER));//设置存储过程的出参 Map
paramsMap = new HashMap
(); paramsMap.put("spaceId", spaceId);//为前面的入参指定参数值 CallableStatementCreator csc = fac.newCallableStatementCreator(paramsMap); Integer num = jdbcTemplate.execute(csc, new CallableStatementCallback
() {//通过new CallableStatementCallback
创建一个CallableStatementCreator public Integer doInCallableStatement(CallableStatement cs) throws SQLException, DataAccessException { cs.execute(); return cs.getInt(2); } }); return num; } 三、BLOB/CLOB类型数据的操作 1、插入Lob类型的数据 用于保存数据的表有两个Lob字段,其中description是CLOB类型,而imageFile是BLOB类型 package com.smart.dao; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.sql.*; import java.util.HashMap; import java.util.List; import java.util.Map; import com.smart.domain.ViewPoint; import oracle.jdbc.OracleConnection; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.LobRetrievalFailureException; import org.springframework.jdbc.core.CallableStatementCallback; import org.springframework.jdbc.core.CallableStatementCreator; import org.springframework.jdbc.core.CallableStatementCreatorFactory; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.SqlOutParameter; import org.springframework.jdbc.core.SqlParameter; import org.springframework.jdbc.core.support.AbstractLobCreatingPreparedStatementCallback; import org.springframework.jdbc.core.support.AbstractLobStreamingResultSetExtractor; import org.springframework.jdbc.datasource.DataSourceUtils; import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer; import org.springframework.jdbc.support.lob.LobCreator; import org.springframework.jdbc.support.lob.LobHandler; import org.springframework.jdbc.support.rowset.SqlRowSet; import org.springframework.stereotype.Repository; import org.springframework.util.FileCopyUtils; @Repository public class ViewPointDao { @Autowired private JdbcTemplate jdbcTemplate; @Autowired private LobHandler lobHandler;//定义LobHandler属性 @Autowired private DataFieldMaxValueIncrementer incre; public void addViewPoint(final ViewPoint viewPoint) { String sql = " INSERT INTO t_view_point(point_id,space_id,point_name,ticket_price,img_file,description)" + " VALUES(?,?,?,?,?,?)"; jdbcTemplate.execute(sql, new AbstractLobCreatingPreparedStatementCallback(this.lobHandler) { protected void setValues(PreparedStatement ps, LobCreator lobCreator) throws SQLException { //1:固定主键 //ps.setInt(1,1); //2:通过自增键指定主键值LobHandler属性 ps.setInt(1, incre.nextIntValue()); ps.setInt(2, viewPoint.getSpaceId()); ps.setString(3, viewPoint.getPointName()); ps.setDouble(4, viewPoint.getTicketPrice()); lobCreator.setClobAsString(ps, 6, viewPoint.getDescription());//设置Clob字段 lobCreator.setBlobAsBytes(ps, 5, viewPoint.getImgFile());//设置Blob字段 } }); }} 首先在ViewPointDao中引入一个LobHandler属性,并通过jdbcTemplate.execute(sql, new AbstractLobCreatingPreparedStatementCallback(this.lobHandler)方法完成插入Lob数据的操作,通过匿名内部类的方式定义LobCreatingPreparedStatementCallback抽象类的子类,其构造函数需要一个LobHandler入参。 在匿名类中实现了父类的抽象方法setValues(PreparedStatement ps,LobCreator lobCreator)在该方法中,通过lobCreator操作Lob对象。 配置文件中做更改:
lazy-init="true" p:nativeJdbcExtractor-ref="nativeJdbcExtractor"/> 设置为lazy=true是因为nativeJdbcExtractor需要通过运行期的反射机制获取底层的jdbc对象,所以需要避免让Spring容器启动时就实例化这两个Bean LobHandler需要访问本地Jdbc对象,因此需要通过一个NativeJdbcExtractor Bean来完成任务 2、以块数据方式获取Lob数据 用户可以直接以数据块的方式读取Lob数据:以String读取Clob字段的数据,而以byte[]读取Blob字段的数据。 public List
getImgFiles(final int spaceId) { String sql = " SELECT point_id,img_file FROM t_view_point where point_id =? and img_file is not null "; return jdbcTemplate.query(sql, new Object[]{spaceId}, new RowMapper
() { public ViewPoint mapRow(ResultSet rs, int rowNum)throws SQLException { int pointId = rs.getInt(1); byte[] attach = lobHandler.getBlobAsBytes(rs, 2);//以二进制的方式获取Blob数据 ViewPoint viewPoint = new ViewPoint(); viewPoint.setPointId(pointId); viewPoint.setImgFile(attach); return viewPoint; } }); } 通过JdbcTemplate的List
query(String sql;Object[]args,RowMapper rowMapper)接口处理行数据的映射,在RowMapper回调的mapRow()接口方法中,通过LobHandler以byte[]获取Blob字段的数据 3、以流数据方式读取Lob数据 由于Lob数据的体积可能很大,如果直接以块的方式操作Lob数据,需要消耗大量的内存,直接影响到程序的整体运行,对于体积很大的Lob数据,可以使用流的方式进行访问,减少内存的占用,JdbcTemplate为此提供了一个Object query(String sql,Object[]args,ResultSetExtractor rse)fangfa ResultSetExtractor接口拥有一个处理流数据的抽象类org.springframework.jdbc.core.supportAbstractLobStreamingResultS,可以通过扩展此类用流的方式操作Lob字段的数据 public void getImgFile(final int pointId, final OutputStream os) {//用于接收Lob数据的输出流 String sql = " SELECT img_file FROM t_view_point where point_id =? "; jdbcTemplate.query(sql, new Object[]{pointId}, new AbstractLobStreamingResultSetExtractor() {//匿名内部类 protected void handleNoRowFound() throws LobRetrievalFailureException {//处理未找到数据行的情况 System.out.println("Not Found result!"); } public void streamData(ResultSet rs) throws SQLException, IOException {//以流的方式处理Lob字段 InputStream is = lobHandler.getBlobAsBinaryStream(rs, 1); if (is != null) { FileCopyUtils.copy(is, os); } } } ); } 通过扩展 AbstractLobStreamingResultSetExtractor抽象类在streamData(ResultSet rs)方法中以流的方式读取Lob字段数据。这里又利用了Spring的工具类FileCopyUtils,将输入流的数据复制到输出流中。在getImgFile方法中通过入参OutputStream接收Lob的数据 四、其他类型的JdbcTemplate 除了标准的JdbcTemplate之外,Spring还提供了两个好用的JDBC模板类,他们分别是NamedParameterJdbcTemplate和SimpleJdbcTemplate. 1、NamedParameterJdbcTemplate 在低版本的Spring中,用户只能使用?占位符声明参数,并使用索引号绑定参数,使用这种方法绑定参数时,必须足够小心,以确保正确匹配。 @Repository public class ViewSpaceDao { @Autowired private JdbcTemplate jdbcTemplate; @Autowired private NamedParameterJdbcTemplate namedParameterJdbcTemplate; public void addViewSpaceByNamedParams(final ViewSpace viewSpace) { final String sql = "INSERT INTO t_view_space(space_name,description,address) VALUES(:spaceName,:description,:address)";//定义参数源 SqlParameterSource sps = new BeanPropertySqlParameterSource(viewSpace);//定义命名参数 namedParameterJdbcTemplate.update(sql, sps);//使用模板方法 } } 需要在Spring的配置文件中添加
在SQL语句中,声明命名参数的格式是:paramName,在这个示例中使用BeanPropertySqlParameterSource提供参数源,他接受一个JavaBean作为构造函数的入参,和标准的JdbcTemplate一样,NamedParameterJdbcTemplate提供了很多的数据访问方法,这些方法大多都拥有一个SqlParameterSource入参,用来提供参数源 上述中的spaceName等都是和Sql语句中命名参数匹配,如果数据表记录没有对应的领域对象 MapSqlParameterSource sps=new MapSqlParameterSource().addValue("spaceName",viewSpace.getSpaceName()).addValue("address",viewSpace.getAddress()); 五、使用OO方式访问数据库 org.springframework.jdbc.object包下的类允许用户以更加面向对象的方式访问数据库,用户通常也可以直接使用JdbcTemplate完成类似的操作,相对于把一个查询操作封装成一个类而言,我们直接调用JdbcTemplate方法更加简洁,更容易理解。 1、使用MappingSqlQuery查询数据 SqlQuery是一个可重用,线程安全的类,它封装了一个SQL查询。用户很少需要直接使用SqlQuery,因为其子类MappingSqlQuery作为一个更加易用的实现类能够将结果集中的行映射为Java对象,SqlQuery还有两个扩展类,分别是MappingSqlQueryWithParameters和UpdateableSqlQuery @Repository public class ViewSpaceOODao { @Autowired private DataSource dataSource; private ViewSpaceQuery viewSpaceQuery;//①声明ViewSpaceQuery变量 @PostConstruct public void init() { this.viewSpaceQuery = new ViewSpaceQuery(this.dataSource); //②初始化ForumQuery对象 this.viewSpaceInsert = new ViewSpaceInsert(this.dataSource); this.viewPointNum = new GetViewPointNum(this.dataSource); this.viewSpaceNumCount = new SqlFunction
(dataSource, "SELECT COUNT(*) FROM t_view_space"); this.viewSpaceNumCount.compile(); } public ViewSpace getViewSpace(int spaceId) { return viewSpaceQuery.findObject(spaceId); //③执行查询并返回结果 } //④定义MappingSqlQuery private class ViewSpaceQuery extends MappingSqlQuery
{ public ViewSpaceQuery(DataSource ds) {//⑤定义查询语句并预编译 super(ds, "SELECT space_id,space_name, description FROM t_view_space WHERE space_id=?"); declareParameter(new SqlParameter(Types.INTEGER)); compile();//⑤-1不能忘记这行编译语句,否则会发生错误 } public ViewSpace mapRow(ResultSet rs, int rownum) throws SQLException {//⑥ ViewSpace viewSpace = new ViewSpace(); viewSpace.setSpaceId(rs.getInt("space_id")); viewSpace.setSpaceName(rs.getString("space_name")); viewSpace.setDescription(rs.getString("description")); return viewSpace; } } 使用MappingSqlQuery一般分为以下3个步骤: 1)定义子类,在子类中声明SQL语句并定义行数据映射逻辑 2)声明子类来的变量并实例化该类 3)使用MappingSqlQuery的方法执行数据查询操作 2、使用SqlUpdate更新数据 @Repository public class ViewSpaceOODao { @Autowired private DataSource dataSource; private ViewSpaceQuery viewSpaceQuery;//①声明ViewSpaceQuery变量 private ViewSpaceInsert viewSpaceInsert; @PostConstruct public void init() { this.viewSpaceQuery = new ViewSpaceQuery(this.dataSource); //②初始化ForumQuery对象 this.viewSpaceInsert = new ViewSpaceInsert(this.dataSource); } //①新增Forum对象 public void addViewSpace(ViewSpace viewSpace) { viewSpaceInsert.insert(viewSpace); } //②扩展SqlUpdate定义子类 private class ViewSpaceInsert extends SqlUpdate { public ViewSpaceInsert(DataSource ds) {//③定义SQL语句并预编译 super(ds, "INSERT INTO t_view_space(space_name, description) VALUES(:spaceName,:description)"); declareParameter(new SqlParameter("spaceName", Types.VARCHAR)); declareParameter(new SqlParameter("description", Types.VARCHAR)); compile(); } } 3、使用StoredProcedure执行存储过程 @Repository public class ViewSpaceOODao { @Autowired private DataSource dataSource; private ViewSpaceQuery viewSpaceQuery;//①声明ViewSpaceQuery变量 private ViewSpaceInsert viewSpaceInsert; private GetViewPointNum viewPointNum; @PostConstruct public void init() { this.viewSpaceQuery = new ViewSpaceQuery(this.dataSource); //②初始化ForumQuery对象 this.viewSpaceInsert = new ViewSpaceInsert(this.dataSource); this.viewPointNum = new GetViewPointNum(this.dataSource); } public int getViewPointNum(int userId) { return viewPointNum.getViewPointNum(userId); } //①扩展StoredProcedure private class GetViewPointNum extends StoredProcedure { private static final String SQL = "P_GET_VIEW_POINT_NUM";//②定义存储过程名 public GetViewPointNum(DataSource ds) { setDataSource(ds); setSql(SQL); //③声明入参 declareParameter(new SqlParameter("spaceId", Types.INTEGER)); //④声明出参 declareParameter(new SqlOutParameter("outNum", Types.INTEGER)); compile(); } public int getViewPointNum(int userId) {//⑤执行存储过程并返回结果 Map
map = new HashMap
(); map.put("userId", userId); Map
outMap = execute(map); return (Integer) outMap.get("outNum"); } } } 通过StoredProcedure执行存储过程SQL语句只需指定存储过程的名,不通过占位符声明入参和出参。而通过declareParameter()方法声明入参合成出参。 4、SqlFunction类 SqlFunction操作类封装了一个SQL函数包装器,该包装器适用于查询并返回一个单行结果集的访问操作。默认返回的是一个int值,不过更推荐使用JdbcTemplate中的queryForXxx()方法返回单值数据 @Repository public class ViewSpaceOODao { @Autowired private DataSource dataSource; private SqlFunction
viewSpaceNumCount; @PostConstruct public void init() { this.viewSpaceNumCount = new SqlFunction
(dataSource, "SELECT COUNT(*) FROM t_view_space"); this.viewSpaceNumCount.compile(); } public int getViewSpaceNum() { return viewSpaceNumCount.run(); } }

转载于:https://www.cnblogs.com/dream-to-pku/p/5794267.html

你可能感兴趣的文章
数值优化(三)
查看>>
LeetCode:Balanced Binary Tree
查看>>
4.时间复杂度和空间复杂度-2
查看>>
华为架构师8年经验谈:从单体架构到微服务的服务化演进之路
查看>>
软件工程——团队答辩
查看>>
Eonasdan bootstrap datetimepicker 使用记录
查看>>
使用 JavaScript 将网站后台的数据变化实时更新到前端-【知乎总结】
查看>>
四: 基本标签
查看>>
图片文件重命名
查看>>
Day1 BFS算法的学习和训练
查看>>
A Tour of Go Methods continued
查看>>
How to setup Wicket Examples in Eclipse
查看>>
什么样的项目适合自动化测试
查看>>
输不起慢的代价,赢不了休息的时间
查看>>
使用弹性布局来解决令人烦恼的垂直居中问题~~
查看>>
《利用python进行数据分析》读书笔记--第十一章 金融和经济数据应用(二)
查看>>
数字图像处理---直方图均衡化
查看>>
java 极光推送
查看>>
Simple2D-20(重构)
查看>>
[cogs2652]秘术「天文密葬法」
查看>>