spring第四天

    一、Spirng中的JdbcTemplate

        1.1JbdcTemplate概述

            他是spring框架中提供的一个对象,是对原始JdbcAPI对象的简单封装。spring框架为我们提供了很多的操作模板类,如下:

ORM持久化技术            模板类

                JDBC                    org.springframework.jdbc.core.JdbcTemplate

                Hibernate3.0             org.springframework.orm.hibernate3.HibernateTemplate

                IBatis(MyBatis)         org.springframework.orm.ibaits.SqlMapClientTemplate

                JPA                        org.springframework.orm.jap.JpaTemplate

今天在spring-jdbc-x.xx.RELEASE.jar中,我们在导包的时候,除了要导入这个jar包外,还要导入spring-tx-x.x.x.RELEASE.jar(它是和事务相关的)。

1.2JdbcTemplate对象的创建

            对象源码:

                public JdbcTemplate() {

                }

public JdbcTemplate(DataSource dataSource) {

                    setDataSource(dataSource);

                    afterPropertiesSet();

                }

public JdbcTemplate(DataSource dataSource, boolean lazyInit) {

                    setDataSource(dataSource);

                    setLazyInit(lazyInit);

                    afterPropertiesSet();

                }

除了默认构造函数之外,都需要提供一个数据源。既然有set方法,依据我们之前学过的依赖注入,我们 可以在配置文件中配置

1.3spring中配置数据源

            1.3.1环境搭建

            1.3.2编写spring的配置文件

                <?xml version="1.0" encoding="UTF-8"?>

                <beans xmlns="http://www.springframework.org/schema/beans"

                    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

                    xsi:schemaLocation="http://www.springframework.org/schema/beans http://wwww.springframework.org/schema/beans/spring-beans.xsd">

</beans>

1.3.3配置数据源

                我们之前已经解除过两个数据源,一个C3P0,一个DBCP。要想使用这两个数据源都需要导入对应的jar包。

导入c3p0-x.x.x.x.jar到工程的lib目录。在spring的配置文件中配置:

                    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">

                        <property name="driverClassName" value="jdbc:mysql://localhost:8080/sql_test"></property>

                        <property name="url" value="jdbc:mysql://sql_test"></property>

                        <property name="username" value="root"></property>

                        <property name="password" value="123456"></property>

                    </bean>

1.3.4将数据库连接的信息配置到属性文件中:

                【定义属性文件】

                    jdbc.driverClass=com.mysql.jdbc.Driver

                    jdbc.url=jdbc:mysql://localhost:8080/sql_test

                    jdbc.username=root

                    jdbc.password=123456

【引入外部的属性文件】

                    一种方式:

                        <!-- 引入外部属性文件: -->

                        <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfiguurer">

                            <property name="location" value="classpath:jdbc.properties"/>

                        </bean>

第二种方式:

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

1.4JdbcTemplate的增删改查操作

            1.4.1前期准备

                创建数据库:

                    create database sql_test;

                    use sql_test;

                    创建表:

                    create table account(

                        id int primary key auto_increment,

                        name varchar(40),

                        money float

                    )character set utf8 collate utf8_general_ci;

1.4.2在spring配置文件中配置JdbcTemplate

                <?xml version="1.0" encoding="UTF-8"?>

                <beans xmlns="http://www.springframework.org/schema/beans"

                        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

                        xsi:schemaLocation="http://www.springframework.org/schema/beans 

                        http://www.springframework.org/schema/beans/spring-beans.xsd">

<!-- 配置一个数据库的操作模板:JdbcTemplate -->

                    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">

                        <property name="dataSource" ref="dataSource"></property>

                    </bean>

                    

                    <!-- 配置数据源 -->

                    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">

                    <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>

                    <property name="url" value="jdbc:mysql:///spring_day04"></property>

                    <property name="username" value="root"></property>

                    <property name="password" value="1234"></property>

                </bean>

                </beans>

1.4.3最基本的使用

                public class JdbcTemplateDemo1{

                    public static void main(String[] args){

                        //1.获取Spring容器

                        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");

//2.根据id获取bean对象

                        JdbcTemplate it = (JdbcTemplate) ac.getBean("jdbcTemplate");

//3.执行操作

                        jt.execute("insert into account(name, money)values('eee', 500)");

                    }

                }

1.4.4保存操作

                public class JdbcTemplateDemo2{

                    public static void main(String[] args){

                        //1.获取Spring容器

                        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");

//2.根据id获取bean对象

                        JdbcTemplate it = (JdbcTemplate) ac.getBean("jdbcTemplate");

//3.执行操作

                        jt.execute("insert into account(name, money)values('fff', 1000)");

                    }

                }

1.4.5更新操作

                public class JdbcTemplateDemo3{

                    public static void main(String[] args){

                        //1.获取Spring容器

                        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");

//2.根据id获取bean对象

                        JdbcTemplate it = (JdbcTemplate) ac.getBean("jdbcTemplate");

//3.执行操作

                        jt.execute("update account set money = money - ? where id = ?", 100, 6);

                    }

                }

1.4.6删除操作

                public class JdbcTemplateDemo4{

                    public static void main(String[] args){

                        //1.获取Spring容器

                        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");

//2.根据id获取bean对象

                        JdbcTemplate it = (JdbcTemplate) ac.getBean("jdbcTemplate");

//3.执行操作

                        jt.execute("delete from account where id = ?", 6);

                    }

                }

