??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲AV成人精品网站在线播放,亚洲精品无码av人在线观看 ,337p日本欧洲亚洲大胆人人http://m.tkk7.com/176142998/category/33690.htmlzh-cnSat, 02 Apr 2011 00:37:30 GMTSat, 02 Apr 2011 00:37:30 GMT60开发soap的一个简单的例子http://m.tkk7.com/176142998/archive/2011/04/01/347484.html飞飞飞飞Fri, 01 Apr 2011 09:21:00 GMThttp://m.tkk7.com/176142998/archive/2011/04/01/347484.htmlhttp://m.tkk7.com/176142998/comments/347484.htmlhttp://m.tkk7.com/176142998/archive/2011/04/01/347484.html#Feedback0http://m.tkk7.com/176142998/comments/commentRss/347484.htmlhttp://m.tkk7.com/176142998/services/trackbacks/347484.html1、徏一个Project取名为SOAP
2、将axis-1_4\webapps\axis\WEB-INF\lib下的所有文件拷贝到你的SOAP工程文g?/div>
3、新Z个HelloWord.java
package com;
public class HelloWord {
public String getHelloWord(userInfo userInfo) {
return "hi!:" + userInfo.getName() + "| " + userInfo.getPassword()
+ " | " + userInfo.getArea();
}
}
 
4、新Z个userInfo.java 对象
package com;
public class userInfo implements java.io.Serializable{
/**
 * 
 */
private static final long serialVersionUID = -1536718814867769008L;
String name;
String password;
String area;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getArea() {
return area;
}
public void setArea(String area) {
this.area = area;
}
}
5、在WEB-INF\server-config.wsdd 文gd以下内容Q注意颜色标记的地方时跟soap相关的地方)(j)
<?xml version="1.0" encoding="UTF-8"?>
<deployment xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<handler type="java:org.apache.axis.handlers.http.URLMapper"
name="URLMapper" />
<service name="HelloWord" provider="java:RPC">
<parameter name="className" value="com.HelloWord" />
<parameter name="allowedMethods" value="getHelloWord" />
<beanMapping languageSpecificType="java:com.userInfo" qname="ns:userInfo" xmlns:ns="urn:BeanService"/>
</service>
<transport name="http">
<requestFlow>
<handler type="URLMapper" />
</requestFlow>
</transport>
</deployment> 
6、web.xml 内容
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web
Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<display-name>Apache-Axis</display-name>
<servlet>
<servlet-name>AxisServlet</servlet-name>
<display-name>Apache-Axis Servlet</display-name>
<servlet-class>
org.apache.axis.transport.http.AxisServlet
    </servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>AxisServlet</servlet-name>
<url-pattern>/servlet/AxisServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>AxisServlet</servlet-name>
<url-pattern>*.jws</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>AxisServlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
<welcome-file>index.html</welcome-file>
<welcome-file>index.jws</welcome-file>
</welcome-file-list>
</web-app>
7、访问\?http://localhost:8080/SOAP/services/HelloWord?wsdl
8、用soapUI 3.6.1 生成客户端JUNIT试代码.q行单元试Q设|soapui的axis参数
9、生成客L(fng)JUNIT试代码
 
 
10、将生成的代码放到SOAP工程下。修Ҏ(gu)试用例?/div>
 
 
11、执行测试,查看l果Q?/div>


飞飞 2011-04-01 17:21 发表评论
]]>Spring的JDBCTemplatehttp://m.tkk7.com/176142998/archive/2008/08/12/221507.html飞飞飞飞Tue, 12 Aug 2008 07:31:00 GMThttp://m.tkk7.com/176142998/archive/2008/08/12/221507.htmlhttp://m.tkk7.com/176142998/comments/221507.htmlhttp://m.tkk7.com/176142998/archive/2008/08/12/221507.html#Feedback1http://m.tkk7.com/176142998/comments/commentRss/221507.htmlhttp://m.tkk7.com/176142998/services/trackbacks/221507.htmlSpring的JDBCTemplate

当hql{查询方式不能满x(chng)能或灵zL的要求Q必M用SQLӞ大家有三U选择Q?/p>

W一、用Hibernate 的sql 查询函数Q将查询l果对象转ؓ(f)Entity对象?/p>

W二、用Hibernate Session的getConnection 获得JDBC ConnectionQ然后进行纯JDBC API操作Q?/p>

W三、选择把Spring的JDBCTemplate作ؓ(f)一U很不错的JDBC Utils来用?/p>

     JDBCTemplate的用很单,只要在ApplicationContext文g里定义一个jdbcTemplate节点QPOJO获得注入后可以直接执行操作,不需要承什么基c,详见JDBCTemplate参考文?sup>?/p>

     AplicationContext定义Q?/p>

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>

实际使用Q?nbsp;

SqlRowSet rs = jdbcTemplate.queryForRowSet(sql, params);

Tips1Q?/strong> jdbcTemplate有很多的ORM化回调操作将q回l果转ؓ(f)对象列表Q但很多时候还是需要返回ResultSetQSpring有提供一个类似ResultSet?Spring SqlRowSet对象?/p>

         

Tips2Q?/strong>.注意jdbcTemplate量只执行查询操作,莫要q行更新Q否则很Ҏ(gu)破坏Hibernate的二U缓存(sh)pR?/p>

Chapter 11. 使用JDBCq行数据讉K

11.1. ?/h2>

Spring JDBC抽象框架所带来的h(hun)值将在以下几个方面得以体玎ͼ(x)Q注Q用了(jin)Spring JDBC抽象框架之后Q应用开发h员只需要完成斜体字部分的编码工作。)(j)

  1. 指定数据库连接参?/p>

  2. 打开数据库连?/p>

  3. 声明SQL语句

  4. 预编译ƈ执行SQL语句

  5. 遍历查询l果Q如果需要的话)(j)

  6. 处理每一ơ遍历操?/em>

  7. 处理抛出的Q何异?/p>

  8. 处理事务

  9. 关闭数据库连?/p>

