各们帮忙看一下,为什么spring引用不到jdbctemplate 事务

Spring JDBC模板类—org.springframework.jdbc.core.JdbcTemplate - JustDoMyself - ITeye技术网站
博客分类:
今天看了下Spring的源码——关于JDBC的"薄"封装,Spring 用一个Spring JDBC模板类来封装了繁琐的JDBC操作。下面仔细讲解一下Spring JDBC框架。
一、首先看一下为什么要对JDBC进行封装?
传统的JDBC API实现比较底层,不管用户执行一个复杂的数据库操作还是一个简单的数据库查询操作,都有一个模板可以使用:捕获或抛出异常—获取连接—创建Statement或PreparedStatement—执行数据库操作—获取结果(ResultSet)—其他操作—处理异常—关闭ResultSet—关闭Statement或PreparedStatement—关闭连接。这样的重复操作会让人比较有结构感的同时也消耗了大量的时间。既然所有的数据库操作都可以引用这一模板。那Spring就对JDBC API进行了一层"薄"封装,让程序员脱离繁琐的结构而只编写各个数据库操作程序中的核心部分:CRUD。通过在配置文件中配置数据源来获取连接。这样就减少了那些在传统JDBC编程中的重复编程,让这部分重复交由Spring JDBC容器来处理。
二、Spring JDBC封装是怎样的?
Spring JDBC是提供了一个数据库操作的模板类JdbcTemplate来进行封装的。org.springframework.jdbc.core.JdbcTemplate extends JdbcAccessor implements JdbcOperations 。下面我们来具体看一下这个封装类:
1、JdbcAccessor 是一个抽象类,实现了InitializingBean接口。InitializingBean接口实现了对BeanFactory中的所有属性设置后的响应。JdbcAccessor实现InitializingBean的唯一方法afterPropertiesSet来对设置数据源和其他的日志信息和异常信息和是否是LazyInit(懒加载)。
2、JdbcOperations是一个接口。这个接口定义了一个JDBC操作的集合,多数用回调来对操作进行定义。下面就是其中的方法定义,基本上也可以作为SpringJDBC的文档进行阅读。
JdbcOperations 方法定义
处理简单连接Connection
Object execute(ConnectionCallback action)
处理静态查询Statement
Object execute(StatementCallback action)
void execute(String sql)
Object query(String sql, ResultSetExtractor rse)
void query(String sql, RowCallbackHandler rch)
List query(String sql, RowMapper rowMapper)
Object queryForObject(String sql, RowMapper rowMapper)
Object queryForObject(String sql, Class requiredType)
Map queryForMap(String sql)
long queryForLong(String sql)
int queryForInt(String sql)
List queryForList(String sql, Class elementType)
List queryForList(String sql)
SqlRowSet queryForRowSet(String sql)
int update(String sql)
int[] batchUpdate(String[] sql)
处理PreparedStatement
Object execute(PreparedStatementCreator psc, PreparedStatementCallback action)
Object execute(String sql, PreparedStatementCallback action)
Object query(PreparedStatementCreator psc, ResultSetExtractor rse)
Object query(String sql, PreparedStatementSetter pss, ResultSetExtractor rse)
Object query(String sql, Object[] args, int[] argTypes, ResultSetExtractor rse)
Object query(String sql, Object[] args, ResultSetExtractor rse)
void query(PreparedStatementCreator psc, RowCallbackHandler rch)
void query(String sql, PreparedStatementSetter pss, RowCallbackHandler rch)
void query(String sql, Object[] args, int[] argTypes, RowCallbackHandler rch)
void query(String sql, Object[] args, RowCallbackHandler rch)
List query(PreparedStatementCreator psc, RowMapper rowMapper)
List query(String sql, PreparedStatementSetter pss, RowMapper rowMapper)
List query(String sql, Object[] args, int[] argTypes, RowMapper rowMapper)
List query(String sql, Object[] args, RowMapper rowMapper)
Object queryForObject(String sql, Object[] args, int[] argTypes, RowMapper rowMapper)
Object queryForObject(String sql, Object[] args, RowMapper rowMapper)
Object queryForObject(String sql, Object[] args, int[] argTypes, Class requiredType)
Object queryForObject(String sql, Object[] args, Class requiredType)
Map queryForMap(String sql, Object[] args, int[] argTypes)
Map queryForMap(String sql, Object[] args)
long queryForLong(String sql, Object[] args, int[] argTypes)
long queryForLong(String sql, Object[] args)
int queryForInt(String sql, Object[] args, int[] argTypes)
int queryForInt(String sql, Object[] args)
List queryForList(String sql, Object[] args, int[] argTypes, Class elementType)
List queryForList(String sql, Object[] args, Class elementType)
List queryForList(String sql, Object[] args, int[] argTypes)
List queryForList(String sql, Object[] args)
SqlRowSet queryForRowSet(String sql, Object[] args, int[] argTypes)
SqlRowSet queryForRowSet(String sql, Object[] args)
int update(PreparedStatementCreator psc, KeyHolder generatedKeyHolder)
int update(String sql, PreparedStatementSetter pss)
int update(String sql, Object[] args, int[] argTypes)
int update(String sql, Object[] args)
int[] batchUpdate(String sql, BatchPreparedStatementSetter pss)
处理callable Statement
Object execute(CallableStatementCreator csc, CallableStatementCallback action)
Object execute(String callString, CallableStatementCallback action)
Map call(CallableStatementCreator csc, List declaredParameters)
上面的所有方法均throws DataAccessE
3、DataAccessException继承NestedRuntimeException,NestedRuntimeException继承RuntimeException,主要输出异常信息。异常类都不会自己实现太多的方法而是一般调用父类方法来进行实现,只是更细化相应信息的输出和传入相应参数到父类方法进行执行。
4、大家可以看到上述方法很多是用回调来作为参数,而具体在JdbcTemplate中方法的实现还是利用传统的JDBC API中的Connection、Statement、PreparedStatement、ResultSet等类和相应的方法来进行实现回调。
下载次数: 267
浏览: 47376 次
来自: 贵阳
mark,多谢分享了
{name=罗*, birthday=Fri May 21 1 ...
写的很详细啊,赞一个
/?(\w*)/(\w*).do
第一个【类】
第二个【方法】 ...
如果和nginx的try_files结合使用,就可以实现静态化 ...使用 JdbcTemplate 动态创建表并添加数据 - java小强 - ITeye技术网站
博客分类:
之前写了一个 ,按月动态生成表 ,但是他并不能进行公用,使用时需要每个人都写自己的处理代码,为了方便使用,我写了一个公共的处理方法,仅供参考。
为了考虑大家项目的集成,获得JdbcTemplate我采用Spring配置,也为了方便大家直接运行,初始化Spring的方式是写的Main方法
主要思路是:
使用Spring配置JdbcTemplate
通过一个代理对象和数据库进行对应,这个对象除了id和一个tableName属性外和数据库的字段名称都是一致的
通过一个公共方法类来获得代理类有那些属性,用来创建表和新增时进行动态SQL的拼装
核心处理是,先看有么有该表,没有创建插入,有的话直接插入
首先配置Spring,大家都会的:
&?xml version="1.0" encoding="UTF-8"?&
&beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"&
&!-- 数据源 --&
&bean id="dataSource"
class="mons.dbcp.BasicDataSource"
destroy-method="close"&
&property name="driverClassName" value="com.mysql.jdbc.Driver" /&
&property name="url"
value="jdbc:mysql://192.168.0.69:3306/cui?useUnicode=true&characterEncoding=UTF-8" /&
&property name="username" value="root" /&
&property name="password" value="root" /&
&!-- 连接池启动时的初始值 --&
&property name="initialSize" value="2" /&
&!-- 连接池的最大值 --&
&property name="maxActive" value="2" /&
&!-- 最大空闲值.当经过一个高峰时间后,连接池可以慢慢将已经用不到的连接慢慢释放一部分,一直减少到maxIdle为止 --&
&property name="maxIdle" value="2" /&
最小空闲值.当空闲的连接数少于阀值时,连接池就会预申请去一些连接,以免洪峰来时来不及申请 --&
&property name="minIdle" value="2" /&
&property name="defaultAutoCommit" value="true" /&
&!-- JDBC 操作模板 --&
&bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"&
&constructor-arg&
&ref bean="dataSource"/&
&/constructor-arg&
&!-- 用于初始化获得Spring对象的类 --&
&bean id="springfactory" class="com.SpringFactory"&&/bean&
com.SpringFactory对象是用来动态获取Spring管理对象的类,之前博客中提到过:
import org.springframework.beans.BeansE
import org.springframework.context.ApplicationC
import org.springframework.context.ApplicationContextA
* @说明 获得Spring管理对象
* @author cuisuqiang
* @version 1.0
public class SpringFactory implements ApplicationContextAware {
private static ApplicationC
@SuppressWarnings("static-access")
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.context = applicationC
public static Object getObject(String id) {
Object object =
object = context.getBean(id);
这个类可以根据配置的对象ID来获得该对象的引用
我们还需要将参数中对象进行处理,获得对象的属性名称和对应的值,这里提供了一个公共方法,之前博客提到过,只是改动了一些:
import java.lang.reflect.F
import java.lang.reflect.M
import java.util.HashM
import java.util.M
* @说明 对象操纵高级方法
* @author cuisuqiang
* @version 1.0
public class ObjectUtil {
* 返回一个对象的属性和属性值
@SuppressWarnings("unchecked")
public static Map&String,String& getProperty(Object entityName) {
Map&String,String& map = new HashMap&String, String&();
Class c = entityName.getClass();
// 获得对象属性
Field field[] = c.getDeclaredFields();
for (Field f : field) {
Object v = invokeMethod(entityName, f.getName(), null);
map.put(f.getName(), v.toString());
} catch (Exception e) {
* 获得对象属性的值
@SuppressWarnings("unchecked")
private static Object invokeMethod(Object owner, String methodName,
Object[] args) throws Exception {
Class ownerClass = owner.getClass();
methodName = methodName.substring(0, 1).toUpperCase()
+ methodName.substring(1);
Method method =
method = ownerClass.getMethod("get" + methodName);
} catch (SecurityException e) {
} catch (NoSuchMethodException e) {
return " can't find 'get" + methodName + "' method";
return method.invoke(owner);
传递一个对象,就会返回该对象的属性和属性值的Map
再来看一下对象实体类,要注意这个类一定不要和实际的类混了,因为你的业务对象类中可能会有一些额外的字段,这个会被公共方法的类解析而出问题的
* @说明 需要操作的实体
* @author cuisuqiang
* @version 1.0
* @since 这个只能是代理对象,也就是说你需要和数据库同步对属性字段,实际上我们在表中还动态添加了一个 tableName 字段
public class Users {
private String userN
private String userP
public String getUserName() {
return userN
public void setUserName(String userName) {
this.userName = userN
public String getUserPass() {
return userP
public void setUserPass(String userPass) {
this.userPass = userP
也就是说数据会有四个字段 id,userName,userPass,tableName,其中id和tableName是无需关心的
核心处理类我先发代码:
import java.sql.C
import java.sql.DatabaseMetaD
import java.sql.ResultS
import java.text.SimpleDateF
import java.util.D
import java.util.M
import java.util.S
import org.springframework.context.ApplicationC
import org.springframework.context.support.ClassPathXmlApplicationC
import org.springframework.jdbc.core.JdbcT
* @说明 进行测试
* @author cuisuqiang
* @version 1.0
public class DbTest {
private static ApplicationContext context =
public static void main(String[] args) {
context = new ClassPathXmlApplicationContext("applicationContext.xml");
Users user = new Users();
user.setUserName("");
user.setUserPass("/");
int re = insertObject("users",user);
System.out.println("----&" + re + "&----");
public static int insertObject(String tableName,Object obj){
int re = 0;
JdbcTemplate jt = (JdbcTemplate)context.getBean("jdbcTemplate");
SimpleDateFormat format = new SimpleDateFormat("yyyy_MM");
String tname = tableName + "_" + format.format(new Date());
// 如果有某表
if(getAllTableName(jt,tname)){
// 保存数据
re = saveObj(jt,tname,obj);
// 动态创建表
re = createTable(jt,tname,obj);
// 保存数据
re = saveObj(jt,tname,obj);
} catch (Exception e) {
e.printStackTrace();
* 保存方法,注意这里传递的是实际的表的名称
public static int saveObj(JdbcTemplate jt,String tableName,Object obj){
int re = 0;
String sql = " insert into " + tableName + " (";
Map&String,String& map = ObjectUtil.getProperty(obj);
Set&String& set = map.keySet();
for(String key : set){
sql += (key + ",");
sql += " tableName ) ";
sql += " values ( ";
for(String key : set){
sql += ("'" + map.get(key) + "',");
sql += ("'" + tableName + "' ) ");
re = jt.update(sql);
} catch (Exception e) {
e.printStackTrace();
* 根据表名称创建一张表
* @param tableName
public static int createTable(JdbcTemplate jt,String tableName,Object obj){
StringBuffer sb = new StringBuffer("");
sb.append("CREATE TABLE `" + tableName + "` (");
sb.append(" `id` int(11) NOT NULL AUTO_INCREMENT,");
Map&String,String& map = ObjectUtil.getProperty(obj);
Set&String& set = map.keySet();
for(String key : set){
sb.append("`" + key + "` varchar(255) DEFAULT '',");
sb.append(" `tableName` varchar(255) DEFAULT '',");
sb.append(" PRIMARY KEY (`id`)");
sb.append(") ENGINE=InnoDB DEFAULT CHARSET=utf8;");
jt.update(sb.toString());
} catch (Exception e) {
e.printStackTrace();
* 查询数据库是否有某表
* @param cnn
* @param tableName
* @throws Exception
@SuppressWarnings("unchecked")
public static boolean getAllTableName(JdbcTemplate jt,String tableName) throws Exception {
Connection conn = jt.getDataSource().getConnection();
ResultSet tabs =
DatabaseMetaData dbMetaData = conn.getMetaData();
{ "TABLE" };
tabs = dbMetaData.getTables(null, null, tableName, types);
if (tabs.next()) {
} catch (Exception e) {
e.printStackTrace();
tabs.close();
conn.close();
动态检查是否有某表和动态创建表之前博客有提到,最主要的就是根据对象属性Map进行动态SQL拼装
但是这里这个方法有很多的限制,比如创建字段的长度,新增时字段就必须有值,因为动态SQL会进行全量字段插入
另外,新增的字段表的名称是为了之后删除和查询详细做准备的
请您到ITEYE看我的原创:
或支持我的个人博客,地址:
cuisuqiang
浏览: 1100123 次
来自: 北京
浏览量:941367
学习了 谢谢哦
不错,简单易懂,试验成功查看:652|回复:3
助理工程师
弱弱的请教一下,大家是否是遇到这么一个问题??用 spring JdbcTemplate 进行嵌套查询时,会报错??如下::String sql = &SELECT * FROM store WHERE id in &
+&(select store_id from&&store2user WHERE user_id=?)&;
return jdbcTemplate.queryForList(sql, userId);
报错如下:
SQL [SELECT * FROM store WHERE id in select store_id from store2user WHERE user_id=?]; Parameter index out of range (1 & number of parameters, which is 0).; nested exception is java.sql.SQLException: Parameter index out of range (1 & number of parameters, which is 0).]
这个是怎么解决的???(我使用这条语句在 navcat 上执行没有问题的。)谢谢
助理工程师
直接把userid的值放到sql语句里面 最好用单引号括起来 别用? 试下应该可以的乏
你这个?好像是全角的问号啊,另外,in后面的语句用()括起来,
SELECT * FROM store WHERE id in (select store_id from store2user WHERE user_id=?)
助理工程师
引用:原帖由 z 于
14:55 发表
你这个?好像是全角的问号啊,另外,in后面的语句用()括起来,
SELECT * FROM store WHERE id in (select store_id from store2user WHERE user_id=?) 这个与 “?”号没有关系的,sql 的子查询我也用()里,不过还是不行。我将这两个查询分成两次来实现了。转载:为什么使用ibatis而不用spring jdbcTemplate - 魔豆 - 博客园
第一:ibatis仅仅是对jdbc薄薄的一层封装,完全不丧失sql的灵活性 第二:ibatis所有的sql都可以放在配置文件中,这样有利于sql的集中管理,特别是在sql tuning是很容易把得到所有的sql,如果使用spring jdbctemplate,那么难免要在sql adv上调试好了sql,然后在粘贴到java代码中,会有一大堆的StringObj+=和 StringBufferObj.append() ,如果sql 很长,那么总是copy , paste 也很烦,ibatis没有这样的问题。 第三:ibatis可以把查出的结果集自动mapping成po,不用写一行代码,只需配置一下ResultMap参数即可,而jdbcTemplate大多数情况都要手动的mapping或者实现MappingSqlQuery,ResultSetExtractor等,无论如何都要编程,这些都是体力活,如果使用了ibatis,这些体力活完全可以省去。 第四:ibatis内置cache机制,同时还可以和osCache集成,cache的也是可以配置的,如果配置得当可以大大提高程序性能。 第五:ibatis支持动态sql,不需要在java里有那么多if, else,完全配置
原文地址:Spring中使用纯JDBC连接数据库的配置 - 吾生也有涯,而知也无涯 - ITeye技术网站
博客分类:
最近学习了如何配置在spring中使用单纯的jdbc连接数据库(不用hibernate等持久层框架),记录了一下几个关键的地方,备自己和有需之人查阅。
首先,在spring 的applicationContext配置文件中,需要配置数据源:
&bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"&
&property name="locations"&
&value&classpath*:jdbc.properties&/value&
&/property&
&!-- dbcp pool config --&
&bean id="dataSource"
class="mons.dbcp.BasicDataSource"
destroy-method="close"&
&property name="maxIdle" value="${jdbc.maxIdle}"&&/property&
&property name="maxActive" value="${jdbc.maxActive}"&&/property&
&property name="maxWait" value="${jdbc.maxWait}"&&/property&
&property name="minIdle" value="${jdbc.minIdle}"&&/property&
&property name="driverClassName"
value="${jdbc.driverClassName}"&
&/property&
&property name="url" value="${jdbc.url}"&&/property&
&property name="username" value="${jdbc.username}"&&/property&
&property name="password" value="${jdbc.password}"&&/property&
&/bean&
我想上面的东西不用解释了吧,用的是dbcp的连接池。
然后,spring提供了一个JDBC的DaoSupport可供我们使用,就像集成hibernate时提供的hibernate的DaoSupport一样。这里叫JdbcDaoSupport。假设我们有个叫我们像如下的方式使用:
public class ImplBaseDao extends JdbcDaoSupport implements BaseDao {
public List get(String ID) {
}
因为完全是一个Demo,所以BaseDao这个接口里面只有一个名为get的方法。
public interface BaseDao {
public List get(String ID);
}
然后,具体的业务dao都可以继承自ImplBaseDao
public class PassengerInfoDao extends ImplBaseDao {
public List&PassengerInfo& list = new ArrayList&PassengerInfo&();
@SuppressWarnings("unchecked")
public List&PassengerInfo& getPassengerInfo(String id) {
String sql = "select * from passengerinfo where id="+
return (List&PassengerInfo&) this.getJdbcTemplate().query(sql,
new PassengerInfoMapper());
}
我惊叹spring的地方在于,对于this.getJdbcTemplate().query(sql,new PassengerInfoMapper());这句话中,第二个参数new PassengerInfoMapper()来自于spring提供一个接口的实现:
import java.sql.ResultS
import java.sql.SQLE
import org.springframework.jdbc.core.RowM
import com.travelsky.web.pojo.PassengerI
public class PassengerInfoMapper implements RowMapper {
public Object mapRow(ResultSet rs, int index) throws SQLException {
PassengerInfo passengerInfo = new PassengerInfo();
passengerInfo.setId(rs.getInt("id"));
passengerInfo.setPaName(rs.getString("paName"));
return passengerI
}
可以看见,通过这样的方式,实现了bean与rs的一个转换,虽然很原始,但是这样做比我们完全靠自己去写还是要方便很多。
好了,说说spring集成jdbc的事务和配置和对dao的托管。
在applicationContext中
&!-- 事务管理 --&
&bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"&
&property name="dataSource"&
&ref bean="dataSource" /&
&/property&
&bean id="transactionInterceptor"
class="org.springframework.transaction.interceptor.TransactionInterceptor"&
&property name="transactionManager" ref="transactionManager" /&
&property name="transactionAttributes"&
&!-- 定义规则 --&
&prop key="*"&PROPAGATION_REQUIRED,-Exception&/prop&
&prop key="get*"&PROPAGATION_REQUIRED,readOnly&/prop&
&/property&
&bean id="transactionProxyCreator"
class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"&
&property name="beanNames"&
&value&*Service&/value&
&/property&
&property name="interceptorNames"&
&value&transactionInterceptor&/value&
此处增加新的Interceptor
&/property&
class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor"&
&property name="transactionInterceptor"
ref="transactionInterceptor" /&
&/bean&
以上是对事务的配置,大同小异,不明白的可以参照相关spring事务配置说明的文档。
接下来是对dao service action等我们常见类型bean的托管。
其实很简单了,不写大家都会。
&!-- project实例配置 start --&
&bean id="baseDao" class="com.travelsky.web.core.dao.ImplBaseDao"&
&property name="dataSource"&
&ref bean="dataSource" /&
&/property&
&bean id="JdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"&
&property name="dataSource"&
&ref bean="dataSource"/&
&/property&
&!-- 将所有的dao按顺序配置在这个地方 --&
&bean id="passengerInfoDao"
class="com.travelsky.web.dao.PassengerInfoDao"&
&property name="dataSource"&
&ref bean="dataSource"/&
&/property&
&!-- 给其直接配置dataSource或者配置jdbcTemplate都可以实现与数据源的引用--&
&property name="jdbcTemplate"&
&ref bean="JdbcTemplate"/&
&/property&
&!-- 将所有的service按顺序配置在这个地方 --&
&bean id="passengerInfoService"
class="com.travelsky.web.service.PassengerInfoService"&
&property name="passengerInfoDao"&
&ref bean="passengerInfoDao" /&
&/property&
&!-- 将所有的action配置在这个地方 --&
&bean name="/painfo"
class="com.travelsky.web.web.PassengerInfoAction"&
&property name="passengerInfoService"&
&ref bean="passengerInfoService" /&
&/property&
&!-- project实例配置 end --&
好了,写到这里,该结束了。
浏览: 192658 次
来自: 北京
动态方法貌似只能用!不能使用其他的么
自定义字体生成的pdf文件很大啊,怎么解?
字间距怎么设?}

我要回帖

更多关于 spring4 jdbctemplate 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信