1.4.7查询所有操作

                public class JdbcTemplateDemo3 {

                    public static void main(String[] args) {

//1.获取Spring容器

                        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");

                        //2.根据id获取bean对象

                        JdbcTemplate jt = (JdbcTemplate) ac.getBean("jdbcTemplate");

                        //3.执行操作

                        //查询所有

                        List<Account> accounts = jt.query("select * from account where money > ? ", 

                                                            new AccountRowMapper(), 500);

                        for(Account o : accounts){

                            System.out.println(o);

                        }

                    }

                }

public class AccountRowMapper implements RowMapper<Account>{

                    @Override

                    public Account mapRow(ResultSet rs, int rowNum) throws SQLException {

                        Account account = new Account();

                        account.setId(rs.getInt("id"));

                        account.setName(rs.getString("name"));

                        account.setMoney(rs.getFloat("money"));

                        return account;

                    }

                    

                }

1.4.8查询一个操作

                使用RowMapper的方式:常用的方式

                public class JdbcTemplateDemo3 {

                    public static void main(String[] args) {

//1.获取Spring容器

                        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");

                        //2.根据id获取bean对象

                        JdbcTemplate jt = (JdbcTemplate) ac.getBean("jdbcTemplate");

                        //3.执行操作

                        //查询一个

                        List<Account> as = jt.query("select * from account where id = ? ", 

                                                        new AccountRowMapper(), 55);

                        System.out.println(as.isEmpty()?"没有结果":as.get(0));

                    }

                }

使用ResultSetExtractor的方式:不常用的方式

                public class JdbcTemplateDemo3 {

                    public static void main(String[] args) {

//1.获取Spring容器

                        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");

                        //2.根据id获取bean对象

                        JdbcTemplate jt = (JdbcTemplate) ac.getBean("jdbcTemplate");

                        //3.执行操作

                        //查询一个

                        Account account = jt.query("select * from account where id = ?",

                                                    new AccountResultSetExtractor(),3);

                        System.out.println(account);

                    }

                }

1.4.8查询返回一行一列操作

                public class JdbcTemplateDemo3 {

                    public static void main(String[] args) {

//1.获取Spring容器

                        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");

                        //2.根据id获取bean对象

                        JdbcTemplate jt = (JdbcTemplate) ac.getBean("jdbcTemplate");

                        //3.执行操作

                        //查询返回一行一列:使用聚合函数,在不使用group by字句时,都是返回一行一列。最长用的就是分页中获取总记录条数

                        Integer total = jt.queryForObject("select count(*) from account where money > ? ",Integer.class,500);

                        System.out.println(total);

                    }

                }

1.5在dao中使用JdbcTemplate

            1.5.1准备实体类

                /**

                 * 账户的实体

                 */

                public class Account implements Serializable {

private Integer id;

                    private String name;

                    private Float money;

                    public Integer getId() {

                        return id;

                    }

                    public void setId(Integer id) {

                        this.id = id;

                    }

                    public String getName() {

                        return name;

                    }

                    public void setName(String name) {

                        this.name = name;

                    }

                    public Float getMoney() {

                        return money;

                    }

                    public void setMoney(Float money) {

                        this.money = money;

                    }

                    @Override

                    public String toString() {

                        return "Account [id=" + id + ", name=" + name + ", money=" + money + "]";

                    }

                }

1.5.2第一种方式:在dao中定义JdbcTemplate

                /**

                 * 账户的接口

                 */

                public interface IAccountDao {

                    

                    /**

                     * 根据id查询账户信息

                     * @param id

                     * @return

                     */

                    Account findAccountById(Integer id);

/**

                     * 根据名称查询账户信息

                     * @return

                     */

                    Account findAccountByName(String name);

                    

                    /**

                     * 更新账户信息

                     * @param account

                     */

                    void updateAccount(Account account);

                }

/**

                 * 账户的持久层实现类

                 * 此版本的dao,需要给dao注入JdbcTemplate

                 */

                public class AccountDaoImpl implements IAccountDao {

private JdbcTemplate jdbcTemplate;

                    

                    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {

                        this.jdbcTemplate = jdbcTemplate;

                    }

@Override

                    public Account findAccountById(Integer id) {

                        List<Account> list =  jdbcTemplate.query("select * from account where id = ? ",new AccountRowMapper(),id);

                        return list.isEmpty()?null:list.get(0);

                    }

@Override

                    public Account findAccountByName(String name) {

                        List<Account> list =  jdbcTemplate.query("select * from account where name = ? ",new AccountRowMapper(),name);

                        if(list.isEmpty()){

                            return null;

                        }

                        if(list.size()>1){

                            throw new RuntimeException("结果集不唯一,不是只有一个账户对象");

                        }

                        return list.get(0);

                    }

@Override

                    public void updateAccount(Account account) {

                        jdbcTemplate.update("update account set money = ? where id = ? ",account.getMoney(),account.getId());

                    }

}

