Spring JDBC
一.基本用法
1.1 添加依賴
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
1.2配置Dao
DataSource-->JdbcTemplate-->Dao-->Service-->Action
1.3配置DataSource
DataSource的實現方式:
- 使用Spring提供的數據源(DriverManagerDataSource),沒有連接池的功能,效率低
- 使用第三方的數據源,如:dbcp,c3p0,druid(德魯伊)
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
二、用戶注冊
JDBC默認是自動提交數據的,每執(zhí)行完一條sql語句就提交事務
解決:配置事務
Spring事務管理
一、兩種方式
定義事務管理器,相當于事務的通知
<!--配置事務管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
- 方式1:基于命名空間
<!--定義通知,并指定事務管理器-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--配置事務屬性-->
<tx:attributes>
<tx:method name="login" propagation="SUPPORTS" read-only="true"/>
<tx:method name="regist" propagation="REQUIRED" isolation="READ_COMMITTED" no-rollback-for="java.lang.ArithmeticException"
timeout="5000" />
</tx:attributes>
</tx:advice>
<aop:config>
<!--配置切入點-->
<aop:pointcut id="pc" expression="execution(* com.hxx.service.impl.*.*(..))"/>
<!--進行織入-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="pc"/>
</aop:config>
- 方式2:基于注解
@Transactional(propagation = Propagation.REQUIRED,rollbackFor = NullPointerException.class,
timeout = 5000)
<!--配置注解驅動-->
<tx:annotation-driven transaction-manager="transactionManager"/>
二、事務屬性
五個事務屬性:
-
傳播屬性
propagation:定義事務的邊界,用來定義當前方法是否需要事務。
常用取值:- REQUIRED:必須添加事務,如果當前沒有事務,則創(chuàng)建一個新的事務,一般用于增刪改操作。
- SUPPORTS:可以沒有事務,如果當前有事務則運行,如果沒有事務也可以運行,一般用于查詢操作。
-
隔離級別
isolation:用來解決事務并發(fā)時會出現的一些問題。
四種隔離級別:- TRANSACTION_READ_COMMITTED:已提交讀——>可以避免臟讀,但是可能發(fā)生不可重復讀和幻讀。
- TRANSACTION_READ_UNCOMMITTED:未提交讀——>可能會發(fā)生臟讀,不可重復讀和幻讀。
- TRANSACTION_REPEATABLE_READ:可重復讀——>可避免臟讀和不可重復讀,但可能會發(fā)生幻讀。
- TRANSACTION_SERIALIZABLE:可序列化——>可以避免臟讀,不可重復讀和幻讀,相當于單并發(fā),沒意義。
事務并發(fā)時可能會出現的三個問題:
- 臟讀:一個事務讀取到另一個事務沒有提交的數據,一般不會發(fā)生,如MySql、Oracle底層默認只允許讀取已經提交的數據。
- 不可重復讀:一個事務已經讀取數據,另一個事務在修改數據,可能導致使用的數據與數據庫中不同步。
- 虛讀或幻讀:一個事務已經讀取數據,另外一個事務在添加或刪除數據,可能導致數據量與數據庫不同步。
注意:不可重復讀和幻讀是小概率事件,發(fā)生的幾率比較低??梢酝ㄟ^版本檢查來解決,如:Hibernate中的悲觀鎖和樂觀鎖就是通過版本檢查來實現的,不但麻煩而且效率還低。實際開發(fā)中一般不需要配置隔離級別,大多是通過定時任務+人工審核。
回滾條件
rollback:默認拋出RuntimeException時才會回滾
rollbackFor=""表示發(fā)生該異常時回滾
norollbackFor=""表示發(fā)生該異常時不回滾只讀優(yōu)化
readOnly:在該事務中只允許讀取數據,一般用于查詢超時處理
timeout:配置事務的超時時間,一般不配置
三、事務特性
四個事務特性:ACID 原子性、一致性、隔離性、永久性