Spring常见数据源及声明式事务配置

Spring自带了一组数据访问框架,集成了多种数据访问技术。无论我们是直接通过 JDBC 还是像Hibernate或Mybatis那样的框架实现数据持久化,Spring都可以为我们消除持久化代码中那些单调枯燥的数据访问逻辑。Spring对大多数的持久化方式提供支持。

​   Spring在数据访问中使用模板的模式,将访问过程中固定的和可变的部分明确划分为两个不同的类:模板(template)和回调(callback)。模板处理数据访问中固定的部分——事务控制、管理资源及处理异常,而回调处理应用程序相关的的数据访问——语句、绑定参数及整理结果集。基于此,我们只需关心自己的数据访问逻辑即可。

​ 针对不同的持久化平台,Spring提供了多个可选的模板,如果直接使用JDBC,那么我们可以选择JdbcTemplate。

一.常见数据源的配置
​ 无论我们选择哪一种数据访问方式,都需要配置一个数据源的引用。我们总结了几种常见的数据源配置方式。

1.导入外部的数据源属性配置文件
jdbc.properties:
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///spring_02
jdbc.username=sh
jdbc.password=sh123
applicationContext.xml中进行导入
复制代码

复制代码 1.Spring内置数据源 第一步:导入jar包或Maven坐标 org.springframework spring-jdbc 5.0.2.RELEASE 第二步:在applicationContext.xml中配置 复制代码 复制代码 Tips: DriverManagerDataSource是一个标准的数据源(实现了接口javax.sql.DataSource)。没有连接池技术,没次都会获取新的数据库连接。用于学习、练习及小应用。

2.C3P0数据源
第一步:导入jar包或Maven坐标

com.mchange
c3p0
0.9.5.2

第二步:在applicationContext.xml中配置
复制代码

复制代码 Tips: C3P0是一个标准的数据源,带有池技术,适合生产环境。

3.Druid数据源
第一步:导入jar包或Maven坐标

com.alibaba
druid
1.0.14

第二步:在applicationContext.xml中配置
复制代码

复制代码 Tips: Druid是一个标准数据源,带有池技术,适合生产环境

4.DBCP数据源
第一步:导入jar包或Maven坐标

commons-dbcp
commons-dbcp
1.4

第二步:在applicationContext.xml中配置
复制代码

复制代码 Tips: tomcat内置的就是dbcp数据源,也是一个标准的数据源,带有池技术,适合生产环境。

