JdbcTemplate概述

  • 以往使用jdbc时,每次都需要自己获取PreparedStatement,执行sql语句,关闭连接等操作。操作麻烦冗余,影响编码的效率。

  • Spring把对数据库的操作在jdbc上面做了深层次的封装,使用spring的注入功能,可以把DataSource注册到JdbcTemplate(jdbc模板)之中,这样我们只需要做一些简单的操作(eg:编写SQL语句、传递参数)就可以了。

  • spring框架根据不同持久层方案为我们提供了不同的JdbcTemplate(jdbc模板类)。例如:操作关系型数据的JdbcTemplate和HibernateTemplate,操作nosql数据库的RedisTemplate,操作消息队列的JmsTemplate等等

QuickStart

导入spring-jdbc和spring-tx坐标

<dependencies><!-- Spring上下文坐标,如果使用到了Spring的上下文容器,需要导入--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.0.5.RELEASE</version></dependency><!-- 使用Spring JdbcTemplate需要导入下面两个坐标 --><!-- 导入spring-jdbc坐标 --><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.0.5.RELEASE</version></dependency><!-- 导入spring-tx事务管理坐标,如果不使用事务管理,可以不导 --><dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId><version>5.0.5.RELEASE</version></dependency><!-- 因为操作Mysql数据库,需要导入数据库驱动坐标 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.6</version></dependency><!-- 数据源选择使用c3p0连接池 --><dependency><groupId>c3p0</groupId><artifactId>c3p0</artifactId><version>0.9.1.2</version></dependency><!-- 使用单元测试 --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency>
</dependencies>

在测试类中创建JdbcTemplate对象并使用

public class AccountTest {@Testpublic void test1() throws PropertyVetoException {//1. 创建JdbcTemplate模板对象JdbcTemplate jdbcTemplate = new JdbcTemplate();//2. 设置数据源ComboPooledDataSource对象//创建DataSource对象,并设置连接四要素ComboPooledDataSource dataSource = new ComboPooledDataSource();dataSource.setDriverClass("com.mysql.jdbc.Driver");dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");dataSource.setUser("root");dataSource.setPassword("root");//JdbcTemplate依赖于DataSourcejdbcTemplate.setDataSource(dataSource);//3. 执行增删改查操作int row = jdbcTemplate.update("insert into account values (?,?)", "赵丽颖", 666);System.out.println(row);}
}

Spring容器创建并维护JdbcTemplate及相关对象

1)思路分析

  • Spring的核心之一就是Ioc,控制反转,也就是由Spring容器负责对象的创建和对象间依赖关系的管理。上述代码中DataSource、JdbcTemplate对象以及他们之间的关系都是由我们手动创建,并且手动设置依赖关系的。

  • 经过观察,JdbcTemplate类可以通过无参构造创建该类对象,同时又setDataSource()方法用于设置数据源依赖,所以JdbcTemplate类的对象完全可以交给Spring容器管理,数据源DataSource可以交给Spring容器管理,那我们就可以使用Spring容器管理并维护上述两个对象。

2)代码实现

导入坐标:因为要使用到Spring容器创建对象并维护对象依赖关系,所以要在pom.xml中确定导入了spring-context坐标。

    <!-- Spring上下文坐标,使用到了Spring的上下文容器,需要 --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.0.5.RELEASE</version></dependency>

Xml配置:在applicationContext.xml文件中先配置数据源,然后配置JdbcTemplate,最后将数据源注入到JdbcTemplate中。

<!-- DataSource对象 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver"></property><property name="jdbcUrl" value="jdbc:mysql:///test"></property><property name="user" value="root"></property><property name="password" value="root"></property>
</bean><!-- JdbcTemplate对象 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource"></property>
</bean>

Java代码:通过Spring容器获得JdbcTemplate对象,调用JdbcTemplate对象的update方法,传入sql语句及参数完成插入数据的操作

@Test
public void test2() throws PropertyVetoException {//1. 获取JdbcTemplate模板对象(Spring已经将DataSource注入其中)ApplicationContext ac= new ClassPathXmlApplicationContext("applicationContext.xml");JdbcTemplate jdbcTemplate = ac.getBean(JdbcTemplate.class);//2. 不需要设置数据源ComboPooledDataSource对象//3. 执行增删改查操作int row = jdbcTemplate.update("insert into account values (?,?)", "shheima", 60000);System.out.println(row);
}

