spring与jdbc整合
spring+jdbc开发,我使用的是c3p0连接池
1、数据库建表:
create table person(
id int primary key auto_increment,
name varchar()
)
2、配置数据源:
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClassName}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="maxPoolSize" value="${jdbc.maxPoolSize}"/>
<property name="minPoolSize" value="${jdbc.minPoolSize"/>
<property name="initialPoolSize" value="${jdbc.initialPoolSize"/>
<property name="maxIdleTime" value="${jdbc.maxIdleTime}"/>
<property name="acquireIncrement" value="${jdbc.acquireIncrement}"/>
</bean>
我这里使用的是c3p0连接池,不同连接池对应的数据源的class是不一样的。我的配置信息存放在属性文件中。这里使用类似el表达式读取的属性文件。
属性文件jdbc.properties:
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc\:mysql\://localhost\:3306/customers?useUnicode\=true&characterEncoding\=UTF-8
jdbc.username=guodaxia
jdbc.password=961012gz
jdbc.maxPoolSize=
jdbc.minPoolSize=
jdbc.initialPoolSize=
jdbc.maxIdleTime=
jdbc.acquireIncrement=
如何让spring容器加载属性文件使得我们可以直接使用呢?
使用占位符指定属性文件:
<context:property-placeholder location="classpath:jdbc.properties"/>
这里用到了context,所以不要忘了加上context的namespace在声明中
spring中使用事务:
针对事务操作,我们需要引入事务有关的命名空间:
xmlns:tx="http://www.springframework.org/schema/tx"
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
然后我们要在配置文件中装载spring提供的事务管理器:
<!-- 装载spring提供的针对数据源的事务管理器 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
1、使用注解方式使用事务
前提:
定义配置项(加入对应注解处理器):
<tx:annotation-driven transaction-manager="txManager"/>
使用:
@Transactional 注解
放在类上,类中的所有方法都开始被spring声明式事务管理。
@Service("personService") @Transactional
public class PersonServiceBean implements PersonService {
只要该bean被spring容器管理,这样一声明该bean中的所有方法就会被spring事务管理器管理。
关于事务管理的细节:
默认的事务属性:
业务方法执行前,打开事务
业务方法结束前,结束事务
什么时候事务提交,什么时候事务回滚呢?
默认情况下对于业务方法出现运行期异常RuntimeException,也叫checked异常,会进行事务的回滚
如果业务方法出现Exception的话,默认的事务是不会滚的,Exception也叫checked异常
限定异常类型是否回滚的属性:
noRollbackFor 指定不会滚的对应的异常类型
rollbackFor 指定回滚对应的异常类型
@Transactional(noRollbackFor=RuntimeException.class,rollbackFor=Exception.class)
public void deletePerson(Integer personId) throws Exception{
noRollbackForClassName和rollbackForClassName我就不说了
事务传播属性(propagation):
我们知道spring管理事务默认是方法开始前打开事务,结束后关闭事务。@Transactional注解放在类上,则该类的所有方法都具有事务特性。但我们有时候需要改变这种特性,
比如:我的查询方法不希望开启和打开事务,这时怎么办呢?
我们需要使用@Transactional注解的另一个属性propagation。
属性值以及对应的意义:
REQUIRED:
业务方法需要在一个事务中运行。如果方法运行时,已经处在一个事务中,那么加入到该事务,否则为自己创建一个新的事务。这是spring默认的事务传播属性
NOT_SUPPORT:
声明方法不需要事务。如果方法没有关联到一个事务,容器不会为它开启事务。如果方法在一个事务中被调用,该事务会被挂起,在方法调用结束后,原先的事务便
会恢复执行
MANDATORY:
该属性指定事务方法只能在一个已经存在的事务中执行,业务方法不能发起自己的事务,如果业务方法没有在事务的环境下调用,容器就会抛出异常。
SUPPORTS:
这一属性表明,如果业务方法在某个事务范围内被调用,则方法称为该事务的一部分,如果业务方法在事务范围外被调用,则方法在没有事务的环境下执行。
NEVER:
指定业务方法绝对不能在事务范围内执行。如果业务放大在某个事务中执行,则容器会抛出异常,只有业务方法没有关联到任何事务,才能正常执行。
NESTED:
如果一个活动的事务存在,则运行在一个嵌套的事务中,如果没有活动事务,则按REQUIRED属性执行,它使用了一个单独的事务,这个事务拥有多个可以回
滚的保存点。内部事务的回滚不会对外部事务造成影响。它只对DataSourceTransactionManager事务管理器起效果。外部事务的回滚会对内部事务造成影响,也要回滚。
@Transactional(propagation=Propagation.NEVER)
public void deletePerson(Integer personId){
设置事务的等待时间:timeout属性
设置事务的隔离级别(isolation):
数据库系统提供了四种事务隔离级别
Read Uncommited:读未提交数据(会出现脏读,不可重复读和幻读)
Read Commited:读已提交数据(会出现不可重复读和幻读)
Repeatable Read:可重复读(会出现幻读,解决不可重复读的方式类似于镜像)
Serializable:串行化
脏读:
一个事务读取到另一事务未提交的更新数据
不可重读:
在同一事务中,多次读取同一数据返回的结果有所不同。换句话说,后续读取可以读取到另一事务的更新数据。相反,“不可重复读”在同一事务中多次读取
事务时,能够保证所读数据一样,也就是后续速去不能读取到另一事务已经提交的更新数据。
幻读:
一个事务读取到另一事务已经提交的insert数据
@Transactional(isolation=Isolation.READ_COMMITTED)
public void deletePerson(Integer personId){
基于xml方式配置事务
beans.xml中:
<aop:config>
<aop:pointcut expression="execution(* cn.itcast.service..*.*(..))" id="mycut"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="mycut"/>
</aop:config>
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="get*" read-only="true" propagation="NOT_SUPPORTED"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
检验事务是否成功管理:
public void deletePerson(Integer personId){
jdbcTemplate.update("delete from person where id=?",
new Object[]{personId},
new int[]{java.sql.Types.INTEGER}); jdbcTemplate.update("delete from personss where id=3");
}
第二条删除语句中表名有误,测试的时候如果spring管理了事务则两条sql语句都会回滚,也就是同一个事务,如果没有管理事务则只有一条sql语句回滚,所有第一条还是会
删除数据库记录
完整代码(部分被后面覆盖)
package cn.itcast.service; import java.util.List; import cn.itcast.domain.Person; public interface PersonService { /**
* 保存person
* @param person
*/
public void save(Person person); /**
* 更新person
* @param person
*/
public void update(Person person); /**
* 根据id获取person
* @param personId
* @return
*/
public Person getPerson(Integer personId); /**
* 获取所有person
* @return
*/
public List<Person> getPersons(); /**
* 根据id删除person
* @param personId
*/
public void deletePerson(Integer personId);
}
PersonService.java
package cn.itcast.service.impl; import java.util.List; import javax.annotation.Resource;
import javax.sql.DataSource; import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import cn.itcast.domain.Person;
import cn.itcast.service.PersonService;
@Service("personService") @Transactional
public class PersonServiceBean implements PersonService { private JdbcTemplate jdbcTemplate; public void save(Person person) {
jdbcTemplate.update("insert into person(name) values(?)",
new Object[]{person.getName()},
new int[]{java.sql.Types.VARCHAR});
} public void update(Person person) {
jdbcTemplate.update("update person set name=? where id=?",
new Object[]{person.getName(),person.getId()},
new int[]{java.sql.Types.VARCHAR,java.sql.Types.INTEGER});
} public Person getPerson(Integer personId) {
Person person = (Person) jdbcTemplate.queryForObject("select * from person where id=?",
new Object[]{personId},
new int[]{java.sql.Types.INTEGER},
new PersonRowMapper());
return person;
} public List<Person> getPersons() {
@SuppressWarnings("unchecked")
List<Person> persons=jdbcTemplate.query("select * from person", new PersonRowMapper());
return persons;
} public void deletePerson(Integer personId){
jdbcTemplate.update("delete from person where id=?",
new Object[]{personId},
new int[]{java.sql.Types.INTEGER}); jdbcTemplate.update("delete from personss where id=3");
} @Resource(name="dataSource")
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
} }
PersonServiceBean.java
package cn.itcast.service.impl; import java.sql.ResultSet;
import java.sql.SQLException; import org.springframework.jdbc.core.RowMapper; import cn.itcast.domain.Person; public class PersonRowMapper implements RowMapper{ //外部调用我们方法的时候已经做了rs.next()操作
public Object mapRow(ResultSet rs, int index) throws SQLException {
Person person=new Person(rs.getInt("id"),rs.getString("name"));
return person;
} }
PersonRowMapper.java
package junit.test; import java.util.List; import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import cn.itcast.domain.Person;
import cn.itcast.service.PersonService; public class PersonServiceBeanTest { private static PersonService personService; @BeforeClass
public static void setUpBeforeClass() throws Exception {
try{
ApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");
personService=(PersonService) ctx.getBean("personService");
}catch(RuntimeException e){
e.printStackTrace();
} } @Test public void testSave(){
for(int i=;i<;i++)
personService.save(new Person("传智播客"+""));
}
@Test public void testUpdate(){
Person person=personService.getPerson();
person.setName("张三");
personService.update(person);
}
@Test public void testDetetePerson(){
personService.deletePerson();
}
@Test public void testgetPerson(){
Person person=personService.getPerson();
System.out.println(person.getId()+" "+person.getName());
} @Test public void testFindAll(){
List<Person> persons=personService.getPersons();
if(persons!=null){
for(Person person:persons){
System.out.println(person.getId()+" "+person.getName());
}
}
} }
PersonServiceBeanTest.java
<?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:context="http://www.springframework.org/schema/context"
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.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> <context:component-scan base-package="cn.itcast"/> <context:property-placeholder location="classpath:jdbc.properties"/> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClassName}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="maxPoolSize" value="${jdbc.maxPoolSize}"/>
<property name="minPoolSize" value="${jdbc.minPoolSize}"/>
<property name="initialPoolSize" value="${jdbc.initialPoolSize}"/>
<property name="maxIdleTime" value="${jdbc.maxIdleTime}"/>
<property name="acquireIncrement" value="${jdbc.acquireIncrement}"/>
</bean> <!-- 装载spring提供的针对数据源的事务管理器 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean> <!-- 打开注解配置管理事务的处理器 -->
<tx:annotation-driven transaction-manager="txManager"/> <aop:config>
<aop:pointcut expression="execution(* cn.itcast.service..*.*(..))" id="mycut"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="mycut"/>
</aop:config>
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="get*" read-only="true" propagation="NOT_SUPPORTED"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice> </beans>
beans.xml
spring与jdbc整合的更多相关文章
- 【spring基础】spring与jdbc整合详解
先上一段简单示例 public class MyTemplate { private DataSource dataSource; public DataSource getDataSource() ...
- 1.Spring对JDBC整合支持
1.Spring对JDBC整合支持 Spring对DAO提供哪些支持 1)Spring对DAO异常提供统一处理 2)Spring对DAO编写提供支持的抽象类 3)提高编程效率,减少DAO编码量 Spr ...
- Spring学习5-Spring整合JDBC及其事务处理(注解方式)
一.整合的步骤 1.步骤一:首先要获得DataSource连接池(推荐使用B方式): 要对数据库执行任何的JDBC操作,需要有一个Connection.在Spring中,Connection对象是 ...
- Unit06: Spring对JDBC的 整合支持 、 Spring+JDBC Template、Spring异常处理
Unit06: Spring对JDBC的 整合支持 . Spring+JDBC Template .Spring异常处理 1. springmvc提供的异常处理机制 我们可以将异常抛给spring框架 ...
- spring对JDBC的整合支持
参考网址:https://blog.csdn.net/u013821825/article/details/51606171 springMVC,目前用到的jar包 spring IOC 5个包 + ...
- 轻量级Java EE企业应用实战(第4版):Struts 2+Spring 4+Hibernate整合开发(含CD光盘1张)
轻量级Java EE企业应用实战(第4版):Struts 2+Spring 4+Hibernate整合开发(含CD光盘1张)(国家级奖项获奖作品升级版,四版累计印刷27次发行量超10万册的轻量级Jav ...
- Spring Security 3整合CAS 实现SSO
spring security 3整合cas client用于实现各Application之间的单点登录. 1. 需要准备的jar spring-security-core-3.0.8.RELEASE ...
- Spring+springmvc+Mybatis整合案例 annotation版(myeclipse)详细版
Spring+springmvc+Mybatis整合案例 Version:annotation版 文档结构图: 从底层开始做起: 01.配置web.xml文件 <?xml version=&qu ...
- Spring+springmvc+Mybatis整合案例 xml配置版(myeclipse)详细版
Spring+springmvc+Mybatis整合案例 Version:xml版(myeclipse) 文档结构图: 从底层开始做起: 01.配置web.xml文件 <?xml version ...
随机推荐
- 【Excle数据透视表】如何显示/隐藏数据透视表字段列表
在创建完毕的数据透视表中,若单击数据透视表中任意单元格,即可显示数据透视表字段列表窗格,用户就可以通过弹出的窗格进行字段调整 两种情况需要隐藏数据数据透视表窗格 ①数据透视表已经完成 ②失误关闭窗格 ...
- 七款Debug工具推荐:iOS开发必备的调试利器
历时数周或数月开发出来了应用或游戏.可为什么体验不流畅?怎么能查出当中的纰漏?这些须要调试诊断工具从旁协助.调试是开发过程中不可缺少的重要一环.本文会列举几个比較有效的调试诊断工具,能够帮助你寻根究底 ...
- jenkins 构建一个前端web项目
Jenkins发布web前端代码 “系统管理”“管理插件”“已安装” 检查是否有“Git plugin”和“Publish Over SSH”两个插件,如果没有,则需点击“可选插件”,找到它并安装 ...
- eclipse右下角总显示自动下载xml和jar,如何关闭
windows->preference->查找download-选择Models->右侧下方Enable auto-download去掉 2.Automatic Updates-&g ...
- Oracle更新时间字段
update field set BEGINDATE=to_date('2015-05-03 10:30:20','yyyy-mm-dd hh24:mi:ss') where NOO='01'
- linux下网卡绑定
网卡绑定的作用:1.冗余,防止单点故障 2.防止传输瓶颈 1.交换机端口绑定: system-view link-aggregation group 1 mode manual 比如把端口1和2进行绑 ...
- selenium3 踩坑--move_to_element()报错
问题:selenium3 使用move_to_element()报错,报错信息如下图所示: 网上没有找到合适的解决办法,回退到稳定的selenium2可以解决. pip install seleniu ...
- programming review (c++): (3)graph, binary search
I.graph #include <iostream> #include <vector> using namespace std; vector<vector<, ...
- 【BZOJ4399】魔法少女LJJ 线段树合并
[BZOJ4399]魔法少女LJJ Description 在森林中见过会动的树,在沙漠中见过会动的仙人掌过后,魔法少女LJJ已经觉得自己见过世界上的所有稀奇古怪的事情了LJJ感叹道“这里真是个迷人的 ...
- springcloud与docker微服务架构实战--笔记
看了<微服务那些事>之后,Spring boot和Spring Cloud的关系理清楚了,Spring cloud各个模块的作用也了解了. 但是,Spring cloud 与Docker的 ...