Spring替我们完成所有单调乏味的JDBC底层l节处理工作?

11.1.1. Spring JDBC包结?/h3>

Spring JDBC抽象框架由四个包构成Q?tt class="literal">core?dataSource?tt class="literal">object以及(qing)support?

org.springframework.jdbc.core包由JdbcTemplatecM?qing)相关的回调接口Qcallback interfaceQ和cȝ成?

org.springframework.jdbc.datasource包由一些用来简?tt class="interfacename">DataSource讉K的工L(fng)Q以?qing)各U?tt class="interfacename">DataSource接口的简单实?主要用于单元试以及(qing)在J2EE容器之外使用JDBC)l成。工L(fng)提供?jin)一些静(rn)态方法,诸如通过JNDI获取数据q接以及(qing)在必要的情况下关闭这些连接。它支持l定U程的连接,比如被用?tt class="classname">DataSourceTransactionManager的连接?

接下来,org.springframework.jdbc.object包由装?jin)查询、更C?qing)存储过E的cȝ成,q些cȝ对象都是U程安全q且可重复用的。它们类gJDOQ与JDO的不同之处在于查询结果与数据库是“断开q接”的。它们是?tt class="literal">org.springframework.jdbc.core包的基础上对JDBC更高层次的抽象?

最后,org.springframework.jdbc.support包提供了(jin)一?tt class="classname">SQLException的{换类以及(qing)相关的工L(fng)?

在JDBC处理q程中抛出的异常被转换?tt class="literal">org.springframework.dao包中定义的异常。因此用Spring JDBCq行开发将不需要处理JDBC或者特定的RDBMS才会(x)抛出的异常。所有的异常都是unchecked exceptionQ这h们就可以对传递到调用者的异常q行有选择的捕莗?

11.2. 利用JDBC核心(j)cd现JDBC的基本操作和错误处理

11.2.1. JdbcTemplatec?/h3>

JdbcTemplate是core包的核心(j)cR它替我们完成了(jin)资源的创Z?qing)释攑ַ作,从而简化了(jin)我们对JDBC的用。它q可以帮助我们避免一些常见的错误Q比如忘记关闭数据库q接。JdbcTemplate完成JDBC核心(j)处理程Q比如SQL语句的创建、执行,而把SQL语句的生成以?qing)查询结果的提取工作留给我们的应用代码。它可以完成SQL查询、更C?qing)调用存储过E,可以?tt class="interfacename">ResultSetq行遍历q加以提取。它q可以捕获JDBC异常q将其{换成org.springframework.dao包中定义的,通用的,信息更丰富的异常?

使用JdbcTemplateq行~码只需要根据明定义的一l契U来实现回调接口?tt class="interfacename">PreparedStatementCreator回调接口通过l定?tt class="interfacename">Connection创徏一个PreparedStatementQ包含SQL和Q何相关的参数?tt class="literal">CallableStatementCreateor实现同样的处理,只不q它创徏的是CallableStatement?tt class="literal">RowCallbackHandler接口则从数据集的每一行中提取倹{?

我们可以在一个service实现cM通过传递一?tt class="interfacename">DataSource引用来完成JdbcTemplate的实例化Q也可以在application context中配|一个JdbcTemplate beanQ来供service使用。需要注意的?tt class="interfacename">DataSource在application contextL配制成一个beanQ第一U情况下Q?tt class="interfacename">DataSource bean传递给serviceQ第二种情况?tt class="interfacename">DataSource bean传递给JdbcTemplate bean。因为JdbcTemplate使用回调接口?tt class="interfacename">SQLExceptionTranslator接口作ؓ(f)参数Q所以一般情况下没有必要通过l承JdbcTemplate来定义其子类?

JdbcTemplate中用的所有SQL会(x)?#8220;DEBUG”U别记入日志Q一般情况下日志的category?tt class="classname">JdbcTemplate相应的全限定cdQ不q如果需要对JdbcTemplateq行定制的话Q可能是它的子类名)(j)?

11.2.2. NamedParameterJdbcTemplatec?/h3>

NamedParameterJdbcTemplatecd加了(jin)在SQL语句中用命名参数的支持。在此之前,在传l的SQL语句中,参数都是?tt class="literal">'?'占位W来表示的?NamedParameterJdbcTemplatecd部封装了(jin)一个普通的JdbcTemplateQƈ作ؓ(f)其代理来完成大部分工作。下面的内容主要针对NamedParameterJdbcTemplate?tt class="classname">JdbcTemplate的不同之处来加以说明Q即如何在SQL语句中用命名参数?

通过下面的例子我们可以更好地?jin)?tt class="classname">NamedParameterJdbcTemplate的用模式(在后面我们还有更好的使用方式Q?

// some JDBC-backed DAO class...
public int countOfActorsByFirstName(String firstName) {
String sql = "select count(0) from T_ACTOR where first_name = :first_name";
NamedParameterJdbcTemplate template = new NamedParameterJdbcTemplate(this.getDataSource());
SqlParameterSource namedParameters = new MapSqlParameterSource("first_name", firstName);
return template.queryForInt(sql, namedParameters);
}

在上面例子中Q?tt class="literal">sql变量使用?jin)命名参数占位?#8220;first_name”Q与其对应的值存?tt class="literal">namedParameters变量中(cd?tt class="classname">MapSqlParameterSourceQ?

如果你喜Ƣ的话,也可以用基于Map风格的名值对命名参C递给NamedParameterJdbcTemplateQ?tt class="classname">NamedParameterJdbcTemplate实现?tt class="interfacename">NamedParameterJdbcOperations接口Q剩下的工作由调用该接口的相应Ҏ(gu)来完成,q里我们׃再赘qͼ(j)Q?

// some JDBC-backed DAO class...
public int countOfActorsByFirstName(String firstName) {
String sql = "select count(0) from T_ACTOR where first_name = :first_name";
NamedParameterJdbcTemplate template = new NamedParameterJdbcTemplate(this.getDataSource());
Map namedParameters = new HashMap();
namedParameters.put("first_name", firstName);
return template.queryForInt(sql, namedParameters);
}

另外一个值得一提的Ҏ(gu)是?tt class="classname">NamedParameterJdbcTemplate位于同一个包中的SqlParameterSource接口。在前面的代码片断中我们已经看到?jin)该接口的实玎ͼ?tt class="classname">MapSqlParameterSourcec)(j)Q?tt class="interfacename">SqlParameterSource可以用来作ؓ(f)NamedParameterJdbcTemplate命名参数的来源?tt class="classname">MapSqlParameterSourcecL一个非常简单的实现Q它仅仅是一?tt class="interfacename">java.util.Map适配器,当然其用法也׃a自明?jin)(如果q有不明?jin)的Q可以在Spring的JIRApȝ中要求提供更多的相关资料Q?