配置文件

                <?xml version="1.0" encoding="UTF-8"?>

                <beans xmlns="http://www.springframework.org/schema/beans"

                        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

                        xsi:schemaLocation="http://www.springframework.org/schema/beans 

                        http://www.springframework.org/schema/beans/spring-beans.xsd">

                    

                    <!-- 配置一个dao -->

                    <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl">

                        <!-- 注入jdbcTemplate -->

                        <property name="jdbcTemplate" ref="jdbcTemplate"></property>

                    </bean>

                    

                    <!-- 配置一个数据库的操作模板:JdbcTemplate -->

                    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">

                        <property name="dataSource" ref="dataSource"></property>

                    </bean>

                    

                    <!-- 配置数据源 -->

                    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">

                        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>

                        <property name="url" value="jdbc:mysql:///spring_day04"></property>

                        <property name="username" value="root"></property>

                        <property name="password" value="1234"></property>

                    </bean>

                </beans>

                思考:

                    此种方式有什么问题吗?

                答案:

                    有个小问题。就是我们的dao有很多时,每个dao都有一些重复性的代码。下面就是重复代码:

                    private JdbcTemplate jdbcTemplate;

                    

                    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {

                        this.jdbcTemplate = jdbcTemplate;

                    }

                    能不能把它抽取出来呢?

                    请看下一小节。

1.5.3第二种方式:让dao继承JdbcDaoSupport

                JdbcDaoSupport是spring框架为我们提供的一个类,该类中定义了一个JdbcTemplate对象,我们可以直接获取使用,但是要想创建该对象,需要为其提供一个数据源:具体源码如下:

                    public abstract class JbdcDaoSupport extends DaoSupport{

                        //定义对象

                        private JdbcTemplate jdbcTemplate;

//set方法注入数据源,判断是否注入了,注入了就创建JdbcTmplate

                        public final void setDateSource(DataSource dataSource){

                            if(this.jdbcTemplate == null || dataSource != this.jdbcTemplate.getDataSource()){

                                //如果提供了数据源就创建JdbcTemplate

                                this.jdbcTmpelate = createJdbcTemplate();

                                initTemplateConfig();

                            }

                        }

//使用数据源创建JdbcTemplate

                        protected JdbcTemplate createJbdcTemplate(DataSource dateSource){

                            return new JdbcTemplate(dataSource);

                        }

//当然,也可以通过注入JdbcTemplate对象

                        public final void setJdbcTemplate(JdbcTemplate jdbcTemplate){

                            this.jdbcTemplate = jdbcTemplate;

                            initTemplateConfig();

                        }

//使用getJdbcTemplate方法获取操作模板对象

                        public final JdbcTemplate getJdbcTemplate(){

                            return this.jdbcTemplate;

                        }

                    }

/**

                    *    账户的接口

                    */

                    public interface IAccountDao {

    

                        /**

                         * 根据id查询账户信息

                         * @param id

                         * @return

                         */

                        Account findAccountById(Integer id);

/**

                         * 根据名称查询账户信息

                         * @return

                         */

                        Account findAccountByName(String name);

                        

                        /**

                         * 更新账户信息

                         * @param account

                         */

                        void updateAccount(Account account);

                    }

/**

                     * 账户的持久层实现类

                     * 此版本dao,只需要给它的父类注入一个数据源

                     */

public class AccountDaoImpl2 extends JdbcDaoSupport implements IAccountDao {

@Override

                        public Account findAccountById(Integer id) {

                            //getJdbcTemplate()方法是从父类上继承下来的。

                            List<Account> list = getJdbcTemplate().query("select * from account where id = ? ",new AccountRowMapper(),id);

                            return list.isEmpty()?null:list.get(0);

                        }

@Override

                        public Account findAccountByName(String name) {

                            //getJdbcTemplate()方法是从父类上继承下来的。

                            List<Account> list =  getJdbcTemplate().query("select * from account where name = ? ",new AccountRowMapper(),name);

                            if(list.isEmpty()){

                                return null;

                            }

                            if(list.size()>1){

                                throw new RuntimeException("结果集不唯一,不是只有一个账户对象");

                            }

                            return list.get(0);

                        }

@Override

                        public void updateAccount(Account account) {

                            //getJdbcTemplate()方法是从父类上继承下来的。

                            getJdbcTemplate().update("update account set money = ? where id = ? ",account.getMoney(),account.getId());

                        }

                    }

配置文件:

                    <?xml version="1.0" encoding="UTF-8"?>

                    <beans xmlns="http://www.springframework.org/schema/beans"

                            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

                            xsi:schemaLocation="http://www.springframework.org/schema/beans 

                            http://www.springframework.org/schema/beans/spring-beans.xsd">

                        

                    <!-- 配置dao2 -->

                    <bean id="accountDao2" class="com.itheima.dao.impl.AccountDaoImpl2">

                        <!-- 注入dataSource -->

                        <property name="dataSource" ref="dataSource"></property>

                    </bean>

                    <!-- 配置数据源 -->

                    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">

                        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>

                        <property name="url" value="jdbc:mysql:///spring_day04"></property>

                            <property name="username" value="root"></property>

                            <property name="password" value="1234"></property>

                        </bean>

                    </beans>

两种的Dao设计的区别:

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

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

二、Spring事务控制

        2.1Spring事务控制我们要明确的

            第一:JavaEE体系进行分层开发,事务处理位于业务层,Spring提供了分层设计业务层的事务处理解决方案。

            第二:spring框架为我们提供了一组事务控制的接口。具体在后面的第二小节介绍。这组接口是在spring-tx-x.x.x.RELEASE.jar中。

            第三:spring的事务控制都是局域AOP的,它既可以使用编程的方式实现,也可以使用配置的方法实现。我们学习的重点是使用配置的方式实现的。