抽取jdbc配置

  • 目前的jdbc四要素已经脱离了代码,已经实现了解耦,之后如果数据库信息修改后直接修改配置文件即可。

  • 但是目前数据库四要素的配置耦合进了Spring的配置文件,为了更方便的维护,建议将该信息抽取到一个独立properties文件中。

  • 提取数据源的基本连接信息到配置文件jdbc.properties(名字任意,格式为properties)

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///test
jdbc.username=root
jdbc.password=root

引入properties文件,并修改DataSource注入基本参数的配置,具体如下:

<!-- 导入jdbc.properties文件。classpath表示文件在类路径下 -->
<context:property-placeholder location="classpath:jdbc.properties"/><!-- DataSource对象 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><!--property的name属性名称通过set方法截取;因为属性值为String,所以通过value属性设置通过${key}的方式可以从properties文件中读取key对应的值。--><property name="driverClass" value="${jdbc.driver}"></property><property name="jdbcUrl" value="${jdbc.url}"></property><property name="user" value="${jdbc.username}"></property><property name="password" value="${jdbc.password}"></property>
</bean><!-- JdbcTemplate对象 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource"></property>
</bean>

如果有多个properties文件需要引入可以使用通配符:

<!--如果需要导入多个文件,可以使用通配符 -->
<context:property-placeholder location="classpath:*.properties"/>

JdbcTemplate常用操作

jdbcTemplate更新数据库常用方法

  • update (更新数据,也就是增删改)
  • queryForObject (单行查询)
  • query (多行查询)
  • queryForObject (单值查询)

JdbcTemplate常用操作-增删改操作

JdbcTemplate对象的update方法可以完成增删改的操作,只是传入的sql语句及对应参数不同。

语法:对数据库进行增删改的操作,返回影响的行数
jdbcTemplate.update(sql语句, sql语句参数列表)

代码如下:

@RunWith(SpringJUnit4ClassRunner.class)                     //指定测试器
@ContextConfiguration("classpath:applicationContext.xml")    //指定Spring配置文件并加载
public class JdbcTemplatetTest {@Autowired         //自动注入JdbcTemplate对象private JdbcTemplate jdbcTemplate;/*** testUpdate:测试删除*/@Testpublic void testDelete(){int row = jdbcTemplate.update("delete from account where name=?","nanjingheima");System.out.println(row);}/*** testUpdate:测试修改*/@Testpublic void testUpdate(){int row = jdbcTemplate.update("update account set money=? where name=?", 500000,"hzheima");System.out.println(row);}
}

JdbcTemplate常用操作-查询操作

JdbcTemplate对象的query**()方法可以完成查询的操作。

多行查询
List<T> query(sql语句, new BeanPropertyRowMapper<T>(T.class)) 查询并将结果通过BeanPropertyRowMapper将查询的结果集封装到List集合中
List<T> query(sql语句, new BeanPropertyRowMapper<T>(T.class), sql语句参数列表)查询并将结果通过BeanPropertyRowMapper将查询的结果集封装到List集合中
单行查询
T queryForObject(sql语句, new BeanPropertyRowMapper<T>(T.class), sql语句参数列表)单行查询查询并将结果通过BeanPropertyRowMapper将查询结果封装到javaBean对象中
单值查询
要求的查询结果类型 queryForObject(sql语句, 要求的查询结果类型.class)查询并将结果通过BeanPropertyRowMapper将聚合查询结果转化到要去的结果类型
要求的查询结果类型 queryForObject(sql语句, 要求的查询结果类型.class, sql语句参数列表)查询并将结果通过BeanPropertyRowMapper将聚合查询结果转化到要去的结果类型

代码如下:

@RunWith(SpringJUnit4ClassRunner.class)                     //指定测试器
@ContextConfiguration("classpath:applicationContext.xml")    //指定Spring配置文件并加载接卸
public class JdbcTemplatetTest {@Autowired         //自动注入JdbcTemplate对象private JdbcTemplate jdbcTemplate;/*** testQueryCount:聚合查询*/@Testpublic void testQueryCount(){long count = jdbcTemplate.queryForObject("select count(*) from " +"account",long.class);System.out.println(count);count = jdbcTemplate.queryForObject("select count(*) from " +"account where money = ?",long.class,60000);System.out.println(count);}/*** testQueryOne:查询单个*/@Testpublic void testQueryOne(){Account account = jdbcTemplate.queryForObject("select * from account " +"where name = ?",new BeanPropertyRowMapper<Account>(Account.class) ,"hzheima");System.out.println(account);}/*** testQuerySome:按条件查询部分*/@Testpublic void testQuerySome(){List<Account> accounts = jdbcTemplate.query("select * from account where money = ?",new BeanPropertyRowMapper<Account>(Account.class), 60000);System.out.println(accounts);}/*** testQueryAll:查询所有*/@Testpublic void testQueryAll(){List<Account> accounts = jdbcTemplate.query("select * from account",new BeanPropertyRowMapper<Account>(Account.class));System.out.println(accounts);}
}

补充:

批量更新(增删改)

//批量增删改,batchArgs为批量更新的参数列表,类型为Object[]数组类型的List集合
jdbcTemplate.batchUpdate(String sql, List batchArgs);
/***testBatechUpdate:批量更新,批量 insert,update,delete*/
@Test
public void testBatechUpdate() {String sql = "insert into account(name, money) values(?,?)";List<Object[]> batchArgs = new ArrayList<Object[]>();batchArgs.add(new Object[] {"zhangsan",2000});batchArgs.add(new Object[] {"lisi",2000});batchArgs.add(new Object[] {"wangwu",2000});jdbcTemplate.batchUpdate(sql, batchArgs);
}

自定义绑定(使用场景较少)

除了使用系统提供的RowMapper的实现类之外,我们也可以自己手动编写RowMapper实现类,以实现特殊的结果集到javaBean的封装转化,实例代码如下:

Account account = jdbcTemplate.queryForObject("select * from account where money = ?",new Object[]{60000L},new RowMapper<Account>() {//重写该方法时只需要将获取的结果集中单个结果封装到某个JavaBean中,//query方法会根据实际情况选择选择返回一个javaBan对象还是一个Listpublic Account mapRow(ResultSet rs, int rowNum) throws SQLException {Account account = new Account();account.setUsername(rs.getString("name"));account.setMoney(rs.getString("money"));return account;}});

执行DDL语句(使用场景很少)

Spring的JdbcTemplate也可以使用execute(…)方法运行任意SQL语句。所以,该方法通常用于DDL语句。下面代码创建一个表:

jdbcTemplate.execute("create table mytable (id integer, name varchar(100))");

Spring事务管理

Spring事务管理主要应用在软件分层之后的业务层,也就是Service层。一个service层的操作依赖的多个dao层操作要被事务管理起来,保证数据安全准确。eg:转账。

Spring事务管理核心API

Spring事务管理的三个高层接口

  • PlatformTransactionManager:Spring提供的事务管理器核心接口,内部规定了常用的事务管理的规则。

  • TransactionDefinition:Spring提供的封装事务属性的接口,用于封装和操作事务的属性

  • TransactionStatus:Spring提供的封装事务状态的接口,用于封装事务的状态

PlatformTransactionManager

Spring提供的事务管理器接口,整个Spring进行事务管理的核心接口,内部规定了常用的操作事务的规则。

a) 接口中规定的操作事务的方法:

操作事务的方法
TransactionStatus getTransaction
(TransactionDefination defination)
根据事务定义信息获取事务状态信息
void commit(TransactionStatus status) 提交事务
void rollback(TransactionStatus status) 回滚事务

根据上述方法,

​ TransactionStatus getTransaction(TransactionDefination defination)

我们可以推断:PlatformTransactionManager根据TransactionDefinition对象获得 TransactionStatus 对象

  • 三者的关系平台事务管理器(PlatformTransactionManager)根据 事务属性管理器(TransactionDefinition)中定义的事务属性对事务进行管理;事务运行过程中,每一个时间点都有对应的事务状态信息(TransactionStatus)。

  • 也就是说,干活的是Manager(PlatformTransactionManager),根据事务属性管理器(TransactionDefinition)的配置信息干活,在干活的过程中会有一些状态信息,通过TransactionStatus体现。

b) 不同的Dao层技术则有不同的实现类