SqlParameterSource接口的另一个实玎ͼQ?tt class="classname">BeanPropertySqlParameterSource为我们提供了(jin)更有的功能。该cd装一个类似JavaBean的对象,所需要的命名参数值将由包装对象提供,下面我们使用一个例子来更清楚地说明它的用法?

// some JavaBean-like class...
public class Actor {
private Long id;
private String firstName;
private String lastName;
public String getFirstName() {
return this.firstName;
}
public String getLastName() {
return this.lastName;
}
public Long getId() {
return this.id;
}
// setters omitted...
}
// some JDBC-backed DAO class...
public int countOfActors(Actor exampleActor) {
// notice how the named parameters match the properties of the above 'Actor' class
String sql = "select count(0) from T_ACTOR where first_name = :firstName and last_name = :lastName";
NamedParameterJdbcTemplate template = new NamedParameterJdbcTemplate(this.getDataSource());
SqlParameterSource namedParameters = new BeanPropertySqlParameterSource(exampleActor);
return template.queryForInt(sql, namedParameters);
}

大家必须牢记一点:(x)NamedParameterJdbcTemplatecd?span class="emphasis">包装?jin)一个标准的JdbcTemplatecR如果你需要访问其内部?tt class="classname">JdbcTemplate实例Q比如访?tt class="classname">JdbcTemplate的一些方法)(j)那么你需要?tt class="literal">getJdbcOperations()Ҏ(gu)q回?span class="emphasis">JdbcOperations接口。(JdbcTemplate实现?tt class="interfacename">JdbcOperations接口Q?

NamedParameterJdbcTemplatecLU程安全的,该类的最佳用方式不是每ơ操作的时候实例化一个新?tt class="classname">NamedParameterJdbcTemplateQ而是针对每个DataSource只配|一?tt class="classname">NamedParameterJdbcTemplate实例Q比如在Spring IoC容器中用Spring IoC来进行配|)(j)Q然后在那些使用该类的DAO中共享该实例?

11.2.3. SimpleJdbcTemplatec?/h3>

[Note] Note

h意该cL提供的功能仅适用于Java 5 (Tiger)?/em>

SimpleJdbcTemplatecLJdbcTemplatecȝ一个包装器QwrapperQ,它利用了(jin)Java 5的一些语aҎ(gu),比如Varargs和Autoboxing。对那些用惯?jin)Java 5的程序员Q这些新的语aҎ(gu)还是很好用的?

SimpleJdbcTemplate cd用Java 5的语法特性带来的好处可以通过一个例子来说明。在下面的代码片断中我们首先使用标准?tt class="classname">JdbcTemplateq行数据讉KQ接下来使用SimpleJdbcTemplate做同L(fng)事情?

// classic JdbcTemplate-style...
public Actor findActor(long id) {
String sql = "select id, first_name, last_name from T_ACTOR where id = ?";
RowMapper mapper = new RowMapper() {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
Actor actor = new Actor();
actor.setId(rs.getLong(Long.valueOf(rs.getLong("id"))));
actor.setFirstName(rs.getString("first_name"));
actor.setLastName(rs.getString("last_name"));
return actor;
}
};
// normally this would be dependency injected of course...
JdbcTemplate jdbcTemplate = new JdbcTemplate(this.getDataSource());
// notice the cast, and the wrapping up of the 'id' argument
// in an array, and the boxing of the 'id' argument as a reference type
return (Actor) jdbcTemplate.queryForObject(sql, mapper, new Object[] {Long.valueOf(id)});
}

下面是同一Ҏ(gu)的另一U实玎ͼ惟一不同之处是我们用了(jin)SimpleJdbcTemplateQ这样代码显得更加清晰?

// SimpleJdbcTemplate-style...
public Actor findActor(long id) {
String sql = "select id, first_name, last_name from T_ACTOR where id = ?";
ParameterizedRowMapper<Actor> mapper = new ParameterizedRowMapper<Actor>() {
// notice the return type with respect to Java 5 covariant return types
public Actor mapRow(ResultSet rs, int rowNum) 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;
}
};
// again, normally this would be dependency injected of course...
SimpleJdbcTemplate simpleJdbcTemplate = new SimpleJdbcTemplate(this.getDataSource());
return simpleJdbcTemplate.queryForObject(sql, mapper, id);
}

