Spring知识复习之三

Spring整合JDBC

1 Spring提供了很多持久层技术模板类

ORM持久化技术 模板类

       JDBC                             org.springframework.jdbc.core.JdbcTemplate
       Hibernate3.0             org.springframework.orm.hibernate3.HibernateTemplate
       IBatis(MyBatis)          org.springframework.orm.ibatis.SqlMapClientTemplate
       JPA                              org.springframework.orm.jpa.JpaTemplate

2 Spring与Jdbc

(1)原生JDBC模板
<1>连接池的使用
                1.使用C3p0连接池(com.mchange.v2.c3p0.ComboPooledDataSource)
                代码示例如下:
                    ComboPooledDataSource dataSource=new ComboPooledDataSource();
                    dataSource.setDriverClass("com.mysql.jdbc.Driver");
                    dataSource.setJdbcUrl("jdbc:mysql:///hibernate_crm");
                    dataSource.setUser("root");
                    dataSource.setPassword("root");
                2.使用spring内置连接池(org.springframework.jdbc.datasource.DriverManagerDataSource)
                代码示例如下:
                    DriverManagerDataSource dataSource=new DriverManagerDataSource();
                    dataSource.setDriverClassName("com.mysql.jdbc.Driver");
                    dataSource.setUrl("jdbc:mysql:///hibernate_crm");
                    dataSource.setUsername("root");
                    dataSource.setPassword("root");
    <2>JDBC模板对象的调用
                    //1 创建JDBC模板对象
                    JdbcTemplate jt=new JdbcTemplate();
                    //2连接进连接池
                    jt.setDataSource(dataSource);
                    //3 书写sql语句,并执行
                    String sql="insert into t_user values(null,'rose')";
                    jt.update(sql);
(2)Spring对连接池进行管理
                <1>配置Spring内置的连接池DriverManagerDataSource
                        <bean name="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
                                <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
                                <property name="url" value="jdbc:mysql:///hibernate_crm"></property>
                                <property name="username" value="root"></property>
                                <property name="password" value="root"></property>
                        </bean>
                        <!--配置JDBCTemplate对象并关联Spring内置的连接池  -->
                        <bean name="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
                            <property name="dataSource" ref="dataSource"></property>
                        </bean>
                <2>配置C3P0连接池
                         导入jar包:    com.springsource.com.mchange.v2.c3p0-0.9.1.2.jar
                        <bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
                            <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
                            <property name="jdbcUrl" value="jdbc:mysql:///hibernate_crm"></property>
                            <property name="user" value="root"></property>
                            <property name="password" value="root"></property>
                        </bean>
                        <!--配置JDBCTemplate对象并关联C3p0连接池 -->
                        <bean name="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
                            <property name="dataSource" ref="dataSource"></property>
                        </bean>
                <3>配置db连接池
                        导入jar包: 
                                com.springsource.org.apache.commons.dbcp-1.2.2.osgi.jar
                                com.springsource.org.apache.commons.pool-1.5.3.jar
                                <!-- 配置 DBCP 连接池 -->
                                <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
                                <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
                                <property name="url" value="jdbc:mysql:///spring_day02"/>
                                <property name="username" value="root"/>
                                <property name="password" value="123"/>
                                </bean>
(3)JdbcTemplate对象的增删改查
            概述:JdbcTemplate的增删改都使用  update()方法。而查询则使用queryForObject()
            //增
            @Override
            public void save(User u) {
                String sql="insert into t_user values(null,?)";
                jt.update(sql,u.getName());
            }
            //删(根据id删除)
            @Override
            public void delete(Integer id) {
                String sql="delete from t_user where id=?";
                jt.update(sql,id);
            }
            //改
            @Override
            public void update(User u) {
                String sql="update t_user set name=? where id=?";
                jt.update(sql,u.getName(),u.getId());
            }
            //查(根据id进行查询,获取一个对象)
            @Override
            public User getById(Integer id) {
                String sql="select * from t_user where id=?";
                User user = jt.queryForObject(sql, new RowMapper<User>() {
                    @Override
                    public User mapRow(ResultSet rs, int arg1) throws SQLException {
                        //封装实体 User对象返回给这个方法
                        User u=new User();
                        u.setId(rs.getInt("id"));
                        u.setName(rs.getString("name"));
                        return u;
                    }},id);
                return user;
            }
            //查(查询表中总共有几条记录)
            @Override
            public int getTotalCount() {
                String sql="select count(*) from t_user";
                Integer count = jt.queryForObject(sql,Integer.class);
                return count;
            }
            //查(查询获取表中的所以记录对象,获取的是集合对象)
            @Override
            public List<User> getAll() {
                String sql="select * from t_user";
                List<User> userList = jt.query(sql, new RowMapper<User>(){
                    @Override
                    public User mapRow(ResultSet rs, int arg1) throws SQLException {
                        User user=new User();
                        user.setId(rs.getInt("id"));
                        user.setName(rs.getString("name"));
                        return user;
                    }});
                return userList;
            }