二、JdbcDaoSupport
1.使用jdbcTemplate
dao实现类关键代码
复制代码
public class AccountDaoImpl implements AccountDao {
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public void add(Account account) {
jdbcTemplate.update(“insert into accounts VALUES (null,?,?)”
,account.getAccountName(),account.getBalance());
}
复制代码
applicationContext.xml关键配置
复制代码

--> 复制代码 2.继承JdbcDaoSupport JdbcDaoSupport是Spring框架为我们提供的一个类,该类中定义了一个JdbcTemplate对象,我们可以直接获取使用,但是要创建该对象,需要为其提供一个数据源:

JdbcDaoSupport关键源代码
复制代码
public abstract class JdbcDaoSupport extends DaoSupport {
@Nullable
private JdbcTemplate jdbcTemplate;

public JdbcDaoSupport() {
}
public final void setDataSource(DataSource dataSource) {
    if (this.jdbcTemplate == null || dataSource != this.jdbcTemplate.getDataSource()) {
        this.jdbcTemplate = this.createJdbcTemplate(dataSource);
        this.initTemplateConfig();
    }
}
protected JdbcTemplate createJdbcTemplate(DataSource dataSource) {
    return new JdbcTemplate(dataSource);
}

复制代码
dao实现类关键代码
复制代码
// 此时,实现类需要继承JdbcDaoSupport
public class AccountDaoImpl1 extends JdbcDaoSupport implements AccountDao {
public void add(Account account) {//父类的 getJdbcTemplate()方法。
getJdbcTemplate().update(“insert into accounts VALUES (null,?,?)”
,account.getAccountName(),account.getBalance());
System.out.println(“是我,没错”);
}
复制代码
applicationContext.xml关键配置

Tips: 因为AccountDaoImpl1继承了JdbcDataSupport,所以我们这里配置子类(间接给父类)就

​ 可以。当然,我们也可以不配置数据源,直接配置(间接给父类)一个jdbcTemplate也是可

​ 以的。

总结:
第一种在Dao类中定义JdbcTemplate的方式,适用于所有配置方式(xml和注解都可以)。

第二种让Dao继承JdbcDaoSupport的方式,只能用于基于xml的方式,注解用不了。

三、声明式事务的配置
1.Spring事务控制的API简介
1.1PlatformTransactionManager
​ 此接口是Spring的事务管理器,提供了常用的操作事务的方法,包含3个具体的操作

获取事务状态信息:Transaction getTransaction(TransactionDefinition definition)

提交事务: void commit(TransactionStatus status)

回滚事务: void rollback(TansactionStatus status)

我们在开发时都是使用它的实现类,在使用Spring JDBC或Mybatis进行持久化数据时,真正管理事务的对象是:

org.springframework.jdbc.datasource.DataSourceTransactionManager

1.2TransactionDefinition
​ 它是事务的定义信息对象,内有如下方法:

获取事务对象名称 :String getName()

获取事务隔离级别 : int getIsolationLevel()

获取事务传播行为 : int getPropagationBehavior()

获取事务超时时间 : int getTimeOut()

获取事务是否是只读 : boolean isReadOnly()

Tips: 并不是所有的数据库都支持事务支持的,默认为-1,即没有超时限制。

​ 读写型事务:增删改时开启事务。

​ 只读型事务:执行查询时也开启事务。

事务的传播行为
m1方法有自己的事务,m2方法也有自己的事务,若m2方法中调用了m1的方法,那m1该采用什么用的事务?

​ 这里只介绍常用的两种:

REQUIRED:若m2有事务,则m1加入到m2的事务;若m2没有事务,m1用自己的事务。

SUPPORTS:若m2有事务,则m1加入到m2的事务;若m2没有事务,m1放弃事务。

1.3TransactionStatus
此接口提供事务具体的运行状态:

刷新事务 : void flush()

是否有存储点:boolean hasSavepoint()

事务是否完成:boolean isCompleted()

是否为新的事务: isNew Transaction()

事务是否回滚: boolean isRollbackOnly()

设置事务回滚:void setRollbackOnly()

2.事务管理器 DataSourceTransactionManager
​ 事务控制是横切面问题,采用AOP编程,通知代码即事务管理器是一个实现了

PlatformTransactionManager的类,Spring已经为我们提供好了。这里我们使用

DataSourceTransactionManager。

Tips: 此事务管理器仅用于实现了标准数据源的事务控制。

3.基于xml的事务控制配置
第一步:编写核心业务代码
复制代码
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
public void transfer(String sourceAccount, String targetAccount, Float money) {
Account source = accountDao.findByName(sourceAccount);
Account target = accountDao.findByName(targetAccount);
source.setBalance(source.getBalance()-money);
target.setBalance(target.getBalance()+money);
accountDao.update(source);
// int i=1/0;
accountDao.update(target);
复制代码
第二步:配置applicationContext.xml
复制代码

<context:property-placeholder location=“classpath:jdbc.properties”/>

-->



<tx:advice id=“txAdvice” transaction-manager=“transactionManager” >
tx:attributes
<tx:method name=“transfer” propagation=“REQUIRED” read-only=“false”/>
<tx:method name=“add*” propagation=“REQUIRED” read-only=“false”/>
</tx:attributes>
</tx:advice>

aop:config
<aop:advisor advice-ref=“txAdvice” pointcut=“execution(* cn.dintalk….(…))”/>
</aop:config>
复制代码
Tips: 事务通知属性中的method配置精确控制到方法名,而切点的配置则是模糊匹配。两者并不冲突,而是相互

​ 配合。

如果事务管理器的id为“transactionManager" 则事务通知中的:transaction-manager=”…“可以省略。

4.基于注解的事务控制配置
第一步:添加IOC注解
复制代码
// dao实现类关键代码
@Repository
public class AccountDaoImpl implements AccountDao {
@Autowired
private JdbcTemplate jdbcTemplate;
// service实现类关键代码
@Service(“accountService”)
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountDao accountDao;
//配置事务管理器
//要求事务管理器id必须是transactionManager方可省略
@Transactional(readOnly = false,propagation = Propagation.REQUIRED)
public void transfer(String sourceAccount, String targetAccount, Float money) {
Account source = accountDao.findByName(sourceAccount);
Account target = accountDao.findByName(targetAccount);
source.setBalance(source.getBalance()-money);
target.setBalance(target.getBalance()+money);
accountDao.update(source);
// int i=1/0;
accountDao.update(target);
}
复制代码
第二步:添加applicationContext.xml关键配置
复制代码

<context:component-scan base-package=“cn.dintalk”/>



<tx:annotation-driven transaction-manager=“transactionManager”/>
复制代码
第三步:测试关键代码(xml和注解方式通用)
复制代码
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(“classpath:applicationContext.xml”)
public class AccountServiceTest {
@Autowired
private AccountService accountService;
@Test
public void testTransfer(){
accountService.transfer(“a”,“b”,1f);
}
复制代码
5.基于类的事务控制配置
第一步:编写配置类
复制代码
@ComponentScan(“cn.dintalk”)
@PropertySource(“classpath:jdbc.properties”)// 加载外部属性配置文件
@EnableTransactionManagement //开启注解事务的支持
public class SpringConfig {
@Value(" j d b c . d r i v e r C l a s s N a m e " ) p r i v a t e S t r i n g d r i v e r C l a s s N a m e ; @ V a l u e ( " {jdbc.driverClassName}") private String driverClassName; @Value(" jdbc.driverClassName")privateStringdriverClassName;@Value("{jdbc.url}")
private String url;
@Value(" j d b c . u s e r n a m e " ) p r i v a t e S t r i n g u s e r n a m e ; @ V a l u e ( " {jdbc.username}") private String username; @Value(" jdbc.username")privateStringusername;@Value("{jdbc.password}")
private String password;
// 将数据源交予Spring容器
@Bean(“dataSource”)
public DataSource createDataSource(){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClass(driverClassName);
dataSource.setJdbcUrl(url);
dataSource.setUser(username);
dataSource.setPassword(password);
return dataSource;
}
//将jdbcTemplate交予Spring容器
@Bean(“jdbcTemplate”)
public JdbcTemplate createJdbcTem(@Qualifier(“dataSource”) DataSource dataSource){
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
return jdbcTemplate;
}
//将事务管理器交予Spring容器
@Bean(“transactionManager”)
public DataSourceTransactionManager createTransManager(@Qualifier(“dataSource”)
DataSource dataSource){
DataSourceTransactionManager dataSourceTransactionManager =
new DataSourceTransactionManager(dataSource);
return dataSourceTransactionManager;
}
}
复制代码
第二步:添加IOC注解
复制代码
// dao实现类关键代码
@Repository
public class AccountDaoImpl implements AccountDao {
@Autowired
private JdbcTemplate jdbcTemplate;
// service实现类关键代码
@Service(“accountService”)
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountDao accountDao;
//配置事务管理器
//要求事务管理器id必须是transactionManager方可省略
@Transactional(readOnly = false,propagation = Propagation.REQUIRED)
public void transfer(String sourceAccount, String targetAccount, Float money) {
Account source = accountDao.findByName(sourceAccount);
Account target = accountDao.findByName(targetAccount);
source.setBalance(source.getBalance()-money);
target.setBalance(target.getBalance()+money);
accountDao.update(source);
// int i=1/0;
accountDao.update(target);
}
复制代码
第三步:测试关键代码
复制代码
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {SpringConfig.class})
public class AccountServiceClassTest {
@Autowired
private AccountService accountService;
@Test
public void testTransfer(){
accountService.transfer(“a”,“b”,3f);
}
出处:http://www.cnblogs.com/dintalk/
欢迎转载,但必须给出原文链接,并保留此段声明。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值