2.2Spring中事务控制的API介绍

            2.2.1PlatformTransactionManager

                此接口是spring的事务管理器,它里面提供了我们常用的操作事务的方法,如下:

                    PlatformTransactionMeanager接口提供事务操作的方法,包含有3个具体的操作

                        1.获取事务状态信息

                            TransactionStatus getTransaction(TransactionDefinition definition)

2.提交事务

                            void commit(TransactionStatus status)

3.回滚事务

                            void rollback(TransactionStatus status)

我们在开发中都是使用它的实现类,如下:

                    DataSourceTransactionManager

                        使用SpringJDBC或iBatis间持久化数据时使用

HibernateTransactionManager

                        使用Hibernate3.0版本进行持久化数据时使用

JpaTransactionManager

                        使用JPA进行持久化时使用

JtaTransactionManager

                        使用JTA实现管理事务,在一个事务跨越多个资源时必须使用

真正管理事务的对象

                    org.spirngframework.jdbc.datasource.DataSourceTransactionManager 使用Spring JDBC或iBatis进行持久化数据时使用

org.springframework.orm.hibernate3.HibernateTransactionManager 使用Hibernate版本进行持久化数据时使用

2.2.2TransactionDefinition

                它是事务的定义信息对象,里面有如下方法:

                    获取事务对象名称

                        String getName()

获取事务隔离级

                        int getIsolationLevel()

获取事务传播行为

                        int getPropagetionBehavior()

获取事务超时时间

                        int getTimeout()

获取事务是否只读

                        boolean idReadOnly()

2.2.2.1事务的隔离级别

                    事务隔离级反应事务提交并发访问时的处理态度

                        ISOATION_DEFAULT

                            默认级别,归属下列某一种

ISOLATION_READ_UNCOMMITTED

                            可以读取未提交数据

ISOLATION_READ_COMMITTED

                            只能读取已经提交数,解决脏读问题(Oracle默认级别)

ISOLATION_REPETABLE_READ

                            是否读取其他事物提交修改后的数据,解决不可重复读问题(M有SQL默认级别)

ISOLATION_SERIALIZABLE

                            S是否读取其他事物提交添加后的数据,解决幻读问题

2.2.2.2事务的传播行为

                    REQUIRED:如歌当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。一般的选择(默认值)。

                    SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行(没有事务)。

                    MANDATORY:使用当前的事务,如果当前没有事务,就抛出异常。

                    REQUERS NEW:新建事务,如果当前在事务中,把当前事务挂起。

                    NOT SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

                    NEVER:以非事务方式运行,如果当前存在事务,抛出异常。

                    NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行REQUIRED类似的操作。

2.2.2.3超时时间

                    默认值是-1,没有超时限制。如果有,以秒为单位进行设置。

2.2.2.4是否是只读事务

                    建议查询时设置为只读。

2.2.3TransactionStatus

                此接口提供的是事务具体的运行状态,方法介绍如下:

                    TransactionStatus接口描述了某个时间点上事务对象的状态信息,包含有6个具体的操作

                        1.刷新事务:

                            void flush()

2.获取是否存在存储点

                            boolean hasSavepoint()

3.获取事务是否完成

                            boolean isCompleted()

4.获取事务是否为新的事务

                            boolean isNewTransaction()

5.获取事务是否回滚

                            boolean isRollbackOnly()

设置事务回滚

                                void setRollbackOnly()

2.3基于XML的声明式事物控制(配置方式)重点

            2.3.1环境搭建

                2.3.1.1第一步:拷贝必要的jar包到工厂的lib目录

2.3.1.2第二步:创建spring的配置文件并导入约束

                    <?xml version="1.0" encoding="UTF-8"?>

                    <beans xmlns="http://www.springframework.org/schema/beans"

                            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

                            xmlns:aop="http://www.springframework.org/schema/aop"

                         xmlns:tx="http://www.springframework.org/schema/tx"

                            xsi:schemaLocation="http://www.springframework.org/schema/beans 

                                    http://www.springframework.org/schema/beans/spring-beans.xsd

                                    http://www.springframework.org/schema/tx 

                                    http://www.springframework.org/schema/tx/spring-tx.xsd

                                    http://www.springframework.org/schema/aop 

                                    http://www.springframework.org/schema/aop/spring-aop.xsd">    

                    </beans>

2.3.1.3第三步:准备数据库表和实体类

                    创建数据库:

                        创建数据库:

                        create database spring_day04;

                        use spring_day04;

                        创建表:

                        create table account(

                            id int primary key auto_increment,

                            name varchar(40),

                            money float

                        )character set utf8 collate utf8_general_ci;

                        /**

                         * 账户的实体

                         */

                        public class Account implements Serializable {

private Integer id;

                            private String name;

                            private Float money;

                            public Integer getId() {

                                return id;

                            }

                            public void setId(Integer id) {

                                this.id = id;

                            }

                            public String getName() {

                                return name;

                            }

                            public void setName(String name) {

                                this.name = name;

                            }

                            public Float getMoney() {

                                return money;

                            }

                            public void setMoney(Float money) {

                                this.money = money;

                            }

                            @Override

                            public String toString() {

                                return "Account [id=" + id + ", name=" + name + ", money=" + money + "]";

                            }

                        }

