Spring学习第四天(Spring中的JdbcTemplate的使用、Spring中的事务控制)

一、Spring中JdbcTemplate的使用
1.当不继承JdbcDaoSupport时,需要定义JdbcTemplate对象,并在xml文件中配置JdbcTemplate和注入DataSource对象

1.JdbcDaoSupport的使用:让持久层继承JdbcDaoSupport类就能不用定义JdbcTemplate对象,免去了注入JdbcTemplate的步骤
注意 :免去定义JdbcTemplate对象后,需要使用父类的getJdbcTemplate()方法来调用JdbcTemplate的方法。
Java代码

    public class AccountDaoImpl extends JdbcDaoSupport implements IAccountDao {

    public Account findAccountById(Integer accountId) {
        List<Account> accounts = getJdbcTemplate().query("select * from account where id = ?",new BeanPropertyRowMapper<Account>(Account.class),accountId);
        return accounts.isEmpty() ? null : accounts.get(0);
    }

XML代码(将注入jdbcTemplate改为注入DataSource)

  	<!--配置AccountDao类-->
    <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl">
        <!--<property name="jdbcTemplate" ref="jdbcTemplate"></property>-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>

2.注解配置JdbcTmplate
重点:注解配置是直接@Autowired注入
Java代码

 	@Repository("accountDao")
    public class AccountDaoImpl2  implements IAccountDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;
二、Spring中的事务控制

1、 事务控制的API介绍

	1.1 PlatformTransactionManager:此接口是spring的事务管理器,它里面提供了我们常用的操作事务的方法
            真正管理事务的对象 org.springframework.jdbc.datasource.DataSourceTransactionManager 使用Spring JDBC或iBatis 
            进行持久化数据时使用 org.springframework.orm.hibernate5.HibernateTransactionManager 使用Hibernate版本进行持久化数据时使用
	1.2 TransactionDefinition:    它是事务的定义信息对象。有如下方法
        // 获取事务对象名称
        - String getName();
        // 获取事务隔离级别
        - int getIsolationLevel();
        // 获取事务传播行为
        - int getPropagationBehavior() 
        // 获取事务超时时间
        - int getTimeout()
        // 获取事务是否只读
        - boolean isReadOnly()
	1.3 事务的传播行为
        REQUIRED: 不管原来有无事务,添加后都有事务。一般的选择(默认值) (适用于增删改)
        SUPPORTS: 如果当前没有事务,就以没有事务执行,如果有事务就以有事务执行。(适用于查询)

2、基于XML的AOP实现事务控制
注意:通过XML配置AOP的事务时顺序必须正确,否则会按照错误顺序执行事务。
例如:
XML代码

	<!--配置aop-->
	<aop:config>
	    <!--配置通用切入点表达式-->
	    <aop:pointcut id="pt1" expression="execution(* com.itheima.service.impl.*.*(..))"/>
	    <aop:aspect id="txAdvice" ref="txManager">
	        <!--配置前置通知:开启事务-->
	        <aop:before method="beginTransaction" pointcut-ref="pt1" ></aop:before>
	        <!--配置后置通知:提交事务-->
	        <aop:after-returning method="commit" pointcut-ref="pt1"></aop:after-returning>
	        <!--配置异常通知:回滚事务-->
	        <aop:after-throwing method="rollback" pointcut-ref="pt1"></aop:after-throwing>
	        <!--配置最终通知:释放连接-->
	        <aop:after method="release" pointcut-ref="pt1"></aop:after>
	    </aop:aspect>
	</aop:config>

3、基于注解的AOP实现事务控制
重点:1、如何创建事务管理工具类。2、注释的作用(@Aspect、Pointcut、@Around等)
XML代码

<!--配置spring创建容器时要扫描的包-->
<context:component-scan base-package="com.itheima"></context:component-scan>

<!--开启Spring对注解AOP的支持-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

Java代码

 	/**
     * 和事务管理相关的工具类,它包含了,开启事务,提交事务,回滚事务和释放连接
     */
    @Component("txManager")
    @Aspect
    public class TransactionManager {

        @Autowired
        private ConnectionUtils connectionUtils;
        // 切入点:指定需要注入事务的方法
        @Pointcut("execution(* com.itheima.service.impl.*.*(..))")
        public void pt1(){}
         /**
         * 环绕通知
         */
        @Around("pt1()")
        public Object aroundAdvice(ProceedingJoinPoint pjp){
            Object rtValue = null;
            try {
                Object[] args = pjp.getArgs(); // 获取参数
                this.beginTransaction();// 开启事务
                rtValue = pjp.proceed(args); // 执行方法
                this.commit();
                return rtValue; // 提交事务
            }catch (Throwable throwable){
                this.rollback();
                throw new RuntimeException(throwable);
            }finally {
                this.release();
            }
        }
    }

4、spring中基于XML的声明式事务控制配置
好处:XML配置一次就再也没有事务配置的问题。

	<!--
    	配置步骤:
	        1.配置事务管理器
	        2.配置事务的通知
	            此时我们需要导入事务的约束 tx名称空间和约束,同时也需要aop的
	            使用tx:advice标签配置事务通知
	                属性:
	                    id:给事务通知起一个唯一标志
	                    transaction-manager: 给事务通知提供一个事务管理引用
	        3.配置AOP中的通用切入点表达式
	        4.建立事务通知和切入点表达式的对应关系
	        5.配置事务的属性
	            在事务的通知tx:advice标签内部配置
	-->     
<!--1.配置事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"></property>
</bean>

<!--2.配置事务的通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <!--
        5.配置事务的属性
            isolation:用于指定事务的隔离级别。默认值DEFAULT,表示使用数据库的默认隔离级别
            propagation:用于指定事务的传播行为。默认值是REQUIRED,表示一定会有事务,增删改的选择。查询方法可以选择SUPPORTS。
            read-only:用于指定事务是否只读。只有查询方法才能设置为true,默认值为false,表示读写
            timeout:用于指定事务的超时时间。默认值为-1,表示永不超时。如果指定了数值,以秒为单位。
            rollback-for:用于指定一个异常,当产生该异常时,事务回滚,产生其他异常时,事务不回滚。没有默认值。表示任何异常都回滚
            no-rollback-for:用于指定一个异常,当产生该异常时,事务不回滚,产生其他异常时事务回滚。没有默认值。表示任何异常都回滚
    -->
    <tx:attributes>
        <tx:method name="transfer" propagation="REQUIRED" read-only="false"/>
        <tx:method name="find*" propagation="SUPPORTS" read-only="true"></tx:method>
    </tx:attributes>
</tx:advice>

<!--3.配置AOP-->
<aop:config>
    <!--配置切入点表达式-->
    <aop:pointcut id="pt1" expression="execution(* com.itheima.service.impl.*.*(..))"/>
    <!--4.建立切入点表达式和事务通知的对应关系-->
    <aop:advisor advice-ref="txAdvice" pointcut-ref="pt1"></aop:advisor>
</aop:config>

5、spring中基于注解的声明式事务控制配置
注意:重点是Transactional事务配置的方式不同了,当每次增加新方法时,都需要配置一次事务。
XML代码

	<!--spring中基于注解的声明式事务控制配置步骤
	    1.配置事务管理器
	    2.开启spring对注解事务的支持
	    3.在需要事务支持的地方使用@Transactional注解
	-->
	<!--1.配置事务管理器-->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	    <property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<!--开启spring对注解事务的支持-->
	<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>

Java代码

    @Transactional(propagation = Propagation.SUPPORTS,readOnly = true) // 只读型事务的配置
    public class AccountServiceImpl implements IAccountService{
    
    // 需要的是读写型事务配置
    @Transactional(propagation = Propagation.REQUIRED,readOnly = false)
    public void transfer(String sourceName, String targetName, Float money) {
        System.out.println("transfer....");
        //2.1根据名称查询转出账户
        Account source = accountDao.findAccountByName(sourceName);
        //2.2根据名称查询转入账户
        Account target = accountDao.findAccountByName(targetName);
        //2.3转出账户减钱
        source.setMoney(source.getMoney()-money);
        //2.4转入账户加钱
        target.setMoney(target.getMoney()+money);
        //2.5更新转出账户
        accountDao.updateAccount(source);
//            int i=1/0;
        //2.6更新转入账户
        accountDao.updateAccount(target);
    }

6、spring中基于纯注解的声明式事务控制配置
纯注解注意的点:

    1. 将xml中的固定配置分类,再在config包内创建类,将xml中的固定配置使用注解的方式在类中配置。
    2. 业务层代码不变,通过注解的方式给类和方法添加事务
        例如:@Transactional(propagation = Propagation.SUPPORTS,readOnly = true) // 只读型事务的配置
            @Transactional(propagation = Propagation.REQUIRED,readOnly = false)  // 需要的是读写型事务配置

示例
Spring的主配置类,相当于bean.xml

    @Configuration
    @ComponentScan("com.itheima")
    @Import({JdbcConfig.class,TransactionConfig.class})
    @PropertySource("jdbcConfig.properties")
    @EnableTransactionManagement
    public class SpringConfiguration {
    }

和事务相关的配置类

    public class TransactionConfig {
        @Bean(name = "transactionManager") // 把当前方法的返回值当做对象注入到Spring容器中,并且设置name
        public PlatformTransactionManager createTransactionManager(DataSource dataSource){
            return new DataSourceTransactionManager(dataSource);
        }
    }

和连接数据库相关的配置类

	public class JdbcConfig {
	    @Value("${jdbc.Driver}")
	    private String driver;
	    @Value("${jdbc.url}")
	    private String url;
	    @Value("${jdbc.username}")
	    private String username;
	    @Value("${jdbc.password}")
	    private String password;
	    /**
	     * 创建JdbcTemplate对象
	     * @param dataSource
	     * @return
	     */
	    @Bean(name = "jdbcTemplate")
	    public JdbcTemplate createJdbcTemplate(DataSource dataSource){
	        return new JdbcTemplate(dataSource);
	    }
	
	    @Bean(name = "dataSource")
	    public DataSource createDataSource(){
	        DriverManagerDataSource ds = new DriverManagerDataSource();
	        ds.setDriverClassName(driver);
	        ds.setUrl(url);
	        ds.setUsername(username);
	        ds.setPassword(password);
	        return ds;
	    }
	}

小技巧:自学方法的诀窍(如何定位自己需要的重载方法)
1.我们有什么:sql语句,语句的参数
2.我们要什么: 返回一个List集合

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值