PlatformTransactionManager是一个接口,只负责制定规范,那具体的实现是哪些类呢?Spring根据不同的数据持久层技术提供了不同实现类:

  • Dao 层技术是jdbc、 mybatis、Apache DBUtils时:org.springframework.jdbc.datasource.DataSourceTransactionManager

  • Dao层技术是hibernate时:org.springframework.orm.hibernate5.HibernateTransactionManager

TransactionDefinition

Spring提供的封装事务属性的接口,用于规定封装事务的属性,通过该接口实现类对象可以获取(子类对象可以设置)事务属性。

a) 接口中规定的获取事务属性的方法:

方法名 说明
int getIsolationLevel() 获取事务的隔离级别,隔离级别用于解决事务并发访问读问题
int getPropagationBehavior() 获取事务的传播行为,解决的就是两个事务方法事务统一性的问题
int getTimeout() 获取超时时间
boolean isReadOnly() 判断当前事务是否只读
  • 接口中只规定了获取的方法,在其实现类中有设置的方法,eg:DefaultTransactionDefinition

  • 事务属性需要在进行声明式事务配置时,需要在配置文件中对于事务属性进行配置,以便Spring框架进行解析。

b) 事务的四个特性:

ACID:原子性、一致性、隔离性、持久性。

  • Atomic(原子性):事务中包含的操作被看做一个逻辑单元,这个逻辑单元中的操作要么全部成 功,要么全部失败。

  • Consistency(一致性):事务完成时,数据必须处于一致状态,数据的完整性约束没有被破坏,事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。

  • Isolation(隔离性):事务允许多个用户对同一个数据进行并发访问,而不破坏数据的正确性 和完整性。同时,并行事务的修改必须与其他并行事务的修改相互独立。

  • Durability(持久性):事务结束后,事务处理的结果必须能够得到持久化。

c) 事务属性:隔离级别(理解)

在并发访问的时候,会出现一些读问题。

读问题

  • 脏读:一个事务读取了另外一个事务改写但还未提交的更新数据,如果这些数据被回滚,则读到的数据是无效的。

    • eg:小明工资表,老板算工资的时候被小明看到了。
  • 不可重复读:在同一个事务中,多次读取同一个数据返回的结果有所不同。换句话说就是,后续读取可以读取到另一个事务已提交的更新数据。相反,“可重复读”在同一个事务中多次读取数据时,能保证数据时一样,也就是,后续读取不能读取到另一个事务已经提交的更新数据。
    • eg:小明买手机前后老婆查账。
  • 幻读:一个事务读取了(按照某个规则的)全部数据后,另一个事务插入了一些记录,当后续再次查询的时候,幻读就发生了。在后续查询中,第一个事务就会发现有一些原来没有的记录。
    • eg:老婆查岗打印流水,又发现消费多了。

设置隔离级别,可以解决事务并发产生的读问题,如脏读、不可重复读和虚读(幻读)。

  • ISOLATION_DEFAULT 默认级别,使用数据库内部默认级别(mysql - Repeatable read,其他大多数是 - Read committed)

  • ISOLATION_READ_UNCOMMITTED 读未提交:一个事务可以读取另一个未提交事务的数据,该级别下容易上述所读有问题。性能最高,安全性最差。

  • ISOLATION_READ_COMMITTED 读提交:一个事务要等另一个事务提交后才能读取数据。能解决脏读问题,但是可能会有不可重复读、幻读的问题。

  • ISOLATION_REPEATABLE_READ 重复读,在开始读取数据(事务开启)时,不再允许修改操作。能解决脏读、不可重复读的问题,但是可能会有幻读的问题。

  • ISOLATION_SERIALIZABLE 序列化,解决所有三个问题,相当于锁表安全性高,串行化处理事务,但是非常耗数据库性能,效率低下,一般不用。

列表如下(√表示可能出现,×表示不会出现):

隔离级别\读问题 脏读 不可重复读 幻读
Read uncommitted读未提交
Read commited读提交 ×
Repeatable read重复读 × ×
Serializable × × ×

上述事务的四大特性、四个隔离级别是原来是在数据库内部规定的,Spring从数据库引入了 过来。但是接下来的七种传播行为和数据库没有直接关系,是Spring为了解决实际开发中的问题而引入的。