2.3.1.4第四步:编写业务层接口和实现类

                    /**

                     * 账户的业务层接口

                     */

                    public interface IAccountService {

                        

                        /**

                         * 根据id查询账户信息

                         * @param id

                         * @return

                         */

                        Account findAccountById(Integer id);//查

                        

                        /**

                         * 转账

                         * @param sourceName    转出账户名称

                         * @param targeName        转入账户名称

                         * @param money            转账金额

                         */

                        void transfer(String sourceName,String targeName,Float money);//增删改

                    }

/**

                     * 账户的业务层实现类

                     */

                    public class AccountServiceImpl implements IAccountService {

                        

                        private IAccountDao accountDao;

                        

                        public void setAccountDao(IAccountDao accountDao) {

                            this.accountDao = accountDao;

                        }

@Override

                        public Account findAccountById(Integer id) {

                            return accountDao.findAccountById(id);

                        }

@Override

                        public void transfer(String sourceName, String targeName, Float money) {

                            //1.根据名称查询两个账户

                            Account source = accountDao.findAccountByName(sourceName);

                            Account target = accountDao.findAccountByName(targeName);

                            //2.修改两个账户的金额

                            source.setMoney(source.getMoney()-money);//转出账户减钱

                            target.setMoney(target.getMoney()+money);//转入账户加钱

                            //3.更新两个账户

                            accountDao.updateAccount(source);

                            int i=1/0;

                            accountDao.updateAccount(target);

                        }

                    }

2.3.1.5第五步:编写Dao接口和实现类

                    /**

                     * 账户的持久层接口

                     */

                    public interface IAccountDao {

                        

                        /**

                         * 根据id查询账户信息

                         * @param id

                         * @return

                         */

                        Account findAccountById(Integer id);

/**

                         * 根据名称查询账户信息

                         * @return

                         */

                        Account findAccountByName(String name);

                        

                        /**

                         * 更新账户信息

                         * @param account

                         */

                        void updateAccount(Account account);

                    }

                    /**

                     * 账户的持久层实现类

                     * 此版本dao,只需要给它的父类注入一个数据源

                     */

                    public class AccountDaoImpl extends JdbcDaoSupport implements IAccountDao {

@Override

                        public Account findAccountById(Integer id) {

                            List<Account> list = getJdbcTemplate().query("select * from account where id = ? ",new AccountRowMapper(),id);

                            return list.isEmpty()?null:list.get(0);

                        }

@Override

                        public Account findAccountByName(String name) {

                            List<Account> list =  getJdbcTemplate().query("select * from account where name = ? ",new AccountRowMapper(),name);

                            if(list.isEmpty()){

                                return null;

                            }

                            if(list.size()>1){

                                throw new RuntimeException("结果集不唯一,不是只有一个账户对象");

                            }

                            return list.get(0);

                        }

@Override

                        public void updateAccount(Account account) {

                            getJdbcTemplate().update("update account set money = ? where id = ? ",account.getMoney(),account.getId());

                        }

                    }

/**

                     * 账户的封装类RowMapper的实现类

                     */

                    public class AccountRowMapper implements RowMapper<Account>{

@Override

                        public Account mapRow(ResultSet rs, int rowNum) throws SQLException {

                            Account account = new Account();

                            account.setId(rs.getInt("id"));

                            account.setName(rs.getString("name"));

                            account.setMoney(rs.getFloat("money"));

                            return account;

                        }

                    }

2.3.1.6第六步:在配置文件中配置业务层和持久层

                    <!-- 配置service -->

                    <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">

                        <property name="accountDao" ref="accountDao"></property>

                    </bean>

                        

                    <!-- 配置dao -->

                    <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl">

                        <!-- 注入dataSource -->

                        <property name="dataSource" ref="dataSource"></property>

                    </bean>

                        

                    <!-- 配置数据源 -->

                    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">

                        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>

                        <property name="url" value="jdbc:mysql:///spring_day04"></property>

                        <property name="username" value="root"></property>

                        <property name="password" value="1234"></property>

                    </bean>

2.3.2配置步骤

                2.3.2.1第一步:配置事务管理器

                    <!-- 配置一个事务管理器 -->

                    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

                        <!-- 注入DataSource -->

                        <property name="dataSource" ref="dataSource"></property>

                    </bean>

2.3.2.2第二步:配置事务和通知引用事务管理器

                    <!-- 事务的配置 -->

                    <tx:advice id="txAdvice" transaction-manager="transactionManager">

                    </tx:advice>

2.3.2.3第三步:配置事务的属性

                    <!--在tx:advice标签内部 配置事务的属性 -->

                    <tx:attributes>

                    <!-- 指定方法名称:是业务核心方法 

                        read-only:是否是只读事务。默认false,不只读。

                        isolation:指定事务的隔离级别。默认值是使用数据库的默认隔离级别。 

                        propagation:指定事务的传播行为。

                        timeout:指定超时时间。默认值为:-1。永不超时。

                        rollback-for:用于指定一个异常,当执行产生该异常时,事务回滚。产生其他异常,事务不回滚。没有默认值,任何异常都回滚。

                        no-rollback-for:用于指定一个异常,当产生该异常时,事务不回滚,产生其他异常时,事务回滚。没有默认值,任何异常都回滚。

                        -->

                        <tx:method name="*" read-only="false" propagation="REQUIRED"/>

                        <tx:method name="find*" read-only="true" propagation="SUPPORTS"/>

                    </tx:attributes>