(4)将数据库信息配置到属性文件中
            <1>在src下创建一个配置文件,如 jdbc.properties
                     内容如下:
                        jdbc.driverClass=com.mysql.jdbc.Driver
                    jdbc.url=jdbc:mysql:///spring_crm
                    jdbc.username=root
                    jdbc.password=123
            <2>在applicationContext主配置文件中
                    方式一:
                    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
                    <property name="location" value="classpath:jdbc.properties"/>
                    </bean>
                    方式二:
                    <context:property-placeholder location="classpath:jdbc.properties"/>

Spring事务管理

1事务回顾

        <1>什么是事务:
                事务逻辑上的一组操作,组成这组操作的各个逻辑单元,要么一起成功,要么一起失败.
        <2>事务特性:
                原子性 :强调事务的不可分割.
                一致性 :事务的执行的前后数据的完整性保持一致.
                隔离性 :一个事务执行的过程中,不应该受到其他事务的干扰
                持久性 :事务一旦结束,数据就持久到数据库
        <3>如果不考虑隔离性引发安全性问题:
                脏读  :一个事务读到了另一个事务的未提交的数据
                不可重复读 :一个事务读到了另一个事务已经提交的 update 的数据导致多次查询结果不一致.
                虚幻读 :一个事务读到了另一个事务已经提交的 insert 的数据导致多次查询结果不一致.
        <4>解决读问题: 设置事务隔离级别
                未提交读  :脏读,不可重复读,虚读都有可能发生
                已提交读  :避免脏读。但是不可重复读和虚读有可能发生
                可重复读  :避免脏读和不可重复读.但是虚读有可能发生.
                串行化的  :避免以上所有读问题.
        <5>
                Mysql 默认:可重复读
                Oracle 默认:读已提交          

2 相关的API接口

(1) 平台事务管理器 PlatformTransactionManager
    <1> org.springframework.jdbc.datasource.DataSourceTransactionManager  
          SpringJDBC  或 iBatis 使用
    <2> org.springframework.orm.hibernate3.HibernateTransactionManager
          Hibernate 进行持久化数据时使用
(2)事务定义信息接口 TransactionDefinition 
     事务定义信息内容包括:
        * 隔离级别
        * 传播行为 
                    事务的传播的格式为:PROPAGION_XXX  
                    & 保证同一个事务中
                            PROPAGATION_REQUIRED 支持当前事务,如果不存在 就新建一个(默认)
                            PROPAGATION_SUPPORTS 支持当前事务,如果不存在,就不使用事务
                            PROPAGATION_MANDATORY  支持当前事务,如果不存在,抛出异常
                    & 保证不在同一个事务中
                            PROPAGATION_REQUIRES_NEW  如果有事务存在,挂起当前事务,创建一个新的事务
                            PROPAGATION_NOT_SUPPORTED  以非事务方式运行,如果有事务存在,挂起当前事务
                            PROPAGATION_NEVER 以非事务方式运行,如果有事务存在,抛出异常
                            PROPAGATION_NESTED 如果当前事务存在,则嵌套事务执行
        * 超时信息
        * 是否只读
(3) 事务状态接口 TransactionStatus,记录事务的状态

2 Spring事务管理过程简述

平台事务管理器(PlatformTransactionManager)  
根据  事务定义的信息(TransactionDefinition ) 
将事务管理过程中的状态记录到  TransactionStatus里面

3 Spring事务管理分类

