目录
- 使用数据库连接池druid进行数据库操作
- 数据库事务异常回滚----配置方式和注解方式
- 附:开启 spring 的所有注解支持
一、使用数据库连接池druid进行数据库操作
1.导包
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.19</version>
</dependency>
将数据库连接池配置到spring中,即数据库连接交给spring管理
数据库连接池:,管理整个数据库应用中数据库连接线程的各值,最大最小连接数,最大最小闲置数,数据库连接等待时间等 ,节约资源。
2.使用数据库连接池,必须用到数据库连接的配置文件,因此需要在applicationContext.xml文件中引入:
<!-- 读取类路径下的properties文件中的配置 -->
<context:property-placeholder location="classpath:jdbc.properties" />
读取配置文件后会将文件中的key作为工程中的key,然后可以通过“$”符号引入如:${jdbc.driverClassName}
jdbc.properties文件:
jdbc.username=root
jdbc.password=**********
jdbc.url=jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
jdbc.driverClassName=com.mysql.cj.jdbc.Driver
3.spring整合(阿里)druid连接池的通用配置:
<!-- 将其他人写的bean,整合为当前工程的一个组件,复制即可用 -->
<!-- 不求甚解 -->
<!-- 数据源 -->
<bean id="dataSource"
//使用阿里的class文件,创建出一个bean
class="com.alibaba.druid.pool.DruidDataSource" init-method="init"
destroy-method="close">
<property name="driverClassName"
value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<!-- 配置初始化大小、最小、最大 -->
<property name="initialSize" value="1" />
<property name="minIdle" value="1" />
<property name="maxActive" value="10" />
<!-- 配置获取连接等待超时的时间 -->
<property name="maxWait" value="10000" />
<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="60000" />
<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="300000" />
<property name="testWhileIdle" value="true" />
<!-- 这里建议配置为TRUE,防止取到的连接不可用 -->
<property name="testOnBorrow" value="true" />
<property name="testOnReturn" value="false" />
<!-- 打开PSCache,并且指定每个连接上PSCache的大小 -->
<property name="poolPreparedStatements" value="true" />
<property name="maxPoolPreparedStatementPerConnectionSize"
value="20" />
<!-- 这里配置提交方式,默认就是TRUE,可以不用配置 -->
<property name="defaultAutoCommit" value="true" />
<!-- 验证连接有效与否的SQL,不同的数据配置不同 -->
<property name="validationQuery" value="select 1 " />
<property name="filters" value="stat" />
<!-- <property name="proxyFilters"> <list> <ref bean="logFilter" /> </list>
</property> -->
</bean>
有了数据库连接池通用配合,我们需要spring依据数据库连接池标准封装好的 jdbc 操作模板,可以方便操作数据库连接池 和数据源dataSource
<!-- jdbc操作模板,spring提供的,简单用来操作数据库的工具 -->
<bean id="jdbcTemplate"
class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
使用依赖注入,<property name=“dataSource” ref=“dataSource”>让数据库连接池引用我们配置好的dataSource
@Repository 数据库层注解,注册到Spring容器中
4.服务层实现类UserServiceImpl.java
@Service //or @Repository(userServiceImpl)
public class UserServiceImpl implements UserService{
@Autowired
private UserDao userDao;
//out给in转money
public int transfer(Integer in, Integer out, Double money) {
userDao.addMoney(in, money);
userDao.costMoney(out, money);
return 1;
}
}
主类调用:
public class TxApplication {
public static void main(String [] args) {
ApplicationContext ac =new ClassPathXmlApplicationContext("applicationContext.xml");
UserService us = (UserService) ac.getBean("userServiceImpl");
us.transfer(1, 3, 30d);
}
}
数据库中实现3号用户给一号用户转账30.
二、事务
事物四个特性:
①原子性(Atomic),事务包含的所有操作要么全部成功,要么全部失败回滚;
②隔离性(Durability),当多个用户并发访问数据库时,数据库为每一个用户开启的事务,不被其他事务的操作所干扰,多个并发事务之间要相互隔离;
③一致性(Isolation),事务执行前和执行后必须处于一致性状态;
④持久性(Consistency),一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便在数据库系统遇到故障的情况下也不会丢失事物的操作。
此处特性的解释引用于网络:https://www.cnblogs.com/melody210218/p/7120559.html
1.事务回滚-----配置方式实现
1)引进 spring 整合 jdbc 的 jar 包后,在命名空间中勾选事务相关的约束
2)将事务管理器注册到spring容器中
<!-- spring提供的事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>//事务管理和操作都是对同一数据源
</bean>
加上配置
<!-- 事务配合AOP使用 -->
<tx:advice transaction-manager="transactionManager"
id="txAdvice">
<tx:attributes>
<!-- method相当于一个过滤器,对被切中的所有方法中
只有以Tx结尾的方法才开启事务回滚功能 -->//这里有个*号
<tx:method name="*Tx"/>
</tx:attributes>
</tx:advice>
<!-- 事务通知spring已经写好(异常回滚) -->
<aop:config><!-- 所有业务层的方法都被这个事务通知通知到 -->
<aop:advisor advice-ref="txAdvice" pointcut="execution(* net.xikee..*.service.impl.*.*(..))"/>
</aop:config>
3)在对数据库的两次操作之间加个异常代码:
数据库中1号用户余额从150变成180,而3号用户仍然是680
4)将transfer方法改为transferTx后,数据库事务实现了异常回滚功能。
2.事务回滚----注解方式实现
1)提供事务管理器
<!-- spring提供的事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
在spring容器中开启事务控制注解支持:
<!-- 开启事务控制注解支持 ;
transaction-manager属性告诉spring事务控制器是哪一个;
false为JDK方式实现默认可不写,而非CGLIB方式-->
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="false"/>
2)在类上面加上@transactional, 那么这个类所有方法都会开启事务控制
如果在方法上面加上@transactional,表示对单个方法开启事务控制(类上面的注解则删掉)即可。
三、开启 spring 的所有注解支持:
<!-- 开启对于Spring组件扫描的支持 -->
<context:component-scan base-package="net.xikee"></context:component-scan>
<!-- 开启对AOP注解支持 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<!-- 开启事务控制注解支持
transaction-manager属性告诉spring事务控制器是哪个
false为JDK方式实现默认可不写,而非CGLIB方式-->
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="false"/>