2.3.2.4第四步:配置AOP-切入点表达式

                    <!-- 配置aop -->

                    <aop:config>

                        <!-- 配置切入点表达式 -->

                        <aop:pointcut expression="execution(* com.itheima.service.impl.*.*(..))" id="pt1"/>

                    </aop:config>

2.3.2.5第五步:配置切入点表达式和事务通知的对应关系

                    <!-- 在aop:config标签内部:建立事务的通知和切入点表达式的关系 -->

                    <aop:advisor advice-ref="txAdvice" pointcut-ref="pt1"/>

2.4基于xml和注解组合使用的整合方式

            2.4.1环境搭建

                2.4.1.1第一步:拷贝必备的jar包到工程的lib目录

2.4.1.2第二步:创建spring的配置文件导入约束并配置扫描的包

                    <?xml version="1.0" encoding="UTF-8"?>

                    <beans xmlns="http://www.springframework.org/schema/beans"

                                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

                                xmlns:aop="http://www.springframework.org/schema/aop"

                                xmlns:tx="http://www.springframework.org/schema/tx"

                                xmlns:context="http://www.springframework.org/schema/context"

                                xsi:schemaLocation="http://www.springframework.org/schema/beans 

                                    http://www.springframework.org/schema/beans/spring-beans.xsd

                                        http://www.springframework.org/schema/tx 

                                        http://www.springframework.org/schema/tx/spring-tx.xsd

                                        http://www.springframework.org/schema/aop 

                                        http://www.springframework.org/schema/aop/spring-aop.xsd

                                        http://www.springframework.org/schema/context

                                    http://www.springframework.org/schema/context/spring-context.xsd">

                        <!-- 配置spring要扫描的包 -->

                        <context:component-scan base-package="com.itheima"></context:component-scan>

                    </beans>

2.4.1.3第三步:创建数据库表和实体类

                    和基于xml的配置相同,略

2.4.1.4第四步:创建业务层接口和实现类并使用注解让spring管理

                    业务层接口和基于xml配置的时候相同。略

/**

                     * 账户的业务层实现类

                     */

                    @Service("accountService")

                    public class AccountServiceImpl implements IAccountService {

                        @Autowired

                        private IAccountDao accountDao;

@Override

                        public Account findAccountById(Integer id) {

                            return accountDao.findAccountById(id);

                        }

@Override

                        public void transfer(String sourceName, String targeName, Float money) {

                            //1.根据名称查询两个账户

                            Account source = accountDao.findAccountByName(sourceName);

                            Account target = accountDao.findAccountByName(targeName);

                            //2.修改两个账户的金额

                            source.setMoney(source.getMoney()-money);//转出账户减钱

                            target.setMoney(target.getMoney()+money);//转入账户加钱

                            //3.更新两个账户

                            accountDao.updateAccount(source);

                            int i=1/0;

                            accountDao.updateAccount(target);

                        }

                    }

2.4.1.5第五步:创建Dao接口和实现类并使用注解让spring管理

                    Dao层接口和AccountRowMapper与基于xml配置的时候相同,略

@Repository("accountDao")

                    public class AccountDaoImpl implements IAccountDao {

@Autowired

                        private JdbcTemplate jdbcTemplate;

                        

                        @Override

                        public Account findAccountById(Integer id) {

                            List<Account> list = jdbcTemplate.query("select * from account where id = ? ",new AccountRowMapper(),id);

                            return list.isEmpty()?null:list.get(0);

                        }

@Override

                        public Account findAccountByName(String name) {

                            List<Account> list =  jdbcTemplate.query("select * from account where name = ? ",new AccountRowMapper(),name);

                            if(list.isEmpty()){

                                return null;

                            }

                            if(list.size()>1){

                                throw new RuntimeException("结果集不唯一,不是只有一个账户对象");

                            }

                            return list.get(0);

                        }

@Override

                        public void updateAccount(Account account) {

                            jdbcTemplate.update("update account set money = ? where id = ? ",account.getMoney(),account.getId());

                        }

                    }

2.4.2配置步骤

                2.4.2.1第一步:配置数据源和JdbcTemplate

                    <!-- 配置数据源 -->

                    <bean id="dataSource" 

                                class="org.springframework.jdbc.datasource.DriverManagerDataSource">

                        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>

                        <property name="url" value="jdbc:mysql:///spring_day04"></property>

                        <property name="username" value="root"></property>

                        <property name="password" value="1234"></property>

                    </bean>

2.4.2.2第二步:配置事务管理器并注入数据源

                    <!-- 配置JdbcTemplate -->

                    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">

                        <property name="dataSource" ref="dataSource"></property>

                    </bean>

2.4.2.3第三步:在业务层使用@Transactional注解

                    @Service("accountService")

                    @Transactional(readOnly=true,propagation=Propagation.SUPPORTS)

                    public class AccountServiceImpl implements IAccountService {

                        

                        @Autowired

                        private IAccountDao accountDao;

@Override

                        public Account findAccountById(Integer id) {

                            return accountDao.findAccountById(id);

                        }

@Override

                        @Transactional(readOnly=false,propagation=Propagation.REQUIRED)

                        public void transfer(String sourceName, String targeName, Float money) {

                            //1.根据名称查询两个账户

                            Account source = accountDao.findAccountByName(sourceName);

                            Account target = accountDao.findAccountByName(targeName);

                            //2.修改两个账户的金额

                            source.setMoney(source.getMoney()-money);//转出账户减钱

                            target.setMoney(target.getMoney()+money);//转入账户加钱

                            //3.更新两个账户

                            accountDao.updateAccount(source);

                            //int i=1/0;

                            accountDao.updateAccount(target);

                        }

                    }