(1)传统的事务管理方式:编程式事务方式(手动编写代码完成事务的管理)
     <1> Jdbc相关代码示例:
            (Connection) conn.setAutoCommit(false);  //设置手动管理事务
    <2>Hibernate相关代码示例:
            Session.beginTransaction();
    <3>特点分析:
        优点:细粒度的事务控制,可以对指定方法,或指定方法的某几行进行事务控制。
        缺点:虽灵活,但繁琐,每次要开启 ,提交,回滚,且要释放资源,否则耗内存。
(2)Spring提供对事务的管理,这就叫做声明式事务管理。
    <1>声明式事务管理特点:
            粗粒度的事务控制,只能给整个方法应用事务,不可以对方法的某几行应用事务。
            其核心是基于 AOP的。
    <2>Spring声明式事务管理器分类:
        Jdbc技术:DataSourceTransactionManager
        Hibernate技术:HibernateTransactionManager
    <3>xml声明式事务管理配置如下:
        《1》<!--配置spring的事务核心管理器,封装了所有事务操作,依赖于连接池 -->
        <bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager ">
            <property name="dataSource" ref="dataSource"></property>
        </bean>
        《2》<!--配置spring事务模板对象,用于service层代码API调用,依赖于spring的事务核心管理器  -->
        <bean name="transcationTemplate" class="org.springframework.transaction.support.TransactionTemplate">
            <property name="transactionManager" ref="transactionManager"></property>
        </bean>
        《3》将spring事务模板对象 依赖到service层中
        <bean name="accountService" class="cn.sss.service.AccountServiceImp">
            <property name="ad" ref="accountDao"></property>
            <property name="tt" ref="transcationTemplate"></property>
        </bean>
        《4》<!-- 配置事务通知 ,依赖spring事务核心管理器-->
        <tx:advice transaction-manager="transactionManager" id="txAdvice">
            <tx:attributes>
                <!--以方法为单位,指定方法应用什么事务属性  
                        name:要进行事务管理 的方法名
                        isolation:设置事务的隔离级别
                        propagation:事务的传播行为
                        read-only:只读
                  -->
                <tx:method name="transfer" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>
                <!--下面为企业中的事务管理 的方法配置(使用通配符 *)  -->
                <tx:method name="persist*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>
                <tx:method name="update*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>
                <tx:method name="modify*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>
                <tx:method name="delete*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>
                <tx:method name="remove*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>
                <tx:method name="get*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true"/>
                <tx:method name="find*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true"/>
                <tx:method name="transfer" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>
                <tx:method name="transfer" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>
                <tx:method name="transfer" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>
            </tx:attributes>
        </tx:advice>
        《5》<!--配置织入(把事务通知织入到目标对象中)  -->
                <aop:config>
                    <!--配置切点(需增强的方法)  -->
                    <aop:pointcut expression="execution(* cn.itheima.service.*ServiceImp.*(..))" id="txPc"/>
                    <!-- 配置切面(切点+通知)
                        advice-ref:通知名称
                        pointcut-ref:切点名称
                     -->
                    <aop:advisor advice-ref="txAdvice" pointcut-ref="txPc"/>
                </aop:config>

<4>注解 实现spring声明式事务管理
    * 主配置文件为:
        <!--配置spring的事务核心管理器,封装了所有事务操作,依赖于连接池 -->
        <bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager ">
            <property name="dataSource" ref="dataSource"></property>
        </bean>
        <!--配置spring事务模板对象,依赖于spring的事务核心管理器  -->
        <bean name="transcationTemplate" class="org.springframework.transaction.support.TransactionTemplate">
            <property name="transactionManager" ref="transactionManager"></property>
        </bean>
        <!--开启使用注解管理aop事务  -->
        <tx:annotation-driven/>
    * 业务service层:
        & 在类上方使用注解  注入aop事务管理的配置,作用于整个类中所有的方法
        @Transactional(isolation=Isolation.REPEATABLE_READ,propagation=Propagation.REQUIRED,readOnly=false)
        public class AccountServiceImp implements AccountService {}
        & 在方法名前使用注解配置aop事务(作用于此方法,权限大于在类上写入的注解)
        @Transactional(isolation=Isolation.REPEATABLE_READ,propagation=Propagation.REQUIRED,readOnly=false)
        public void transfer(Integer from, Integer to, Double money) {}

猜你喜欢

转载自blog.51cto.com/14008076/2316037
今日推荐