11.2.4. DataSource接口

Z(jin)从数据库中取得数据,我们首先需要获取一个数据库q接?Spring通过DataSource对象来完成这个工作?DataSource是JDBC规范的一部分Q?它被视ؓ(f)一个通用的数据库q接工厂。通过使用DataSourceQ?Container或Framework可以连接池以及(qing)事务理的细节从应用代码中分d来?作ؓ(f)一个开发h员,在开发和试产品的过E中Q你可能需要知道连接数据库的细节?但在产品实施Ӟ你不需要知道这些细节。通常数据库管理员?sh)(x)帮你设|好数据源?

在用Spring JDBCӞ你既可以通过JNDI获得数据源,也可以自行配|数据源Q?使用Spring提供的DataSource实现c)(j)。用后者可以更方便的脱Web容器来进行单元测试?q里我们?tt class="classname">DriverManagerDataSourceQ不qDataSource有多U实玎ͼ 后面我们?x)讲到。?tt class="classname">DriverManagerDataSource和你以前获取一个JDBCq接 的做法没什么两栗你首先必须指定JDBC驱动E序的全限定名,q样DriverManager 才能加蝲JDBC驱动c,接着你必L供一个urlQ因JDBC驱动而异Qؓ(f)?jin)保证设|正请参考相关JDBC驱动的文档)(j)Q?最后你必须提供一个用戯接数据库的用户名和密码。下面我们将通过一个例子来说明如何配置一?DriverManagerDataSourceQ?

DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.hsqldb.jdbcDriver");
dataSource.setUrl("jdbc:hsqldb:hsql://localhost:");
dataSource.setUsername("sa");
dataSource.setPassword("");

11.2.5. SQLExceptionTranslator接口

SQLExceptionTranslator是一个接口,如果你需要在 SQLException?tt class="classname">org.springframework.dao.DataAccessException之间作{换,那么必须实现该接口?

转换器类的实现可以采用一般通用的做?比如使用JDBC的SQLState code)Q如果ؓ(f)?jin)转换更准,也可以进行定Ӟ比如使用Oracle的error codeQ?

SQLErrorCodeSQLExceptionTranslator是SQLExceptionTranslator的默认实现?该实C用指定数据库厂商的error codeQ比采用SQLState更精?转换q程Z一个JavaBeanQ类型ؓ(f)SQLErrorCodesQ中的error code?q个JavaBean?tt class="classname">SQLErrorCodesFactory工厂cd建,其中的内Ҏ(gu)自于 "sql-error-codes.xml"配置文g。该文g中的数据库厂商代码基于Database MetaData信息中的 DatabaseProductNameQ从而配合当前数据库的用?

 