该注解的属性和xml中的属性含义一致。该注解可以出现在接口上,类上和方法上。

                    出现接口上,表示该接口的所有实现类都有事务支持。

                    出现类上,表示类中所有的方法有事务支持。

                    出现方法上,表示方法有事务支持。

                    以上三个位置的优先级:方法>类>接口

2.4.2.4第四步:在配置文件中开启spring对注解事务的支持

                    <!-- 开启spring注解事务的支持 -->

                    <tx:annotation-driven transaction-manager="transactionManager"/>

2.5基于纯注解的声明式事物控制(配置方式)重点

            2.5.1环境搭建

                2.5.1.1第一步:拷贝必备的jar包到工程的lib目录中

2.5.1.2第二步:创建一个类用于加载spring的配置并指定要扫描的包

                    /**

                     * 用于初始化spring容器的配置类

                     */

                    @Configuration

                    @ComponentScan(basePackages="com.itheima")

                    public class SpringConfiguration {

}

2.5.1.3第三步:创建数据库表和实体类

                    和基于xml的配置相同。略

2.5.1.4第四步:创建业务层接口和实现类并使用注解让spring管理

                    业务层接口和基于xml配置的时候相同。略

/**

                     * 账户的业务层实现类

                     */

                    @Service("accountService")

                    public class AccountServiceImpl implements IAccountService {

                        @Autowired

                        private IAccountDao accountDao;

@Override

                        public Account findAccountById(Integer id) {

                            return accountDao.findAccountById(id);

                        }

@Override

                        public void transfer(String sourceName, String targeName, Float money) {

                            //1.根据名称查询两个账户

                            Account source = accountDao.findAccountByName(sourceName);

                            Account target = accountDao.findAccountByName(targeName);

                            //2.修改两个账户的金额

                            source.setMoney(source.getMoney()-money);//转出账户减钱

                            target.setMoney(target.getMoney()+money);//转入账户加钱

                            //3.更新两个账户

                            accountDao.updateAccount(source);

                            int i=1/0;

                            accountDao.updateAccount(target);

                        }

                    }

2.5.1.5第五步:创建Dao接口和实现类并使用注解让spring管理

                    Dao层接口和AccountRowMapper与基于xml配置的时候相同。略

@Repository("accountDao")

                    public class AccountDaoImpl implements IAccountDao {

@Autowired

                        private JdbcTemplate jdbcTemplate;

                        

                        @Override

                        public Account findAccountById(Integer id) {

                            List<Account> list = jdbcTemplate.query("select * from account where id = ? ",new AccountRowMapper(),id);

                            return list.isEmpty()?null:list.get(0);

                        }

@Override

                        public Account findAccountByName(String name) {

                            List<Account> list =  jdbcTemplate.query("select * from account where name = ? ",new AccountRowMapper(),name);

                            if(list.isEmpty()){

                                return null;

                            }

                            if(list.size()>1){

                                throw new RuntimeException("结果集不唯一,不是只有一个账户对象");

                            }

                            return list.get(0);

                        }

@Override

                        public void updateAccount(Account account) {

                            jdbcTemplate.update("update account set money = ? where id = ? ",account.getMoney(),account.getId());

                        }

                    }

2.5.2配置步骤

                2.5.2.1第一步:使用@Bean注解配置数据源

                    @Bean(name = "dataSource")

                    public DataSource createDS() throws Exception {

                        DriverManagerDataSource dataSource = new DriverManagerDataSource();

                        dataSource.setUsername("root");

                        dataSource.setPassword("123");

                        dataSource.setDriverClassName("com.mysql.jdbc.Driver");

                        dataSource.setUrl("jdbc:mysql:///spring3_day04");

                        return dataSource;

                    }

2.5.2.2第二步:使用@Bean注解配置事务管理器

                    @Bean

                    public PlatformTransactionManager 

                            createTransactionManager(@Qualifier("dataSource") DataSource dataSource) {

                        return new DataSourceTransactionManager(dataSource);

                    }

2.5.2.3第三步:使用@Bean注解配置JdbcTemplate

                    @Bean

                    public JdbcTemplate createTemplate(@Qualifier("dataSource") DataSource dataSource) 

                    {

                        return new JdbcTemplate(dataSource);

                    }

2.5.2.4第四步:在需要控制事务的业务层实现类上使用@Transactional注解

                    @Service("accountService")

                    @Transactional(readOnly=true,propagation=Propagation.SUPPORTS)

                    public class AccountServiceImpl implements IAccountService {

                        

                        @Autowired

                        private IAccountDao accountDao;

@Override

                        public Account findAccountById(Integer id) {

                            return accountDao.findAccountById(id);

                        }

@Override

                        @Transactional(readOnly=false,propagation=Propagation.REQUIRED)

                        public void transfer(String sourceName, String targeName, Float money) {

                            //1.根据名称查询两个账户

                            Account source = accountDao.findAccountByName(sourceName);

                            Account target = accountDao.findAccountByName(targeName);

                            //2.修改两个账户的金额

                            source.setMoney(source.getMoney()-money);//转出账户减钱

                            target.setMoney(target.getMoney()+money);//转入账户加钱

                            //3.更新两个账户

                            accountDao.updateAccount(source);

                            //int i=1/0;

                            accountDao.updateAccount(target);

                        }

                    }