d) 事务属性:传播行为

即然是传播,那么至少有两个东西,才可以发生传播。单体不存在传播这个行为。

事务传播行为(propagation behavior)指的就是当一个事务方法A调用另一个事务方法B时,事务方法B应该以何种事务特性进行。是继续在调用者methodA的事务中运行呢,还是为自己开启一个新事务运行,这就是由methodB的事务传播行为决定的。

事务传播行为是为了解决业务方法相互调用时,事务如何管理的问题。

通常情况下,一个业务方法就是一个事务。但是多个业务方法相互调用的时候可能会出现问题。

eg:取钱打印小票

取钱 required

{

​ 插卡 required

​ 输密码 required

​ 吐钱 required

​ 打印小票 requires_new

}

七种事务传播行为(当前方法:被调用的方法):

  • PROPAGATION_REQUIRED:表示当前方法必须运行在事务中。如果调用者事务存在,当前方法就会在该事务中运行;否则,会启动一个新的事务。一般的选择(默认值)。

  • PROPAGATION_SUPPORTS:表示当前方法不需要事务上下文,但是如果当前事务存在的话,那么该方法会在这个事务中运行。

  • PROPAGATION_MANDATORY:表示当前方法必须在事务中运行,如果当前事务不存在,则会抛出一个异常。

  • PROPAGATION_REQUERS_NEW:表示当前方法必须运行在它自己的事务中,一个新的事务将被启动。如果存在当前事务,该方法执行期间,当前事务会被挂起。

  • PROPAGATION_NOT_SUPPORTED:表示当前方法不应该运行在事务中。如果存在当前事务,该方法运行期间,当前事务会被挂起。

  • PROPAGATION_NEVER:表示当前方法不应该运行在事务上下文中。如果存在当前事务,则会抛出异常。

  • PROPAGATION_NESTED:表示如果当前已经存在一个事务,那么该方法将会在嵌套事务中运行。嵌套的事务可以独立于当前事务进行独立的提交和回滚。如果当前事务不存在,那么其行为与PROPAGATION_REQUIRED一样。注意各厂商对这种传播行为的支持不同,可以参考资源管理器的文档来确认他们是否支持嵌套事务。

e) 事务其他属性

超时时间:默认值是-1,没有超时限制。如果有,以秒为单位进行设置。一般使用默认。
是否只读:建议查询操作时设置为只读,效率更高。

事务中的readOnly属性表示对应的事务会优化为只读事务。如果值为true就会告诉Spring我这个方法里面没有insert或者update,你只需要提供只读的数据库Connection就行了,这种执行效率会比read-write的Connection高。

如果设置了只读事务,Mysql数据库增删改会报错,Oracle无影响(不支持)

TransactionStatus

Spring提供的封装事务状态的接口,用于封装事务的状态。

事务的状态是事务自身的属性,在事务管理不同的时间段,事务会表现出不同的状态,所以不需要配置。

a) 接口中规定的判断事务状态的方法:

方法名 说明
boolean isNewTransaction() 是否是新事务。如果返回false,说明当前事务已存在,或者该操作没在事务环境中。
boolean hasSavepoint() 是否存在回滚点
boolean isRollbackOnly() 判断当前事务是否被设置了rollback-only
boolean isCompleted() 事务是否已结束

声明式事务概述

  • Spring 的声明式事务就是采用声明的方式来设置事务的属性参数,事务会按照指定的规则自动管理运行。

  • 这里所说的声明,指在配置文件中配置(或添加注解)<事务的属性参数>,用在Spring 配置文件(注解)中声明的事务来代替用代码编写的事务。

  • 业务代码运行过程中,Spring容器(中的事务管理器对象)跟据配置文件中的配置参数,动态的把事务加入到业务代码中。(AOP思想)

  • (编码时)事务管理不侵入业务组件。编写业务代码的时候并没有体现事务管理的代码。

  • 事务管理策略维护方便。如果需要修改事务管理策略,只要在配置文件上修改,无需改变代码重新编译。

基于XML的声明式事务管理

配置切点

<!--pointcut 目标对象  内部的方法就是切点-->
<bean id="accountService" class="cs.wy.service.impl.AccountServiceImpl"><property name="accountDao" ref="accountDao"/>
</bean>