SQLErrorCodeSQLExceptionTranslator使用以下的匹配规则:(x)

 

  • 首先(g)查是否存在完成定制{换的子类实现。通常SQLErrorCodeSQLExceptionTranslator q个cd以作Z个具体类使用Q不需要进行定Ӟ那么q个规则不适用?

  • 接着SQLException的error code与错误代码集中的error codeq行匚w?默认情况下错误代码集从SQLErrorCodesFactory取得?错误代码集来自classpath下的sql-error-codes.xml文gQ?它们与数据库metadata信息中的database nameq行映射?

  • 如果仍然无法匚wQ最后将调用fallbackTranslator属性的translateҎ(gu)Q?tt class="classname">SQLStateSQLExceptionTranslatorcd例是默认的fallbackTranslator?

 

SQLErrorCodeSQLExceptionTranslator可以采用下面的方式进行扩展:(x)

public class MySQLErrorCodesTranslator extends SQLErrorCodeSQLExceptionTranslator {
protected DataAccessException customTranslate(String task, String sql, SQLException sqlex) {
if (sqlex.getErrorCode() == -12345) {
return new DeadlockLoserDataAccessException(task, sqlex);
}
return null;
}
}

在上面的q个例子中,error code?tt class="literal">'-12345'的SQLException 采用该转换器进行{换,而其他的error code由默认的{换器q行转换?Z(jin)使用该{换器Q必d其作为参C递给JdbcTemplatec??tt class="literal">setExceptionTranslatorҎ(gu)Qƈ在需要用这个{换器器的数据 存取操作中用该JdbcTemplate?下面的例子演CZ(jin)如何使用该定制{换器Q?

// create a JdbcTemplate and set data source
JdbcTemplate jt = new JdbcTemplate();
jt.setDataSource(dataSource);
// create a custom translator and set the DataSource for the default translation lookup
MySQLErrorCodesTransalator tr = new MySQLErrorCodesTransalator();
tr.setDataSource(dataSource);
jt.setExceptionTranslator(tr);
// use the JdbcTemplate for this SqlUpdate
SqlUpdate su = new SqlUpdate();
su.setJdbcTemplate(jt);
su.setSql("update orders set shipping_charge = shipping_charge * 1.05");
su.compile();
su.update();

在上面的定制转换器中Q我们给它注入了(jin)一个数据源Q因为我们仍焉?使用默认的{换器?tt class="literal">sql-error-codes.xml中获取错误代码集?

11.2.6. 执行SQL语句

我们仅需要非常少的代码就可以辑ֈ执行SQL语句的目的,一旦获得一?DataSource和一?tt class="classname">JdbcTemplateQ?我们可以?tt class="classname">JdbcTemplate提供的丰富功能实现我们的操作?下面的例子用了(jin)极少的代码完成创Z张表的工作?

import javax.sql.DataSource;
import org.springframework.jdbc.core.JdbcTemplate;
public class ExecuteAStatement {
private JdbcTemplate jt;
private DataSource dataSource;
public void doExecute() {
jt = new JdbcTemplate(dataSource);
jt.execute("create table mytable (id integer, name varchar(100))");
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
}

11.2.7. 执行查询

除了(jin)executeҎ(gu)之外Q?tt class="classname">JdbcTemplateq提供了(jin)大量的查询方法?在这些查询方法中Q有很大一部分是用来查询单值的。比如返回一个汇总(countQ结?或者从q回行结果中取得指定列的倹{这时我们可以?tt class="literal">queryForInt(..)?queryForLong(..)或?tt class="literal">queryForObject(..)Ҏ(gu)?queryForObjectҎ(gu)用来返回的JDBCcd对象转换成指定的Java对象Q如果类型{换失败将抛出 InvalidDataAccessApiUsageException异常?下面的例子演CZ(jin)两个查询的用法,一个返?tt class="literal">int|另一个返?String?

import javax.sql.DataSource;
import org.springframework.jdbc.core.JdbcTemplate;
public class RunAQuery {
private JdbcTemplate jt;
private DataSource dataSource;
public int getCount() {
jt = new JdbcTemplate(dataSource);
int count = jt.queryForInt("select count(*) from mytable");
return count;
}
public String getName() {
jt = new JdbcTemplate(dataSource);
String name = (String) jt.queryForObject("select name from mytable", String.class);
return name;
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
}

除了(jin)q回单值的查询Ҏ(gu)Q?tt class="classname">JdbcTemplateq提供了(jin)一l返回Listl果 的方法。List中的每一对应查询返回结果中的一行。其中最单的?tt class="literal">queryForListҎ(gu)Q?该方法将q回一?tt class="interfacename">ListQ该List中的每一?记录是一?tt class="interfacename">Map对象Q对应应数据库中某一行;而该Map 中的每一对应该数据库行中的某一列倹{下面的代码片断接着上面的例子演CZ(jin)如何用该Ҏ(gu)q回表中 所有记录:(x)

public List getList() {
jt = new JdbcTemplate(dataSource);
List rows = jt.queryForList("select * from mytable");
return rows;
}

q回的结果集cM下面q种形式Q?

[{name=Bob, id=1}, {name=Mary, id=2}]

11.2.8. 更新数据?/h3>

JdbcTemplateq提供了(jin)一些更新数据库的方法?在下面的例子中,我们Ҏ(gu)l定的主键值对指定的列q行更新?例子中的SQL语句中用了(jin)“?”占位W来接受参数Q这U做法在更新和查询SQL语句中很常见Q?传递的参数g于一个对象数l中Q基本类型需要被包装成其对应的对象类型)(j)?

import javax.sql.DataSource;
import org.springframework.jdbc.core.JdbcTemplate;
public class ExecuteAnUpdate {
private JdbcTemplate jt;
private DataSource dataSource;
public void setName(int id, String name) {
jt = new JdbcTemplate(dataSource);
jt.update("update mytable set name = ? where id = ?", new Object[] {name, new Integer(id)});
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
}

11.3. 控制数据库连?/h2>

11.3.1. DataSourceUtilsc?/h3>

DataSourceUtils作ؓ(f)一个帮助类提供易用且强大的数据库访问能力, 我们可以使用该类提供?tt class="literal">?rn)?/tt>Ҏ(gu)从JNDI获取数据库连接以?qing)在必要的时候关闭之?它提供支持线E绑定的数据库连接(比如使用DataSourceTransactionManager 的时候,把数据库连接绑定到当前的线E上Q?

注:(x)getDataSourceFromJndi(..)Ҏ(gu)主要用于那些没有使用bean factory 或者application context的场合。如果用application contextQ那么最好是?JndiObjectFactoryBean中配|bean或者直接?JdbcTemplate实例?tt class="classname">JndiObjectFactoryBean 能够通过JNDI获取DataSourceq将 DataSource作ؓ(f)引用参数传递给其他bean?q样Q在不同?tt class="interfacename">DataSource之间切换只需要修攚w|文件即可, 甚至我们可以用一个非JNDI?tt class="interfacename">DataSource来替?FactoryBean定义Q?

11.3.2. SmartDataSource接口

SmartDataSource?tt class="interfacename">DataSource 接口的一个扩展,用来提供数据库连接。用该接口的类在指定的操作之后可以(g)查是否需要关闭连接?该接口在某些情况下非常有用,比如有些情况需要重用数据库q接?

11.3.3. AbstractDataSourcec?/h3>

AbstractDataSource是一个实C(jin)DataSource 接口?tt class="literal">abstract基类。它实现?tt class="interfacename">DataSource接口?一些无关痛痒的Ҏ(gu)Q如果你需要实现自qDataSourceQ那么?该类是个好主意?

11.3.4. SingleConnectionDataSourcec?/h3>

SingleConnectionDataSource?tt class="literal">SmartDataSource接口 的一个实玎ͼ其内部包装了(jin)一个单q接。该q接在用之后将不会(x)关闭Q很昄它不能在多线E?的环境下使用?

当客L(fng)代码调用closeҎ(gu)的时候,如果它L假设数据库连接来自连接池Q就像用持久化工具时一P(j)Q?你应该将suppressClose讄为true?q样Q通过该类获取的将是代理连接(止关闭Q而不是原有的物理q接?需要注意的是,我们不能把用该c获取的数据库连接造型QcastQؓ(f)Oracle Connection之类的本地数据库q接?

SingleConnectionDataSource主要在测试的时候用?它得测试代码很Ҏ(gu)q应用服务器而在一个简单的JNDI环境下运行??tt class="classname">DriverManagerDataSource不同的是Q它始终只会(x)使用同一个数据库q接Q?从而避免每ơ徏立物理连接的开销?

11.3.5. DriverManagerDataSourcec?/h3>

DriverManagerDataSourcecdC(jin) SmartDataSource接口。在applicationContext.xml中可以?bean properties来设|JDBC Driver属性,该类每次q回的都是一个新的连接?

该类主要在测试以?qing)脱J2EE容器的独立环境中使用。它既可以用来在application context中作Z?DataSource beanQ也可以在简单的JNDI环境下用?׃Connection.close()仅仅只是单的关闭数据库连接,因此M能够获取 DataSource的持久化代码都能很好的工作。不q用JavaBean风格的连接池 Q比如commons-dbcpQ也q难事。即使是在测试环境下Q用连接池也是一U比使用 DriverManagerDataSource更好的做法?

11.3.6. TransactionAwareDataSourceProxyc?/h3>

TransactionAwareDataSourceProxy作ؓ(f)目标DataSource的一个代理, 在对目标DataSource包装的同Ӟq增加了(jin)Spring的事务管理能力, 在这一点上Q这个类的功能非常像J2EE服务器所提供的事务化的JNDI DataSource?

[Note] Note

该类几乎很少被用刎ͼ除非现有代码在被调用的时候需要一个标准的 JDBC DataSource接口实现作ؓ(f)参数?q种情况下,q个cd以现有代码参与Spring的事务管理。通常最好的做法是用更高层的抽?来对数据源进行管理,比如JdbcTemplate?tt class="classname">DataSourceUtils{等?

如果需要更详细的资料,请参?tt class="classname">TransactionAwareDataSourceProxy JavaDoc ?/em>

11.3.7. DataSourceTransactionManagerc?/h3>

DataSourceTransactionManagercL PlatformTransactionManager接口的一个实玎ͼ用于处理单JDBC数据源?它将从指定DataSource取得的JDBCq接l定到当前线E,因此它也支持?jin)每个数据源对应C个线E?

我们推荐在应用代码中使用DataSourceUtils.getConnection(DataSource)来获?JDBCq接Q而不是用J2EE标准?tt class="literal">DataSource.getConnection。因为前者将抛出 unchecked?tt class="literal">org.springframework.dao异常Q而不是checked?SQLException异常。Spring Framework中所有的c(比如 JdbcTemplateQ都采用q种做法。如果不需要和q个 DataSourceTransactionManagercM起用,DataSourceUtils 提供的功能跟一般的数据库连接策略没有什么两P因此它可以在M场景下用?

DataSourceTransactionManagercL持定刉ȝ别,以及(qing)对SQL语句查询时的设定?Z(jin)支持后者,应用代码必须使用JdbcTemplate或者在每次创徏SQL语句时调?DataSourceUtils.applyTransactionTimeoutҎ(gu)?

在用单个数据源的情形下Q你可以?tt class="classname">DataSourceTransactionManager来替?tt class="classname">JtaTransactionManagerQ?因ؓ(f)DataSourceTransactionManager不需要容器支持JTA。如果你使用DataSourceUtils.getConnection(DataSource)来获?JDBCq接Q二者之间的切换只需要更改一些配|。最后需要注意的一点就?tt class="classname">JtaTransactionManager不支持隔ȝ别的定制Q?

11.4. 用Java对象来表达JDBC操作

org.springframework.jdbc.object包下的类允许用户以更?面向对象的方式去讉K数据库。比如说Q用户可以执行查询ƈq回一个listQ?该list作ؓ(f)一个结果集把从数据库中取出的列数据映到业务对象的属性上?用户也可以执行存储过E,以及(qing)q行更新、删除以?qing)插入SQL语句?

[Note] Note

在许多Spring开发h员(sh)间存在有一U观点,那就是下面将要提到的各种RDBMS操作c?Q?a title="11.4.4. StoredProcedurec? >StoredProcedurec除外)(j) 通常也可以直接?tt class="classname">JdbcTemplate相关的方法来替换?相对于把一个查询操作封装成一个类而言Q直接调?tt class="classname">JdbcTemplateҎ(gu)更?而且更容易理解?

必须说明的一点就是,q仅仅只是一U?span class="emphasis">观点而已Q?如果你认Z可以从直接用RDBMS操作cM获取一些额外的好处Q?你不妨根据自q需要和喜好q行不同的选择?

11.4.1. SqlQueryc?/h3>

SqlQuery是一个可重用、线E安全的c,它封装了(jin)一个SQL查询?其子cdd?tt class="literal">newResultReader()Ҏ(gu)Q该Ҏ(gu)用来在遍?ResultSet的时候能使用一个类来保存结果?我们很少需要直接?tt class="classname">SqlQueryQ因为其子类 MappingSqlQuery作ؓ(f)一个更加易用的实现能够结果集中的行映ؓ(f)Java对象?SqlQueryq有另外两个扩展分别?MappingSqlQueryWithParameters?tt class="classname">UpdatableSqlQuery?

11.4.2. MappingSqlQueryc?/h3>

MappingSqlQuery是一个可重用的查询抽象类Q其具体cdd?mapRow(ResultSet, int)抽象Ҏ(gu)来将l果集中的每一行{换成Java对象?

?tt class="interfacename">SqlQuery的各U实CQ?MappingSqlQuery是最常用也是最Ҏ(gu)使用的一个?

下面q个例子演示?jin)一个定制查询,它将从客戯中取得的数据映射C?Customercd例?

private class CustomerMappingQuery extends MappingSqlQuery {
public CustomerMappingQuery(DataSource ds) {
super(ds, "SELECT id, name FROM customer WHERE id = ?");
super.declareParameter(new SqlParameter("id", Types.INTEGER));
compile();
}
public Object mapRow(ResultSet rs, int rowNumber) throws SQLException {
Customer cust = new Customer();
cust.setId((Integer) rs.getObject("id"));
cust.setName(rs.getString("name"));
return cust;
}
}

在上面的例子中,我们为用h询提供了(jin)一个构造函数ƈ为构造函C递了(jin)一?DataSource参数。在构造函数里面我们把 DataSource和一个用来返回查询结果的SQL语句作ؓ(f)参数 调用父类的构造函数。SQL语句被用于生成一?tt class="interfacename">PreparedStatement对象Q?因此它可以包含占位符来传递参数。而每一个SQL语句的参数必通过调用 declareParameterҎ(gu)来进行声明,该方法需要一?SqlParameterQ封装了(jin)一个字D名字和一?java.sql.Types中定义的JDBCcdQ对象作为参数?所有参数定义完之后Q我们调?tt class="literal">compile()Ҏ(gu)来对SQL语句q行预编译?

下面让我们看看该定制查询初始化ƈ执行的代码:(x)

public Customer getCustomer(Integer id) {
CustomerMappingQuery custQry = new CustomerMappingQuery(dataSource);
Object[] parms = new Object[1];
parms[0] = id;
List customers = custQry.execute(parms);
if (customers.size() > 0) {
return (Customer) customers.get(0);
}
else {
return null;
}
}

在上面的例子中,getCustomerҎ(gu)通过传递惟一参数id来返回一个客户对象?该方法内部在创徏CustomerMappingQuery实例之后Q?我们创徏?jin)一个对象数l用来包含要传递的查询参数。这里我们只有唯一的一?Integer参数。执?tt class="classname">CustomerMappingQuery?executeҎ(gu)之后Q我们得C(jin)一?tt class="literal">ListQ该List中包含一?Customer对象Q如果有对象满查询条g的话?

11.4.3. SqlUpdatec?/h3>

SqlUpdatecd装了(jin)一个可重复使用的SQL更新操作?跟所?tt class="classname">RdbmsOperationcMPSqlUpdate可以在SQL中定义参数?

该类提供?jin)一pdupdate()Ҏ(gu)Q就像SqlQuery提供的一pdexecute()Ҏ(gu)一栗?

SqlUpdate是一个具体的cR通过在SQL语句中定义参敎ͼq个cd以支?不同的更新方法,我们一般不需要通过l承来实现定制?

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(Types.NUMERIC));
declareParameter(new SqlParameter(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 run(int id, int rating) {
Object[] params =
new Object[] {
new Integer(rating),
new Integer(id)};
return update(params);
}
}

11.4.4. StoredProcedurec?/h3>

StoredProcedurecL一个抽象基c,它是对RDBMS存储q程的一U抽象?该类提供?jin)多U?tt class="literal">execute(..)Ҏ(gu)Q不q这些方法的讉Kcd都是protected的?

从父cȝ承的sql属性用来指定RDBMS存储q程的名字?管该类提供?jin)许多必dJDBC3.0下用的功能Q但是我们更x(chng)的是JDBC 3.0中引入的命名参数Ҏ(gu)?

下面的程序演CZ(jin)如何调用Oracle中的sysdate()函数?q里我们创徏?jin)一个?tt class="classname">StoredProcedure的子c,虽然它没有输入参敎ͼ 但是我必通过使用SqlOutParameter来声明一个日期类型的输出参数?execute()Ҏ(gu)返回一个mapQmap中的每个entry是一个用参数名作keyQ?以输出参Cؓ(f)value的名值对?

import java.sql.Types;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.jdbc.core.SqlOutParameter;
import org.springframework.jdbc.datasource.*;
import org.springframework.jdbc.object.StoredProcedure;
public class TestStoredProcedure {
public static void main(String[] args)  {
TestStoredProcedure t = new TestStoredProcedure();
t.test();
System.out.println("Done!");
}
void test() {
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName("oracle.jdbc.OracleDriver");
ds.setUrl("jdbc:oracle:thin:@localhost:1521:mydb");
ds.setUsername("scott");
ds.setPassword("tiger");
MyStoredProcedure sproc = new MyStoredProcedure(ds);
Map results = sproc.execute();
printMap(results);
}
private class MyStoredProcedure extends StoredProcedure {
private static final String SQL = "sysdate";
public MyStoredProcedure(DataSource ds) {
setDataSource(ds);
setFunction(true);
setSql(SQL);
declareParameter(new SqlOutParameter("date", Types.DATE));
compile();
}
public Map execute() {
// the 'sysdate' sproc has no input parameters, so an empty Map is supplied...
return execute(new HashMap());
}
}
private static void printMap(Map results) {
for (Iterator it = results.entrySet().iterator(); it.hasNext(); ) {
System.out.println(it.next());
}
}
}

下面?tt class="classname">StoredProcedure的另一个例子,它用了(jin)两个Oracle游标cd的输出参数?

import oracle.jdbc.driver.OracleTypes;
import org.springframework.jdbc.core.SqlOutParameter;
import org.springframework.jdbc.object.StoredProcedure;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
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 execute() {
// again, this sproc has no input parameters, so an empty Map is supplied...
return super.execute(new HashMap());
}
}

值得注意的是TitlesAndGenresStoredProcedure构造函C declareParameter(..)?tt class="classname">SqlOutParameter参数Q?该参C用了(jin)RowMapper接口的实现?q是一U非常方便而强大的重用方式?下面我们来看一?tt class="interfacename">RowMapper的两个具体实现?

首先?tt class="classname">TitleMapperc,它简单的?tt class="interfacename">ResultSet中的每一行映ؓ(f)一?tt class="classname">Title Domain Object?

import com.foo.sprocs.domain.Title;
import org.springframework.jdbc.core.RowMapper;
import java.sql.ResultSet;
import java.sql.SQLException;
public final class TitleMapper implements RowMapper {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
Title title = new Title();
title.setId(rs.getLong("id"));
title.setName(rs.getString("name"));
return title;
}
}

另一个是GenreMapperc,也是非常单的?tt class="interfacename">ResultSet中的每一行映ؓ(f)一?tt class="classname">Genre Domain Object?

import org.springframework.jdbc.core.RowMapper;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.foo.domain.Genre;
public final class GenreMapper implements RowMapper {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
return new Genre(rs.getString("name"));
}
}

如果你需要给存储q程传输入参敎ͼq些输入参数是在RDBMS存储q程中定义好?jin)的Q, 则需要提供一个指定类型的execute(..)Ҏ(gu)Q?该方法将调用基类?tt class="literal">protected execute(Map parameters)Ҏ(gu)?例如Q?

import oracle.jdbc.driver.OracleTypes;
import org.springframework.jdbc.core.SqlOutParameter;
import org.springframework.jdbc.object.StoredProcedure;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
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);
declaraParameter(new SqlParameter(CUTOFF_DATE_PARAM, Types.DATE);
declareParameter(new SqlOutParameter("titles", OracleTypes.CURSOR, new TitleMapper()));
compile();
}
public Map execute(Date cutoffDate) {
Map inputs = new HashMap();
inputs.put(CUTOFF_DATE_PARAM, cutoffDate);
return super.execute(inputs);
}
}

11.4.5. SqlFunctionc?/h3>

SqlFunction RDBMS操作cd装了(jin)一个SQL“函数”包装器(wrapperQ, 该包装器适用于查询ƈq回一个单行结果集。默认返回的是一?tt class="literal">int| 不过我们可以采用cMJdbcTemplate中的queryForXxx 做法自己实现来返回其它类型?tt class="classname">SqlFunction优势在于我们不必创徏 JdbcTemplateQ这些它都在内部替我们做?jin)?

该类的主要用途是调用SQL函数来返回一个单值的l果集,比如cM“select user()”?“select sysdate from dual”的查询。如果需要调用更复杂的存储函敎ͼ 可以使用StoredProcedure?tt class="classname">SqlCall?

SqlFunction是一个具体类Q通常我们不需要它的子cR?其用法是创徏该类的实例,然后声明SQL语句以及(qing)参数可以调用相关的runҎ(gu)dơ执行函数?下面的例子用来返回指定表的记录行敎ͼ(x)

public int countRows() {
SqlFunction sf = new SqlFunction(dataSource, "select count(*) from mytable");
sf.compile();
return sf.run();
}


飞飞 2008-08-12 15:31 发表评论
]]>
Spring MVC:视图解析器的讄http://m.tkk7.com/176142998/archive/2008/08/11/221342.html飞飞飞飞Mon, 11 Aug 2008 09:20:00 GMThttp://m.tkk7.com/176142998/archive/2008/08/11/221342.htmlhttp://m.tkk7.com/176142998/comments/221342.htmlhttp://m.tkk7.com/176142998/archive/2008/08/11/221342.html#Feedback0http://m.tkk7.com/176142998/comments/commentRss/221342.htmlhttp://m.tkk7.com/176142998/services/trackbacks/221342.html

