Spring學習(四)Jdbc連線池交個spring管理和事務操作
阿新 • • 發佈:2018-12-30
一、連線池的配置交給Spring管理
1,新增jar包
2,spring的jdbc連線池配置
<!-- 配置連線池 -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="password" value="tianyejun" />
<property name="username" value="root" />
<property name="url" value="jdbc:mysql:///springday3" />
</bean>
<!-- 配置jdbc的模板類 -->
<bean id="JdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name ="dataSource" ref="dataSource"></property>
</bean>
3,測試類
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Demo1 {
/**
* 使用ioc的方式
*/
@Resource(name = "JdbcTemplate")
private JdbcTemplate JdbcTemplate;
@Test
public void run2() {
// 可以實現對資料庫的cud
JdbcTemplate.update("insert into t_account values(null,?,?)", "3343", "1000");
}
/**
* 資料庫查詢
*/
@Test
public void runQuery() {
//查詢一條資料
AccontBean bean =JdbcTemplate.queryForObject("select * from t_account where id=?", new String[] { "1" },
new MyrowMapper());
System.out.println(bean.toString());
// 查詢所有資料
List<AccontBean> list = (List<AccontBean>) JdbcTemplate.query("select * from t_account",new MyrowMapper());
System.out.println(list);
}
public class MyrowMapper implements RowMapper<AccontBean> {
@Override
public AccontBean mapRow(ResultSet rs, int rowNum) throws SQLException {
AccontBean bean = new AccontBean();
bean.setName(rs.getString(2));
bean.setPrice(rs.getInt(3));
return bean;
}
}
}
}
二、Spring的事物管理
1,事物的特性
原子性 :強調事務的不可分割.
一致性 :事務的執行的前後資料的完整性保持一致.
隔離性 :一個事務執行的過程中,不應該受到其他事務的干擾
永續性 :事務一旦結束,資料就持久到資料庫
2,事物的傳播行為
PROPAGION_XXX :事務的傳播行為
- 保證同一個事務中
PROPAGATION_REQUIRED:支援當前事務,如果不存在 就新建一個(預設)
PROPAGATION_SUPPORTS:支援當前事務,如果不存在,就不使用事務
PROPAGATION_MANDATORY:支援當前事務,如果不存在,丟擲異常
- 保證沒有在同一個事務中
PROPAGATION_REQUIRES_NEW: 如果有事務存在,掛起當前事務,建立一個新的事務
PROPAGATION_NOT_SUPPORTED :以非事務方式執行,如果有事務存在,掛起當前事務
PROPAGATION_NEVER : 以非事務方式執行,如果有事務存在,丟擲異常
PROPAGATION_NESTED: 如果當前事務存在,則巢狀事務執行
案例:模擬銀行轉賬漏洞環境
(1)建立業務層
業務層介面類:
public interface AccountServiceInter {
public void pay(String out, String in, double money);
}
業務層介面實現類
public class AccountServiceImp implements AccountServiceInter {
private AccountDaoInter acountdao;
/**
* 轉賬的方法
*/
@Override
public void pay(String out, String in, double money) {
// 先價錢
getAcountdao().outMoney(out, money);
/**
*這裡人為製造一個異常,造成轉賬出現異常
*/
int a=10/0;
// 後加錢
getAcountdao().inMoney(in, money);
}
public AccountDaoInter getAcountdao() {
return acountdao;
}
public void setAcountdao(AccountDaoInter acountdao) {
this.acountdao = acountdao;
}
}
(2)建立dao層
dao介面類
public interface AccountDaoInter {
// 扣錢
public void outMoney(String out, double money);
// 加錢
public void inMoney(String in, double money);
}
dao介面實現類
public class AccountDaoImp extends JdbcDaoSupport implements AccountDaoInter {
/**
* 扣錢
*/
@Override
public void outMoney(String out, double money) {
int update = this.getJdbcTemplate().update("update t_account set money=(money-?) where id=?", money, out);
System.out.println("fdafd" + update);
}
/**
* 加錢
*/
@Override
public void inMoney(String in, double money) {
int update = this.getJdbcTemplate().update("update t_account set money=(money+?) where id=?", money, in);
System.out.println("fdafd" + update);
}
}
(3)spring中配置業務層和dao
<!-- 配置連線池 -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="password" value="tianyejun6" />
<property name="username" value="root" />
<property name="url" value="jdbc:mysql:///springday3" />
</bean>
<!-- service業務層 -->
<bean id="accountService" class="com.itcast.test1.AccountServiceImp">
<property name="acountdao" ref="accountDaoImp"></property>
</bean>
<!-- 持久層dao -->
<bean id="accountDaoImp" class="com.itcast.test1.AccountDaoImp">
<property name="dataSource" ref="dataSource" />
</bean>
(4)編寫測試類
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Test1 {
@Resource(name = "accountService")
private AccountServiceInter accountService;
DataSourceTransactionManager a;
@Test
public void run1() {
accountService.pay("1", "3", 100);
}
}
總結:上面轉賬過程如果出現異常情況,就會造成轉賬漏洞,所以採用下面AOP轉賬方式
三、spring事務管理採用AOP方式
1,引入jar包
2,配置事務管理器 ,開啟事物註解
<!-- 1,配置平臺事務管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 開啟註解事務管理 -->
<tx:annotation-driven
transaction-manager="transactionManager"/>
3,配置事務的通知
<!-- 2,配置通知 -->
<tx:advice id="myAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!--
isolation="DEFAULT" 隔離級別
propagation="REQUIRED" 傳播行為
read-only="false" 只讀
timeout="-1" 過期時間
rollback-for="" -Exception
no-rollback-for="" +Exception
-->
<tx:method name="pay" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>
4,配置AOP
<!--
配置AOP:如果是自己編寫的aop使用<aop:aspect>;
如果使用spring框架提供的通知使用<aop:advisor/>
-->
<aop:config>
<aop:advisor advice-ref="myAdvice"
pointcut="execution(public * com.itcast.test2.AccountServiceImp.pay(..))"/>
</aop:config>
5,實現程式碼
(1)業務層
業務層介面
public interface AccountServiceInter {
public void pay(String out, String in, double money);
}
業務層介面實現類
/**
*
*@Transactional 新增到類上,該類所有的方法都有事務
*/
@Transactional
public class AccountServiceImp implements AccountServiceInter {
private AccountDaoInter acountdao;
/**
* 轉賬的方法
*/
@Override
@Transactional
public void pay(String out, String in, double money) {
// 先價錢
getAcountdao().outMoney(out, money);
// int a=10/0;
// 後加錢
getAcountdao().inMoney(in, money);
}
public AccountDaoInter getAcountdao() {
return acountdao;
}
public void setAcountdao(AccountDaoInter acountdao) {
this.acountdao = acountdao;
}
}
(2)dao層
dao介面類
public interface AccountDaoInter {
// 扣錢
public void outMoney(String out, double money);
// 加錢
public void inMoney(String in, double money);
}
dao實現介面類
public class AccountDaoImp extends JdbcDaoSupport implements AccountDaoInter {
/**
* 扣錢
*/
@Override
public void outMoney(String out, double money) {
int update = this.getJdbcTemplate().update
("update t_account set money=(money-?) where id=?", money, out);
System.out.println("fdafd" + update);
}
/**
* 加錢
*/
@Override
public void inMoney(String in, double money) {
update("update t_account set money=(money+?) where id=?", money, in);
System.out.println("fdafd" + update);
}
}
(3)Spring的xml配置
<!-- 配置連線池 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="password" value="tianyejun6" />
<property name="username" value="root" />
<property name="url" value="jdbc:mysql:///springday3" />
</bean>
<!-- service業務層 -->
<bean id="accountService" class="com.itcast.test2.AccountServiceImp">
<property name="acountdao" ref="accountDaoImp"></property>
</bean>
<!-- 持久層dao -->
<bean id="accountDaoImp" class="com.itcast.test2.AccountDaoImp">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 1,配置平臺事物管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 宣告式事物 -->
<!-- 2,配置通知 -->
<tx:advice id="myAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="pay" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>
<!--
配置AOP:如果是自己編寫的aop使用<aop:aspect>;
如果使用spring框架提供的通知使用<aop:advisor/>
-->
<aop:config>
<aop:advisor advice-ref="myAdvice"
pointcut="execution(public * com.itcast.test2.AccountServiceImp.pay(..))"/>
</aop:config>
(4)測試類
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext2.xml")
public class Test1 {
@Resource(name = "accountService")
private AccountServiceInter accountService;
DataSourceTransactionManager a;
@Test
public void run1() {
accountService.pay("1", "3", 100);
}
}
(5)原始碼