Spring 数据访问和事务知识点整理

来源:互联网 发布:fgo卡牌美型 知乎 编辑:程序博客网 时间:2024/06/07 17:09
3、使用Spring进行数据访问
    3.1、JdbcTemplate ?
        为了解决JDBC API在实际使用中的种种尴尬局面,Spring 框架提出了org.springframework.jdbc.core.JdbcTemplate作为数据访问的Helper类。JdbcTemplate是整个Spring数据访问抽象层提供的所有JDBC API 最佳实践的基础。其主要做两件事,一是封装所有基于JDBC的数据访问代码,以统一的格式和规范来使用JDBC API。二是对SQLException所提供的异常访问信息在框架内进行统一转译。
        JdbcTemplate中的各种模板方法按照其通过相应Callback接口所公开的API自由度的大小,可以简单划分为如下4组。面向Connection的模板方法、面向Statement的模板方法、面向PreparedStatement的模板方法和面向CallableStatement的模板方法。
        Spring还提供了NamedParameterJdbcTemplate的模板类为我们提供更加有语义的符号来作为SQL中的参数占位符。
    3.2、JdbcDaoSupport ?
        在使用JdbcTemplate进行编程的时候,我们会使用相应的DataSource提供数据库连接,使用JdbcTemplate进行数据库操作。但每个DAO都要这样做注入这两个依赖。为了方便Spring提供了JdbcDaoSupport作为所有基于JDBC进行数据访问的DAO实现类的超类,将DataSource和JdbcTemplate全部抽取到统一的超类JdbcDaoSupport中。这样Dao直接继承JdbcDaoSupport就行了。
    3.3、Spring在对各种ORM的集成时,起什么作用 ?
        主要体现在一下3个方面:
        1)、统一的资源管理方式。
        2)、特定于ORM的数据访问异常到Spring统一异常体系的转译。
        3)、统一的数据访问事物管理及控制方式。
    3.4、Spring中的DataSource ?
        DataSource的基本角色是ConnectionFactory,所有的数据库连接将通过DataSource接口统一管理。按照DataSource实现类的功能的强弱可以划分三类:
        1)、简单的DataSource
            通常该类DataSource实现只提供作为ConnectionFactory角色的基本功能。Spring提供了DriverManagerDataSource和SingleConnectionDataSource等。
        2)、拥有缓存池的DataSource
            通常该类DataSource实现除了提供作为ConnectionFactory角色的基本功能外,通常内部还会通过连接缓冲池对数据库连接进行管理。该类DataSource如Jakarta Commons DBCP和C3P0。
            配置如下:
            <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
                <property name="user" value="${jdbc.user}"></property>
                <property name="password" value="${jdbc.password}"></property>
                <property name="driverClass" value="${jdbc.driverClass}"></property>
                <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
                
                <property name="initialPoolSize" value="${jdbc.initPoolSize}"></property>
                <property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property>
            </bean>
        3)、支持分布式事务的DataSource实现类
            这类DataSource应该是javax.sql.XADataSource的实现类。该类DataSource如EBA的WebLogic或者IBM的WebSphere等。
    3.5、Spring对Hibernate集成时,如何配置和获取SessionFactory ?
        Spring采用FactoryBean的形式对SessionFactory的配置和获取进行封装。LocalSessionFactoryBean将是我们在Spring中配置或获取SessionFactory最为常用的方式。通过LocalSessionFactoryBean配置Hibernate数据访问相关的所有资源,包括Datasource、配置文件位置、映射文件位置。
        LocalSessionFactoryBean的配置形如:
        <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
            <properyt name="dataSource" ref="dataSource"></property>
            <property name="configLocation">
                <value>cn.test.hibernate.cfg.xml</value>
            </properyt>
        </bean>
    
        