配置通知(事务管理器)

<!-- advice 配置通知-事务管理器就是通知(增强)所在的类 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><tx:method name="*"/></tx:attributes>
</tx:advice><!--jdbc 使用的(平台)事务管理器是 DataSourceTransactionManager事务管理管理的是Service层,service层需要调用dao层操作数据库,dao层依赖DataSource管理连接池并连接数据库所以事务管理器中需要注入DataSource
-->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property>
</bean>

配置织入

<!-- weaving 配置事务的织入。 增强方法 + 目标方法 -->
<aop:config><aop:advisor advice-ref="txAdvice"pointcut="execution(* cs.wy.service.impl.*.*(..))"/>
</aop:config>

基于XML的声明式事务管理参数详解

重点分析如下配置:

<!-- advice  配置通知-事务管理器就是通知(增强)所在的类 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><tx:method name="*"/></tx:attributes>
</tx:advice>

其中:

tx:advice        advice,增强方法所在的类(transactionManager的class)tx:attributes具体的事务需要配到这个标签里面tx:method     每一个tx:method代表一个类别事务在这个标签里面的属性上会配置某些业务逻辑的方法(目标方法),并同时配置对应的事务管理逻辑。tx:nethod ~   namename属性,用于配置被切点表达式拦截的所有方法中,哪些业务逻辑方法被当前事务管理。该属性并非Spring事务本身的属性,而是为了让该事务匹配关联到某些业务逻辑方法。name值可以使用*统配,比方说*代表所有方法,save*代表所有save开头的方法tx:nethod ~ isolation               isolation属性,配置当前事务的隔离级别;如不设置或设置DEFAULT,使用默认的隔离级别。mysql默认的Repeatable read,其他大多数是Read committed。tx:method ~ propagationpropagation属性,配置当前事务的传播行为。不设置则使用默认值REQUIRED。tx:method ~ timeouttimeout属性,配置当前事务的超时时间,不设置则使用默认值-1,表示不限制。一般不设置。
tx:method ~ readonlyreadonly属性,值为boolean类型。默认值为false。

关于tx:attributes

a. 如果不配置该标签,所有切点方法都会单独开启属性为默认值的事务
b. 如果配置该标签,内部tx:method中name匹配的方法会按照当前配置开启事务,其他未匹配成功的方法会单独开启属性为默认值的事务
c. 存在多个tx:method标签时,会按照配置顺序挨个匹配,直到匹配成功,未匹配成功开启默认事务     <tx:attributes>  <tx:method name="add*" propagation="REQUIRED"/>  <tx:method name="upd*" propagation="REQUIRED"/>  <tx:method name="del*" propagation="REQUIRED"/> <tx:method name="*" propagation="SUPPORTS" read-only="true" />
</tx:attributes>

关于切点表达式:多个切点表达式可以进行逻辑运算连接(主要使用或||):

<aop:pointcut id="tranpc" expression="execution(* cs.wy.user.service.*.*(..))|| execution(* cs.wy.goods.service.*.*(..))"/>

关于readonly

对于mysql数据库:如果是查询操作,建议设为true,优化查询性能;其他设为false或者不设置使用默认值。增删改操作如果设置为true,则会抛出异常。
对于Oracle数据库:无效果

基于注解的声明式事务控制

使用基于注解的声明式事务控制,步骤如下:

1、 在xml中开启自动代理

<aop:aspectj-autoproxy/>

2、然后在方法或类上配置@Transactional注解

1. 配置在类上表示该类下所有方法均开启事务
2. 配置在方法上,表示该方法开启事务
  1. 推荐做法:
在类上添加@Transactional统一开启事务,
如有需要,可以在特定方法上添加@Transactional用于配置特属性。
@Transactional(readOnly = true,,propagation = Propagation.SUPPORTS)