该注解的属性和xml中的属性含义一致。该注解可以出现在接口上,类上和方法上。

                    出现接口上,表示该接口的所有实现类都有事务支持。

                    出现在类上,表示类中所有方法有事务支持

                    出现在方法上,表示方法有事务支持。

                    以上三个位置的优先级:方法>类>接口。

2.5.2.5第五步:使用@EnableTransactionManagement开启spring对注解事务的支持

                    @Configuration

                    @EnableTransactionManagement

                    public class SpringTxConfiguration{

                        //这里配置数据源,配置JdbcTemplate,配置事务管理器。在之前的步骤已经写过了。

                    }

开放源代码的设计层面框架Spring——day04的更多相关文章

  1. 开放源代码的设计层面框架Spring——day01

    spring第一天     一.Spring概述         1.1spring概述             1.1.1spring介绍                 Spring是分层的Jav ...

  2. 开放源代码的设计层面框架Spring——day03

    spring第三天     一.AOP的相关概念         1.1AOP概述             1.1.1什么是AOP                 AOP:全称是Aspext Orie ...

  3. 开放源代码的设计层面框架Spring——day02

    spring第二天     一.基于注解的IOC配置         1.1写在最前             学习基于注解的IOC配置,大家脑海里首先得有一个认知,即注解配置和xml配置要实现的功能是 ...

  4. Hibernate(开放源代码的对象关系映射框架)

    Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架,hibernate可以自动生成SQL语句,自 ...

  5. JavaEE之Hibernate(开放源代码的对象关系映射框架)

    Hibernate(开放源代码的对象关系映射框架) 1.简介 Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全 ...

  6. [JSP]Maven+SSM框架(Spring+SpringMVC+MyBatis) - Hello World

    来源:http://blog.csdn.net/zhshulin/article/details/37956105?utm_source=tuicool&utm_medium=referral ...

  7. 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(一)开放源代码

    本文为 Dennis Gao 原创技术文章,发表于博客园博客,未经作者本人允许禁止任何形式的转载. 开源倾情奉献系列链接 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(一)开放源代码 开源倾 ...

  8. Spring day04笔记(SVN讲解和回顾昨天知识)

    spring day03回顾 事务管理 基于xml配置 1.配置事务管理器 jdbc:DataSourceTransactionManager hibernate:HibernateTransacti ...

  9. Maven+SSM框架(Spring+SpringMVC+MyBatis) - Hello World(转发)

    [JSP]Maven+SSM框架(Spring+SpringMVC+MyBatis) - Hello World 来源:http://blog.csdn.net/zhshulin/article/de ...

随机推荐

  1. Win 10 无法打开内核设备“\\.\Global\vmx86”问题

    Win 10操作系统, VMWareWorkstation10 无法打开内核设备"\\.\Global\vmx86": 系统找不到指定的文件.你想要在安装 VMware Works ...

  2. C# -- 使用FileInfo获取文件信息

    C# -- 使用FileInfo获取文件信息 1. 代码实现 static void Main(string[] args) { GetFileInfo(@"D:\Test.xlsx&quo ...

  3. java网络爬虫基础学习(一)

    刚开始接触java爬虫,在这里是搜索网上做一些理论知识的总结 主要参考文章:gitchat 的java 网络爬虫基础入门,好像要付费,也不贵,感觉内容对新手很友好. 一.爬虫介绍 网络爬虫是一个自动提 ...

  4. vuetify

    vue add vuetify打包之后再发过来另外剪头发 typescript 1.配置 2.当用 let 声明一个变量,它使用的是词法作用域或块作用域. let与var区别,所以要--- 3.看来 ...

  5. 前端/C# 前后台交互文件上传、下载

    试了很多方式,最终确认这个全面简单版的.废话不多说,贴码. 文件上传 input的type命名为file,即可实现文件上传.嗯~~~现在html还是很强大的.Good! 前端 单个文件上传 Html: ...

  6. 题解 P1944 最长括号匹配_NOI导刊2009提高(1)

    栈,模拟 把每个元素逐个入栈 如果和栈顶元素匹配,那么一块弹出去,同时标记这里是可匹配的. 取出连续的,最长的可匹配的序列即可. #include <iostream> #include ...

  7. springMVC静态资源

    静态资源放在哪 静态资源不要放在WEB-INF里面,放在和WEB-INF同级的目录里,一起放在webapp下,原生tomcat中,这里的资源可以直接访问. springmvc配置怎么写 <!-- ...

  8. 逆向工程核心原理-IA-32寄存器

    IA-32由四类寄存器组成:通用寄存器,段寄存器,程序状态与控制寄存器,指令指针寄存器. 通用寄存器:用于传送和暂存数据,也可参与算数逻辑运算,并保存运算结果. EAX(0-31) 32位      ...

  9. bzoj4892 [TJOI2017]DNA

    bzoj4892 [TJOI2017]DNA 给定一个匹配串和一个模式串,求模式串有多少个连续子串能够修改不超过 \(3\) 个字符变成匹配串 \(len\leq10^5\) hash 枚举子串左端点 ...

  10. 译注(2): How to Write a 21st Century Proof

    原文:Computer Scientist Tells Mathematicians How To Write Proofs 对比一下下面两个证明哪个更好? 版本一: "A square a ...