4、事物
    4.1 、事物的属性(ACID)
        1)、原子性(Atomicity)
            原子性要求事务包含的全部操作是一个不可分割的整体,这些操作要么全部提交成功,要么只要其中一个操作失败,就全部失败。
        2)、一致性(Consistency)
            一致性要求事务的所包含的操作不能违反数据资源的一致性检查,数据源在事务执行之前处于某个数据一致性状态,那么,事务执行之后也依然需要保持数据间的一致性状态。
        3)、隔离性(Isolation)
            事务的隔离性主要规定了各个事务之间互相影响的程度。隔离性概念主要面向对数据资源的并发访问(Concurrency),并兼顾影响事务的一致性。
            事务指定了4种隔离级别(从弱到强分别是):
            ①、Read Uncommitted
                它是最低的隔离级别。Read Uncommitted最直接的效果是,一个事务可以读取另一个事务没有提交的更新结果。
                其无法避免以下问题:脏读(Dirty Read)、不可重复读(Non-Repeatable Read)和幻读(Phanton Read)。
            ②、Read Committed
                通常这是大部分数据库默认的隔离级别。在该隔离级别下,一个事务的更新操作结果只有在该事务提交之后,另一个事务才可能读取到同一笔数据更新后的结果。
                可以避免脏读,但无法避免不可重复读和幻读。
            ③、Repeatable Read
                Repeatable Read 可以保证在整个事务的过程中,对同一笔数据的读取结果是相同的,不管其它事务是否同时在对同一笔事务进行更新,也不管其它事务对同一笔数据的更新提交与否。
                可以避免脏读和不可重复读,但无法避免幻读。
            ④、Serializable
                它是最严格的级别。所有的事务操作都必须依次顺序执行,可以避免其它级别有的问题。但是太影响系统的并性能。
                
            通常,我们会使用其它隔离级别加上相应的并发锁的机制来控制对数据的访问,这样既保证了系统性能不会有太大的损失,也能够在一定程度上保证数据的一致性。
        4)、持久性(Durability)
            一旦整个事务提交成功,对数据所作的变更将被记录并不可逆转。
    4.2、Spring的TransactionDefinition中定义了5个可供选择的隔离级别是?
        ISOLATION_DEFAULT(如果指定隔离级别为ISOLATION_DEFAULT,则表示使用数据库默认的隔离级别)、ISOLATION_READ_UNCOMMITTED、ISOLATION_READ_COMMITED、ISOLATION_REPEATABLE_READ和ISOLATION_SERIALIZABLE。
    4.3、什么是第一类丢失更新、脏读、不可重复读、第二类丢失更新、幻读 ?
        ①、第一类丢失更新
            撤销一个事务的时候,把其它事务已提交的更新数据覆盖了。这是完全没有事务隔离级别造成的。如果事务1被提交,另一个事务被撤销,那么会连同事务1所做的更新也被撤销。
        ②、脏读(Dirty Read)
            如果一个事务对数据进行了更新,但事务还没有提交,另一个事务就可以“看到”该事务没有提交的更新结果。这样就造成的问题就是,如果第一个事务回滚,那么第二个事务在此之前所“看到”的数据就是一笔脏数据。
        ③、不可重复读取(Non-Repeatable Read)
            不可重复读取是指同一个事务在整个事务过程中对同一笔数据进行读取,每次读取结果都不同。如果事务1在事务2的更新操作之前读取一次数据,在事务2的更新操作之后再读取同一笔数据一次,两次结果是不同的。所以Read Uncommitted也无法避免不可重复读取的问题。
        ④、第二类丢失更新
            它和不可重复读本质上是同一类并发问题,通常将它看成不可重复读的特例。当两个或多个事务查询相同的记录,然后各自基于查询的结果更新记录时会造成第二类丢失更新问题。每个事务不知道其它事务的存在,最后一个事务对记录所做的更改将覆盖其它事务之前对该记录所做的更改。
        ⑤、幻读(Phanton Read)
            幻读是指同样一个查询在整个事务过程中多次执行后,查询所得的结果集是不一样的。幻读针对的是多笔记录。在Read Uncommitted隔离级别下,不管事务2的插入操作是否提交,事务1在插入操作执行之前和之后执行相同的查询,取得的结果集是不同的,所以Read Uncommitted同样无法避免幻读。
        无事务隔离级别,则存在:第一类丢失更新、脏读、不可重复读、第二类丢失更新和幻读问题。
        Read Uncommitted存在:脏读、不可重复读、第二类丢失更新和幻读问题。
        Read committed存在:不可重复读、第二类丢失更新和幻读问题。
        Repeatable Read存在:幻读问题。
        Serializable 不存在问题。
            
    4.4、Spring中事务的传播行为?
        针对事务的传播行为,TransactionDefinition提供了一下7种选择。PROPAGATION_REQUIRED、PROPAGATION_SUPPORTS、PROPAGATION_MANDATORY(强制要求当前存在一个事务,如果不存在,则抛出异常。如果某个方法需要事务支持,但自身又不管理事务提交或者回滚,那么比较适合使用PROPAGATION_MANDATORY)、PROPAGATION_REQUIRES_NEW、PROPAGATION_NOT_SUPPORTED、PROPAGATION_NEVER和PROPAGATION_NESTED.
        除了PROPAGATION_NESTED是Spring特有的外,其它传播行为的语义与CMT基本相同。
        
    4.5、Spring事务的架构?
        Spring 的事务框架设计理念的基本原则是:让事务管理的关注点与数据访问关注点相分离。
        Spring 的事务抽象包括3个主要接口,分别是PlatformTransactionManager、TransactionDefinition、TransactionSatus。
        PlatformTransactionManager负责界定事务边界;TransactionDefinition负责定义事务的相关属性,包括隔离级别、传播行为等;PlatformTransactionManager参照TransactionDefinition的属性定义来开启相关事务。事务开启之后到事务结束期间的事务状态由TransactionStatus负责,我们可以通过TransactionStatus对事务进行有限的控制。
        TransactionDefinition常用的实现有DefaultTransactionDefinition和TransactionTemplate(这两个主要用于编程式的事务场景)、DefaultTransactionAttribute和RuleBasedTransactionAttribute(这两个主要使用Spring AOP 进行声明式事务管理的场景中,RuleBasedTransactionAttribute允许我们同时制定多个回滚规则)。
        
        TransactionStatus有一个实现类DefaultTransactionStatus用来记录事务的状态信息。
        PlatformTransactionManager的实现类可以分为面向局部事务和面向全局事务两个分支。常用的面向局部事务的PlatformTransactionManager有DataSourceTransactionManager(用于JDBC和Mybatis)和HibernateTransactionManager。
    4.6、使用Spring如何进行事务管理?
        Spring的事务管理有两种方式,即编程式事务管理和声明式事务管理。
        4.6.1、编程式事务
            通过Spring 进行编程式事务管理有两种方式,要么直接使用PlatformTransactionManager,要么使用更方便的TransactionTemplate。
        4.6.2、声明式事务
            Spring提供了用于声明式事务管理的拦截器TransactionIntercepter(该拦截器用于查询记载着业务方法与对应事务信息之间关系的映射文件(事务驱动的元数据(Metadata))来决定要不要为当前业务方法创建事务)。有了TransactionIntercepter,我们所要做的就是决定使用XML元数据驱动还是使用注解元数据驱动的声明式事务管理。
            (1)、XML元数据驱动的声明式事务
                可以使用4种配置方式在IoC容器的配置文件中指定事务需要的元数据。
                ①、使用ProxyFactory(ProxyFactoryBean)+ TransactionIntercepter。
                ②、使用“一站式”的TransactionProxyFactoryBean。
                ③、使用BeanNameAutoProxyCreator。
                ④、使用Spring2.x的声明式事务。
                    <tx:advice id="advice" transaction-manager="transactionManager">
                        <tx:attributes>
                            <tx:method name="save*" propagation="REQUIRED"/>
                            <tx:method name="delete*" propagation="REQUIRED"/>
                            <tx:method name="update*" propagation="REQUIRED"/>
                            <tx:method name="add*" propagation="REQUIRED"/>
                            <tx:method name="*" propagation="SUPPORTS" read-only="true"/>
                        </tx:attributes>
                     </tx:advice>
                    
                     <!-- 5: 切入表达式: 配置运行的时候*包的*类切入通知 -->
                     <aop:config>
                        <aop:pointcut expression="execution(* cn.xaut.shop.service.impl.*.*(..))" id="pointcut"/>
                        <aop:advisor advice-ref="advice" pointcut-ref="pointcut"/>
                     </aop:config>
                    
                     <tx:advice>是专门为声明式事务Advice而设置的配置元素,底层当然还是我们的TransactionIntercepter。
            (2)、注解元数据驱动的声明式事务
                Spring 定义了org.springframework.transaction.annotation.Transactional用于标注业务方法所对应的事务元数据的信息。可以标注在业务方法或者业务方法所在的类的定义上。
                使用注解元驱动的声明式事务管理,基本上就需要两步:
                ①、使用@Transactional标注相应的业务对象及相关方法。
                ②、在容器的配置文件中启用事务注解
                <!-- 启用事物注解 -->
                <tx:annotation-driven transaction-manager="transactionManager"/>
0 0
原创粉丝点击