【SSM框架系列】Spring - JdbcTemplate声明式事务相关推荐

  1. 06_02_任务三:Spring JDBCTemplate 声明式事务

    任务三:Spring JDBCTemplate & 声明式事务 课程任务主要内容: Spring的JdbcTemplate Spring的事务 Spring集成web环境 一 Spring的J ...

  2. (续)SSM整合之spring笔记(声明式事务)(P110-116)

    目录 一 .声明式事务概念 二 .基于注解的声明式事务 1 .准备工作 (1)加入依赖 (2)创建jdbc.properties (3)配置Spring的配置文件     tx-annotation. ...

  3. 保护亿万数据安全,Spring有“声明式事务”绝招

    摘要:点外卖时,你只需考虑如何拼单:选择出行时,你只用想好目的地:手机支付时,你只需要保证余额充足.但你不知道这些智能的背后,是数以亿计的强大数据的支持,这就是数据库的力量.那么庞大数据的背后一定会牵 ...

  4. spring配置c3p0连接池、spring的声明式事务管理

    一.spring配置c3p0连接池: 1.导入maven依赖: <!-- https://mvnrepository.com/artifact/com.mchange/c3p0 --> & ...

  5. ❤️Spring的声明式事务

    ❤️Spring的声明式事务 事务在项目开发过程非常重要,涉及到数据的一致性的问题,不容马虎! 事务管理是企业级应用程序开发中必备技术,用来确保数据的完整性和一致性. 事务就是把一系列的动作当成一个独 ...

  6. Spring的声明式事务底层原理

    文章目录 声明式事务的概述 声明式事务的初探 声明式事务的源码分析 声明式事务的概述 Spring 的声明式事务管理在底层是建立在 AOP 的基础之上的.其本质是对方法前后进行拦截,然后在目标方法开始 ...

  7. 【Spring】——声明式事务配置详解

    事务管理是企业级应用程序开发中必备技术,用来确保数据的完整性和一致性.本文主要讲解事务涉及到一些概念以及spring中事务的使用.如有理解偏颇之处,恳请各位大神指正,小编不胜感激! 1.何为事务? 事 ...

  8. Spring AOP声明式事务

    Spring AOP声明式事务 Spring AOP声明式事务 传统spring配置 SpringBoot配置 Spring AOP声明式事务 Spring AOP声明式事务可以帮我们自动管理事务,在 ...

  9. (Spring)声明式事务

    Spring中的事务管理 Spring在不同的事务管理API之上定义了一个抽象层,使得开发人员不必了解底层的事务管理API就可以使用Spring的事务管理机制.Spring支持编程式事务管理和声明式的 ...

最新文章

  1. 上证所Level-2在信息内容和传送方式方面的比较优势[逐笔数据与分笔数据的根本区别]...
  2. 一文搞定Vim/Vi编辑器
  3. 史上最轻量​!阿里新型单元测试Mock工具开源了
  4. SQL 连接字符串的说明(转)
  5. 用Python进行屏幕截图,只用两行代码搞定
  6. 计算机课程在线作业,计算机科学与技术作业答案
  7. JVM内存:年轻代,老年代,永久代
  8. 读博总结的总结:读博的那些事儿
  9. TOPSIS(优劣解距离法)
  10. mysql自学完整_MySQL自学篇(三)
  11. Mac应用程序无法打开提示不明开发者?别着急看这里
  12. 中国光学级聚酯薄膜市场趋势分析与营销策略研究报告2022版
  13. 北京理工大学抢课教程
  14. 《kafka面试100例 -6》如果在/admin/delete_topics/中手动写入一个节点会不会正常删除Topic
  15. 修改源码刷步数、年会摇一摇数据
  16. 计算机操作电脑试题评分标准,2014计算机一级上机试题(1—5套)评分标准.docx
  17. 服务请求2XX、5XX等错误具体是什么
  18. 历史小故事----BUG的来源
  19. 通过网页或者移动设备链接跳转qq(tim)添加好友(群)
  20. 帆软填报问题之填报显示提交成功,数据库却查不到数据

热门文章

  1. magento 给My Account,Log In,Contact Us链接增加nofollow标签
  2. 安装nexus时遇到的一个问题
  3. 纯真IP库的结构分析及一个查询类
  4. 成功修改fastreport3.15,使其支持中日韩四(CJK)中编码PDF的导出
  5. ARM中MMU的作用
  6. 简单但经典的算法题:有效字母的异位词
  7. MySQL第12天:MySQL索引优化分析之性能优化案例实践
  8. 数据结构: 顺序存储二叉树
  9. bzoj 2878 [Noi2012]迷失游乐园——树上的期望dp
  10. 《java编程思想》学习笔记——复用类