spring对数据库的操作、spring中事务管理的介绍与操作
jdbcTemplate的入门
- 创建maven工程
此处省略
- 导入依赖
<!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-expression -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/aopalliance/aopalliance -->
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.8</version>
</dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.2.4.RELEASE</version>
</dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.2.4.RELEASE</version>
</dependency> <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-tx -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.2.4.RELEASE</version>
</dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.2.4.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
<scope>test</scope>
</dependency>
- 配置文件中配置数据库连接池
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd"> <!-- 配置spring提供的数据库连接池 -->
<!-- <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/spring"></property>
<property name="username" value="root"></property>
<property name="password" value="123"></property>
</bean> --> <!-- jdbcTemplate的配置 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
</beans>
- 测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class JdbcTemplateTest {
@Autowired
private JdbcTemplate jdbcTemplate; //增删改的测试
@Test
public void testName() throws Exception {
String sql = "insert into account values(null,?,?)";
jdbcTemplate.update(sql, "lisi",10000);
} //查询简单类型的测试
@Test
public void testName02() throws Exception {
String sql = "select name from account where id=?";
String name = jdbcTemplate.queryForObject(sql, String.class,1);
System.out.println(name);
} //复杂类型的测试
@Test
public void testName03() throws Exception {
String sql = "select * from account where id=?";
Account account = jdbcTemplate.queryForObject(sql, new MyRowMapper(),2);
System.out.println(account);
} class MyRowMapper implements RowMapper<Account>{
@Override
public Account mapRow(ResultSet rs, int arg1) throws SQLException {
Account account = new Account(); //自己编写的实体类
account.setId(rs.getInt("id")); //id,name,money为实体类Account中的成员属性
account.setName(rs.getString("name"));
account.setMoney(rs.getDouble("money"));
return account;
}
}
}
spring配置文件中数据库连接池的配置
C3P0数据库连接池的配置
依赖的jar包
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
xml配置
<!-- c3p0数据库连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/spring"></property>
<property name="user" value="root"></property>
<property name="password" value="123"></property>
</bean>
DBCP数据库连接池的配置
依赖的jar包
<!-- dbcp数据库连接池 -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>commons-pool</groupId>
<artifactId>commons-pool</artifactId>
<version>1.5.3</version>
</dependency>
xml配置
<!-- dbcp数据库连接池 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/spring"></property>
<property name="username" value="root"></property>
<property name="password" value="123"></property>
</bean>
Druid数据库连接池的配置
依赖的jar包
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.18</version>
</dependency>
xml配置
<!-- druid数据库连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/spring"></property>
<property name="username" value="root"></property>
<property name="password" value="123"></property>
</bean>
引入外部属性配置文件来配置数据库连接信息
1. src/main/resources目录下创建jdbc.properties
jdbc.driverClass=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/spring jdbc.username=root jdbc.password=root |
2. spring 的核心配置文件中加载我们的jdbc.properties配置文件
<context:property-placeholder location="classpath:db.properties"/>
3. 改写数据库连接池的配置,通过占位符来引用jdbc.properties属性文件中的内容
<!-- druid数据库连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<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>
spring中事务的管理介绍
事务的概念
事务主要是用来操作数据库的,他的使用是用来保证数据的完整性和一致性。
事务就是一系列的操作,它们被当做一个单独的工作单元。这些操作要么全部成功,要么全部失败。
事务的特性(ACID)
原子性(atomicity): 事务是一个原子操作,由一系列动作组成。事务的原子性确保动作要么全部完成要么完全不起作用。
一致性(consistency): 一旦所有事务动作完成,事务就被提交。数据和资源就处于一种满足业务规则的一致性状态中。
隔离性(isolation): 可能有许多事务会同时处理相同的数据,因此每个事物都应该与其他事务隔离开来,防止数据损坏。
持久性(durability): 一旦事务完成,无论发生什么系统错误,它的结果都不应该受到影响。通常情况下,事务的结果被写到持久化存储器中。
多个事务并发操作存在的问题
读的问题
1、脏读:对于两个事务T1,T2, T1 读取了已经被 T2 更新但还没有被提交的字段。 之后, 若 T2 回滚,T1读取的内容就是临时且无效的。【读但未提交】
2、不可重复读:对于两个事务 T1, T2,T1 读取了一个字段,然后 T2 更新了该字段.。之后, T1再次读取同一个字段,值就不同了。【读更读】
3、幻读:对于两个事务 T1,T2, T1 从一个表中读取了一个字段,然后 T2 在该表中插入了一些新的行。之后,如果 T1 再次读取同一个表,就会多出几行。【读插读】
写的问题
丢失更新 :两个事务同时写一条记录,后一个事务把前一个事务的数据覆盖了,导致前一个事务的数据丢失。
事务的隔离级别
- 读未提交(read uncommited)
允许事务读取其他事务未提交的更新,脏读 、不可重复读、幻读都会出现。
- 读已提交(read commited)
只允许事务读取其他事务已经提交的变更。可以避免脏读,但不可重复读和幻读问题仍然可能出现。
- 可重复读(repeatable read)
确保一个事务可以多次从一个字段中读取相同的值。在这个事务持续期间,禁止其他的事务对这个字段做更新操作。可以避免脏读、不可重复读,但是幻读仍然可能发生。
- 串行化(serialzable)
确保一个事务可以多次从一个表中读取相同的行。在这个事务持续期间,禁止其他事务对这张表进行插入、删除、更新操作。所有的并发都被避免,但是效率低下。
spring的平台事务管理器
PlatformTransactionManager接口有一系列的实现类,用于不同的事务管理,其中最常用的类是【 HibernateTransactionManager】和【 DataSourceTransactionManager】。
HibernateTransactionManager用 Hibernate 框架存取数据库。
DataSourceTransactionManager通过 JDBC 操作数据库来管理事务。
它为事务管理封装了一组独立于技术的方法。无论使用 Spring 的哪种事务管理策略(编程式或声明式事务管理),事务管理器都是必须的。
spring中事务的定义
事物的隔离级别
事物的传播行为
事物的超时信息
事物是否只读
spring当中事务的状态信息定义
状态是否有保存点
事物是否完成
是不是一个新的事物
是否仅仅回滚
spring当中的事务执行过程
Spring当中通过TransactionDefinition来对事物进行定义,然后通过PlatformTransactionManager来对事物进行操作,并且将操作后的事物状态,保存到TransactionStatus当中
spring当中事务的传播行为
事务传播行为的介绍
事务方法的互相调用时(当一个事务方法被另一个事务方法调用时)必须指定事务应该如何传播。方法可能继续在现有事务中运行, 也可能开启一个新事务, 并在这个新的事务中运行。 事务的传播行为可以由传播属性指定。Propagation(传播,扩展)默认值是required,即是如果当前存在事务,则不进行创建,只是利用当前事务,如果当前没有事务,则是进行创建。
举例说明:Required传播行为
传播行为的取值
Spring中事务的操作
Spring 既支持编程式事务管理,也支持声明式的事务管理。
编程式事务管理
声明式事务管理(xml配置方式和注解配置方式)
Spring中使用编程的方式进行事务管理
spring配置文件中配置事务管理器和事务模版
<!-- 配置事务的模版 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 事务的模版 -->
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"></property>
</bean>
接口和实现类
public interface AccountDao {
void moneyOut(int from, double money);
void moneyIn(int in, double money);
}
@Repository
public class AccountDaoImpl implements AccountDao {
@Autowired
private JdbcTemplate jdbcTemplate; @Override
public void moneyOut(int from, double money) {
String sql = "update account set money = money - ? where id = ?";
jdbcTemplate.update(sql, money,from);
} @Override
public void moneyIn(int in, double money) {
String sql = "update account set money = money + ? where id = ?";
jdbcTemplate.update(sql, money,in);
}
}
public interface AccountService {
public void transferMoney(int from,int in,double money);
}
@Service
public class AccountServiceImpl implements AccountService{
@Autowired
private AccountDao accountDao; //注入事务模版
@Autowired
private TransactionTemplate transactionTemplate; @Override
public void transferMoney(int from, int in, double money) {
//编程式事务代码
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus arg0) {
accountDao.moneyOut(from,money);
//抛出异常
System.out.println(1/0);
accountDao.moneyIn(in,money);
}
});
}
}
测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext-tx.xml")
public class TxTest {
@Autowired
private AccountService accountService; @Test
public void testName() throws Exception {
accountService.transferMoney(1, 2, 1000);
}
}
Spring中的声明式事务管理(基于xml配置)
开启tx命名空间
配置声明式事务属性及切入点
<!-- 声明事务管理:xml方式配置 -->
<!-- 配置事务属性:传播行为,隔离级别,事务回滚,只读事务,超时结束 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- 指定事务方法的事务属性信息:如传播行为 -->
<tx:method name="transfer*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice> <!-- 配置事务切入点,以及把事务切入点和事务属性关联起来 -->
<aop:config>
<aop:pointcut expression="execution(* *.transfer*(..))" id="pointCut"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointCut"/>
</aop:config>
测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext-tx-xml.xml")
public class XmlTransactionTest {
@Autowired
private AccountService accountService; @Test
public void testName() throws Exception {
accountService.transferMoney(1, 2, 1000);
}
}
Spring中的声明式事务管理(基于注解的方式)
开启tx命名空间
开启注解扫描
<!-- 注解方式的声明式事务管理 -->
<!-- 开启声明式事务管理的注解驱动 -->
<tx:annotation-driven transaction-manager="transactionManager"/
事务处理
@Service
@Transactional//注意加载service层,不要加在dao层
public class AccountServiceImpl implements AccountService{
@Autowired
private AccountDao accountDao; @Override
public void transferMoney(int from, int in, double money) {
accountDao.moneyOut(from,money);
//抛出异常
System.out.println(1/0);
accountDao.moneyIn(in,money);
}
}
测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext-tx-annotation.xml")
public class AnnotationTransactionTest {
@Autowired
private AccountService accountService; @Test
public void testName() throws Exception {
accountService.transferMoney(1, 2, 1000);
}
}
Spring中的事务管理总结
Spring 既支持编程式事务管理,也支持声明式的事务管理
编程式事务管理: 将事务管理代码嵌入到业务方法中来控制事务的提交和回滚。在编程式管理事务时,必须在每个事务操作中包含额外的事务管理代码,这样的话,会引起业务代码混乱。
声明式事务管理: 大多数情况下比编程式事务管理更好用。它将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理。事务管理作为一种横切关注点, 可以通过 AOP 方法模块化。Spring 通过 Spring AOP 框架支持声明式事务管理。建议使用这种方式。
注意:基于注解的声明式事务管理,注解不要写在dao层处理,应该将事务的处理提取到service层,因为事务的回滚一般会牵涉到多个dao的使用,所以在service层处理,能够最大化的保证数据的完整性。
spring对数据库的操作、spring中事务管理的介绍与操作的更多相关文章
- 8.spring:事务管理(上):Spring的数据库编程、编程式事务管理
Spring的数据库编程 Spring框架提供了JDBC模板模式------>JdbcTemplate 简化了开发,在开发中并不经常是使用 实际开发更多使用的是Hibernate和MyBatis ...
- 关于spring中事务管理的几件小事
1.Spring中的事务管理 作为企业级应用程序框架,Spring在不同的事务管理API之上定义了一个抽象层.而应用程序开发人员不必了解底层的事务管理API,就可以使用Spring的事务管理机制. S ...
- Spring中事务管理的两种方式
spring支持编程式事务管理和声明式事务管理两种方式. 编程式事务管理使用TransactionTemplate或者直接使用底层的PlatformTransactionManager.对于编程式事务 ...
- Spring Boot 2.x基础教程:事务管理入门
什么是事务? 我们在开发企业应用时,通常业务人员的一个操作实际上是对数据库读写的多步操作的结合.由于数据操作在顺序执行的过程中,任何一步操作都有可能发生异常,异常会导致后续操作无法完成,此时由于业务逻 ...
- Spring整合Hibernate 二 - 声明式的事务管理
Spring大战Hibernate之声明式的事务管理 Spring配置文件: 添加事务管理类的bean: <bean id="txManager" class="o ...
- Spring中事务管理
spring事务管理两种方式 第一种 编程式事务管理(不用) 第二种 声明式事务管理 (1) 基于xml配置文件实现 (2) 基于注解实现 一:声明式事务管理(xml配置) 第一步 ...
- Spring.NET中事务管理【转】
http://www.cnblogs.com/GoodHelper/archive/2009/11/16/springnet_transaction.html 浏览了下写的比较清楚. 在.NET FC ...
- 程序员笔记|Spring IoC、面向切面编程、事务管理等Spring基本概念详解
一.Spring IoC 1.1 重要概念 1)控制反转(Inversion of control) 控制反转是一种通过描述(在java中通过xml或者注解)并通过第三方去产生或获取特定对象的方式. ...
- spring boot 或 spring 集成 atomikos jta 完成多数据源事务管理
前言:对于事务,spring 不提供自己的实现,只是定义了一个接口来供其他厂商实现,具体些的请看我的这篇文章: https://www.cnblogs.com/qiaoyutao/p/11289996 ...
随机推荐
- C++_函数4-函数重载与函数模板
函数重载 多个函数,函数名相同,但是调用的时候,参数不同. 函数多态是C++在C语言的基础上新增的功能.多态指的是有多种形式,因此函数多态允许函数可以有多种形式.术语“函数重载”指的是可以有多个同名的 ...
- Kibana6.x.x源码分析--JavaScript中 "!~" 这样的符号是啥意思?
看到源码中有一段JS代码不太懂,如下: 里面这个 "!~" 符号看到后有点儿方啊O__O "…,毛线意思? [查资料,解释如下]: indexOf returns -1 ...
- bzoj4548: 小奇的糖果 题解
题目链接 题解 不包含所有颜色 就强制不选一个颜色 图中圆点颜色相同 矩形越大,包括的点一定不比其一小部分少 如图所示,最大矩形只有3种 离散化\(x\)坐标 然后按\(y\)排序 每次取出颜色的前驱 ...
- 【KMP】【矩阵加速】【递推】洛谷 P3193 [HNOI2008]GT考试 题解
看出来矩阵加速也没看出来KMP…… 题目描述 阿申准备报名参加 GT 考试,准考证号为\(N\)位数\(X_1,X_2…X_n(0\le X_i\le9)\),他不希望准考证号上出现不吉利的数 ...
- BZOJ - 1497 最小割应用
题意:基站耗费成本,用户获得利益(前提是投入成本),求最大获利 最小割的简单应用,所有可能的收益-(消耗的成本/失去的收益),无穷大边表示冲突,最小割求括号内的范围即可 #include<ios ...
- 小a与“204”------数列、排序
链接:https://ac.nowcoder.com/acm/contest/317/B来源:牛客网 小a非常喜欢204204这个数字,因为′a′+′k′=204′a′+′k′=204. 现在他有一个 ...
- 多租户概念以及FreeLink多租户设计思想
多租户实现思想 多租户技术的实现重点,在于不同租户间应用程序环境的隔离(application context isolation)以及数据的隔离(data isolation),以维持不同租户间应用 ...
- esper(4-3)-Non-Overlapping Context
语法 create context context_name start start_condition end end_condition 如: // 9点到17点此context才可用(以引擎的时 ...
- 2.5 Go错误处理
defer import "fmt" func testDefer(){ defer fmt.Println() defer fmt.Println() fmt.Println() ...
- zTree 图标样式
<link rel="stylesheet" href="jquery/ztree/css/zTreeStyle/zTreeStyle.css" /> ...