小码农的代码(二)----------SpringJDBC事务控制
2016-01-27 17:34
537 查看
今年年初遇到一个对接ERP与WMS的项目,只做后端数据同步,不进行页面展示,简而言之就是我们接收ERP http请求传送过来的数据然后转存到自己的数据库并将数据同步到WMS系统的数据库中,(ps:我也比较奇怪为什么不直接用http请求进行对接,而来中间再转存一次)。由于项目较小又不需要前端展示就直接只用SpringJDBC进行数据库操作,项目涉及的内容包括http请求接口的开发、多数据库操作,本文先拉出来整理下SpringJDBC的直接使用。
SpringJDBC的使用目前来看非常简单,主要就是三个步骤。
一、maven加载所需要的jar包;
一、Spring配置文件进行数据源与jdbctemple的配置;
二、直接在数据访问层使用。
以下是spring配置文件的内容:
Java代码
<!-- 引入属性文件 -->
<context:property-placeholder location="classpath:config.properties" />
<!-- 自动扫描dao和service包( 自动注入) -->
<context:component-scan base-package="com.zh.demo" />
<!-- 数据连接池C3P0 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="${jdbc.driverClass}" />
<property name="jdbcUrl" value="${jdbc.jdbcUrl}" />
<property name="user" value="${jdbc.user}" />
<property name="password" value="${jdbc.password}" />
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
这里的注意点在于spring的数据源配置,不直接使用DriverManagerDataSource的原因是由于其没有实现连接池的机制,因此使用C3P0,这时需要加载c3p0的支持JAR包;
另外在数据访问层进行数据操作时如下:
Java代码
public class BaseDaoImpl implements BaseDao{
@Autowired
private JdbcTemplate jdbcTemplate;
/**
* sql = "insert into user (name,age) values(?,?)"
* */
public void addBySql(String sql,final Object[] params) {
//--------------methods01------------------------------------//
jdbcTemplate.execute(sql);
//-----------------or methods02------------------------------//
//just like updateBySql
}
/**
* sql = “update table_name set name=?,age=?”
* */
public void updateBySql(String sql,final Object[] params) {
//--------------methods01------------------------------------//
jdbcTemplate.update(sql,
new PreparedStatementSetter() {
public void setValues(PreparedStatement ps)
throws SQLException {
ps.setInt(1, Integer.parseInt(params[0].toString()));
}
});
//-----------------or methods02------------------------------//
//jdbcTemplate.update(sql, params);
}
/**
* sql = "delete user where id =? and name = ?;"
* */
public void deleteBySql(String sql,final Object[] params) {
//----------just like update---------------//
jdbcTemplate.update(sql, params);
}
/**
* RowMapper接口封装返回集合,可自定义
* */
public List<UserEntity> getQueryBySql(String sql) {
return (List<UserEntity>) jdbcTemplate.query(sql,
new BeanPropertyRowMapper<UserEntity>(UserEntity.class));
}
}
因为Spring配置文件中已经配置,可以直接依赖注入jdbcTemplate;
另外也可以继承JdbcDaoSupport类,来使用jdbcTemplate,
Java代码
public class BaseDaoImpl2 extends JdbcDaoSupport implements BaseDao{
public void addBySql(String sql,final Object[] params) {
this.getJdbcTemplate().update(sql);
}
}
。
这两个类进一步论证一个接口可以有多个实现类,谁实例化则调用哪个实现类中的方法。
具体的代码例子与测试文件可以下载附件参考,欢迎大家斧正。
另外对于jdbcTemplate的事务控制就是使用Spring对于事务的控制,具体内容会在后续文章中补充说明。
SpringJDBC.rar (20.5 KB)
下载次数: 3
继续上一篇文章中所述项目的代码整理学习,前面提到直接使用springJDBC的进行数据层的操作,事务控制是必须要有的,那么这里整理一下之前使用的事务控制内容。
首先Spring的事务控制是很完善的,能够满足本人目前遇到的几乎所有项目,具体的内容就不展开论述了,因为太多了
。这里贴一张图,基本就可以理清Spring事务控制的最基本配置。本图来源于博客园
由于实际项目周期的问题以及个人习惯能注解就注解=。=,当然因为某种原因,这里并不是使用纯注解的方式进行事务配置,而是使用了tx拦截器的方式进行声明式事务配置(入乡随俗,充分利用Spring特色),其中运用到的aop面向切面编程后续文章中会专门对他的aspectj代理机制进行总结,这里就不对其展开代码编写试验了,当然这里的项目aspectjweaver的JAR包是肯定要添加的
。
首先由于是直接使用SpringJdbc因而使用DataSourceTransactionManager进行事务管理
Java代码
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>其次自然需要开启tx标签注解事务
[code="java<!-- 开启注解事务 只对当前配置文件有效 -->
<tx:annotation-driven transaction-manager="transactionManager" />
<!-- 事务管理配置 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="create*" propagation="REQUIRED" />
<tx:method name="insert*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
<tx:method name="remove*" propagation="REQUIRED" />
<tx:method name="cancel*" propagation="REQUIRED" />
<tx:method name="get*" propagation="REQUIRED" read-only="true" />
<tx:method name="query*" propagation="REQUIRED" read-only="true" />
<tx:method name="find*" propagation="REQUIRED" read-only="true" />
<tx:method name="load*" propagation="REQUIRED" read-only="true" />
<tx:method name="count*" propagation="REQUIRED" read-only="true" />
<tx:method name="list*" propagation="REQUIRED" read-only="true" />
<tx:method name="*" read-only="true" />
</tx:attributes>
</tx:advice>
最后开启Aop的监听与监听切面
Java代码
<aop:aspectj-autoproxy expose-proxy="true" /><aop:config expose-proxy="true">
<!-- 只对业务逻辑层实施事务 -->
<aop:pointcut id="txPointcut"
expression="execution(* com.zh..service.impl.*ServiceImpl.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut" />
</aop:config>
这样配置就结束了。对于不想使用切面直接使用纯注解方式后续的文章总结中可以尝试使用。
接下去就可以展开编码测试了,在上文的基础上新建了Service类,并加入@service注解,使得调用的时候可以自动注入
Java代码
@Service("userService")
public class UserServiceImpl implements UserService{
@Autowired
private BaseDao baseDao;
public void saveUser(String sql) {
try {
baseDao.addBySql("insert into user (name,age)values('张三',13)", null);
baseDao.addBySql("insert into user (id,name,age)values(2,'张三',13)", null);
} catch (Exception e) {
System.out.println("代码错误新增事务回滚");
}
}
}
如果事务正常控制则因为第二条新增语句错误(因id为2的记录已存在,可自行修改)而catch到异常并且数据库中没有新增的记录(ps.数据库很简单,就死一张user表,有id,name,age三个字段,id为主键自增)。经测试,测试结果与预测一致。
ps:注意点:在dao层新增时,如果是以下情况则数据库直接新增前一条记录
Java代码
public void addBySql(String sql,final Object[] params) {
jdbcTemplate.execute(sql);
}
因而保存语句应该使用PreparedStatement,
Java代码
jdbcTemplate.update(sql,
new PreparedStatementSetter() {
public void setValues(PreparedStatement ps)
throws SQLException {
ps.setInt(1, Integer.parseInt(params[0].toString()));
}
});
进入jdbcTemplate.execute()方法可以发现它是直接调用Statement.execute直接执行因为事实上数据库事务已经提交而调用update方法时是使用PreparedStatement进行预编译的。
测试代码见附件,以上内容如有错误 烦请斧正,希望能够在大家的指导下更进一步,谢谢。
下一篇博文将会对SpringJDBC的多数据源在本项目中的实际运用进行总结。
SpringJDBC_事务控制_.rar (26.2 KB)
下载次数: 6
SpringJDBC的使用目前来看非常简单,主要就是三个步骤。
一、maven加载所需要的jar包;
一、Spring配置文件进行数据源与jdbctemple的配置;
二、直接在数据访问层使用。
以下是spring配置文件的内容:
Java代码
<!-- 引入属性文件 -->
<context:property-placeholder location="classpath:config.properties" />
<!-- 自动扫描dao和service包( 自动注入) -->
<context:component-scan base-package="com.zh.demo" />
<!-- 数据连接池C3P0 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="${jdbc.driverClass}" />
<property name="jdbcUrl" value="${jdbc.jdbcUrl}" />
<property name="user" value="${jdbc.user}" />
<property name="password" value="${jdbc.password}" />
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
这里的注意点在于spring的数据源配置,不直接使用DriverManagerDataSource的原因是由于其没有实现连接池的机制,因此使用C3P0,这时需要加载c3p0的支持JAR包;
另外在数据访问层进行数据操作时如下:
Java代码
public class BaseDaoImpl implements BaseDao{
@Autowired
private JdbcTemplate jdbcTemplate;
/**
* sql = "insert into user (name,age) values(?,?)"
* */
public void addBySql(String sql,final Object[] params) {
//--------------methods01------------------------------------//
jdbcTemplate.execute(sql);
//-----------------or methods02------------------------------//
//just like updateBySql
}
/**
* sql = “update table_name set name=?,age=?”
* */
public void updateBySql(String sql,final Object[] params) {
//--------------methods01------------------------------------//
jdbcTemplate.update(sql,
new PreparedStatementSetter() {
public void setValues(PreparedStatement ps)
throws SQLException {
ps.setInt(1, Integer.parseInt(params[0].toString()));
}
});
//-----------------or methods02------------------------------//
//jdbcTemplate.update(sql, params);
}
/**
* sql = "delete user where id =? and name = ?;"
* */
public void deleteBySql(String sql,final Object[] params) {
//----------just like update---------------//
jdbcTemplate.update(sql, params);
}
/**
* RowMapper接口封装返回集合,可自定义
* */
public List<UserEntity> getQueryBySql(String sql) {
return (List<UserEntity>) jdbcTemplate.query(sql,
new BeanPropertyRowMapper<UserEntity>(UserEntity.class));
}
}
因为Spring配置文件中已经配置,可以直接依赖注入jdbcTemplate;
另外也可以继承JdbcDaoSupport类,来使用jdbcTemplate,
Java代码
public class BaseDaoImpl2 extends JdbcDaoSupport implements BaseDao{
public void addBySql(String sql,final Object[] params) {
this.getJdbcTemplate().update(sql);
}
}
。
这两个类进一步论证一个接口可以有多个实现类,谁实例化则调用哪个实现类中的方法。
具体的代码例子与测试文件可以下载附件参考,欢迎大家斧正。
另外对于jdbcTemplate的事务控制就是使用Spring对于事务的控制,具体内容会在后续文章中补充说明。
SpringJDBC.rar (20.5 KB)
下载次数: 3
继续上一篇文章中所述项目的代码整理学习,前面提到直接使用springJDBC的进行数据层的操作,事务控制是必须要有的,那么这里整理一下之前使用的事务控制内容。
首先Spring的事务控制是很完善的,能够满足本人目前遇到的几乎所有项目,具体的内容就不展开论述了,因为太多了
。这里贴一张图,基本就可以理清Spring事务控制的最基本配置。本图来源于博客园
由于实际项目周期的问题以及个人习惯能注解就注解=。=,当然因为某种原因,这里并不是使用纯注解的方式进行事务配置,而是使用了tx拦截器的方式进行声明式事务配置(入乡随俗,充分利用Spring特色),其中运用到的aop面向切面编程后续文章中会专门对他的aspectj代理机制进行总结,这里就不对其展开代码编写试验了,当然这里的项目aspectjweaver的JAR包是肯定要添加的
。
首先由于是直接使用SpringJdbc因而使用DataSourceTransactionManager进行事务管理
Java代码
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>其次自然需要开启tx标签注解事务
[code="java<!-- 开启注解事务 只对当前配置文件有效 -->
<tx:annotation-driven transaction-manager="transactionManager" />
<!-- 事务管理配置 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="create*" propagation="REQUIRED" />
<tx:method name="insert*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
<tx:method name="remove*" propagation="REQUIRED" />
<tx:method name="cancel*" propagation="REQUIRED" />
<tx:method name="get*" propagation="REQUIRED" read-only="true" />
<tx:method name="query*" propagation="REQUIRED" read-only="true" />
<tx:method name="find*" propagation="REQUIRED" read-only="true" />
<tx:method name="load*" propagation="REQUIRED" read-only="true" />
<tx:method name="count*" propagation="REQUIRED" read-only="true" />
<tx:method name="list*" propagation="REQUIRED" read-only="true" />
<tx:method name="*" read-only="true" />
</tx:attributes>
</tx:advice>
最后开启Aop的监听与监听切面
Java代码
<aop:aspectj-autoproxy expose-proxy="true" /><aop:config expose-proxy="true">
<!-- 只对业务逻辑层实施事务 -->
<aop:pointcut id="txPointcut"
expression="execution(* com.zh..service.impl.*ServiceImpl.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut" />
</aop:config>
这样配置就结束了。对于不想使用切面直接使用纯注解方式后续的文章总结中可以尝试使用。
接下去就可以展开编码测试了,在上文的基础上新建了Service类,并加入@service注解,使得调用的时候可以自动注入
Java代码
@Service("userService")
public class UserServiceImpl implements UserService{
@Autowired
private BaseDao baseDao;
public void saveUser(String sql) {
try {
baseDao.addBySql("insert into user (name,age)values('张三',13)", null);
baseDao.addBySql("insert into user (id,name,age)values(2,'张三',13)", null);
} catch (Exception e) {
System.out.println("代码错误新增事务回滚");
}
}
}
如果事务正常控制则因为第二条新增语句错误(因id为2的记录已存在,可自行修改)而catch到异常并且数据库中没有新增的记录(ps.数据库很简单,就死一张user表,有id,name,age三个字段,id为主键自增)。经测试,测试结果与预测一致。
ps:注意点:在dao层新增时,如果是以下情况则数据库直接新增前一条记录
Java代码
public void addBySql(String sql,final Object[] params) {
jdbcTemplate.execute(sql);
}
因而保存语句应该使用PreparedStatement,
Java代码
jdbcTemplate.update(sql,
new PreparedStatementSetter() {
public void setValues(PreparedStatement ps)
throws SQLException {
ps.setInt(1, Integer.parseInt(params[0].toString()));
}
});
进入jdbcTemplate.execute()方法可以发现它是直接调用Statement.execute直接执行因为事实上数据库事务已经提交而调用update方法时是使用PreparedStatement进行预编译的。
测试代码见附件,以上内容如有错误 烦请斧正,希望能够在大家的指导下更进一步,谢谢。
下一篇博文将会对SpringJDBC的多数据源在本项目中的实际运用进行总结。
SpringJDBC_事务控制_.rar (26.2 KB)
下载次数: 6
相关文章推荐
- Arrays类操作数组的使用
- 小码农的代码(三)----------SpringJDBC多数据源应用
- java计算文本MD5值
- 小码农的代码(四)----------JAVA中Timer定时器与Spring定时任务
- Java文档:并发库(一)【接口:Exectuor接口族】
- Java 入门 之 面向对象 封装、继承与多态(二)
- JDK1.8 HashMap源码分析
- Dubbo与Zookeeper、SpringMVC整合和使用(负载均衡、容错)
- Spring Boot 事务的使用
- spring 五个事务隔离级别和七个事务传播行为
- Spring学习笔记---7-Spring事务管理(3)
- java中栈内存和堆内存的区别
- BFS、DFS、先序、中序、后序遍历的非递归算法(java)
- Hadoop Java API 读写文件系统
- Hibernate、Spring和Struts工作原理及使用理由
- jetty使用教程(嵌入eclipse开发)
- 使用Eclipse开发及测试Spark的环境搭建及简单测试
- Java中的String为什么是不可变的? — String源码分析
- web.xml(spring/spring mvc/hibernate)
- struts2的常用标签(二)