视图解析器的一些属?/span>

<bean id="viewResolver"

      class="org.springframework.web.servlet.view.InternalResourceViewResolver">

    <property name="exposeSpringMacroHelpers" value="true"/>

    <property name="requestContextAttribute" value="rc"/>

    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>

    <property name="prefix" value="/"/>

    <property name="suffix" value=".jsp"/>

</bean>

在视图解析器的定义中Q?#8220;exposeSpringMacroHelpers”讄是否通过Spring的宏库暴露一?/span>RequestContext(名ؓ(f)springBindRequestContext)供外部用,默认gؓ(f)false。它暴露?jin)处理表单和验证错误信息的宏操作Q?/span>

requestContextAttribute”?/span>Spring?/span>RequestContext对象暴露为变?/span>rc。利?/span>${rc.contextPath}来获取应用程序的contextPath(也就?/span>/MyUsers)Q利?/span>${rc.getMessage("user.name")}d/WEB-INF/classes/messages.properties本地化信息。此对象对于那些不访?/span>serlveth?/span>View技?/span>(也就?/span>Velocity?/span>FreeMarker模板)来说是必不可的?/span>

q有一些属性:(x)

exposeRequestAttributesQ默认?/span>falseQ设|是否所有的request属性在与模板进行合q之前添加到model中。(可以理解?/span>request范围内包含的所有对象,而不是一个真正的Request对象。)(j)

exposeSessionAttributesQ默认?/span>falseQ设|是否所有的session属性在与模板进行合q之前添加到model中。(理解同上Q?/span>



飞飞 2008-08-11 17:20 发表评论
]]> վ֩ģ壺 ˳Ƶ| ˳վ| ޾Ʒþþ| ĻȫƵ | ĻӰ| ޹AVһ| ޾Ʒþ| ޾ƷŮþþ| ղƷϵ| Ů˱ŮˬƵ| ëƬѹۿ| þþþþһ| պëƬѹۿ| ŷպĸwww777| ޹˾ƷӰ| ŮƵվ| ˾þں2019| þþƷۺɫ| һ| Ұһ| 777777| ߲ѲavƬ| ߹ۿaվ| պƷƬҹѹ| һëƬѿ| һƵ| þùƷ| ߳ˮ| þþƷѲ| selaobanƵѾƷ| 72paoƵ| jizzӰӹۿվ| 9ȾƷѹۿƵ| պAVһl| պƷһ߹ۿ| պһƬѹۿ| պƷר| ˾ƷѴȫ| 㶮ַѹ| һëƬѲ| պһ|