一起学习SSM框架之spring(三)

Spring整合MyBatis

配置数据源

1.引入jdbc.properties配置文件

jdbc.properties

jdbc.url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8&useSSL=false
jdbc.username=root
jdbc.password=root
jdbc.driver=com.mysql.jdbc.Driver
jdbc.init=1
jdbc.minIdle=1
jdbc.maxActive=3

2.整合Spring配置文件和properties配置文件

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"

       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       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/context
                           http://www.springframework.org/schema/context.spring-context.xsd">
        <context:property-placeholder location="jdbc.properties"/>
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
                <!--基本配置-->
                <property name="driverClassName" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>

                <!--配置初始化大小,最小,最大-->
                <property name="initialSize" value="${jdbc.init}"/>
                <property name="minIdle" value="${jdbc.minIdle}"/>
                <property name="maxActive" value="${jdbc.maxActive}"/>

                <!--配置获取连接等待超时的时间-->
                <property name="maxWait" value="60000"/>

                <!--配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒-->
                <property name="timeBetweenEvictionRunsMillis" value="60000"/>

                <!--配置一个连接在池中最小生存的时间,单位是毫秒-->
                <property name="minEvictableIdleTimeMillis" value="300000"/>
        </bean>
</beans>

3.Druid连接池可选参数

    <!--配置初始化大小,最小,最大-->
                <property name="initialSize" value="${jdbc.init}"/>
                <property name="minIdle" value="${jdbc.minIdle}"/>
                <property name="maxActive" value="${jdbc.maxActive}"/>

                <!--配置获取连接等待超时的时间-->
                <property name="maxWait" value="60000"/>

                <!--配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒-->
                <property name="timeBetweenEvictionRunsMillis" value="60000"/>

                <!--配置一个连接在池中最小生存的时间,单位是毫秒-->
                <property name="minEvictableIdleTimeMillis" value="300000"/>

4.Druid监控中心

5.测试监控中心

整合MyBatis

1.导入依赖


        <!--Spring整合MyBatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.3.2</version>
        </dependency>

        <!--MyBatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.5</version>
        </dependency>

        <!--mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
            <scope>runtime</scope>
        </dependency>

2.配置SqlSessionFactory

<!--生产SqlSessionFactory-->
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
               <!--注入连接池-->
                <property name="dataSource" ref="dataSource"/>
                <!--注册mapper文件信息,如果映射文件和dao接口 同包且同名,则此配置可以省略-->
                <property name="mapperLocations">
                        <list>
                                <value>classpath:cn/ozl/dao/*.xml</value>
                        </list>
                </property>
                <!--为mapper文件中的实体定义缺省包路径-->
                <property name="typeAliasesPackage" value="cn.ozl.entity"></property>
        </bean>

3.配置MapperScannerConfigurer

管理DAO实现类的创建,并创建DAO对象,存入工厂管理
1.扫描所有DAO接口,去构建DAO实现
2.将DAO实现存入工厂管理
3.DAO实现对象在工厂的id是:“首字母小写的-接口额类名”,例如UserDao=》userDao
 <bean id="mapperScannerConfigurer9" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            <property name="basePackage" value="cn.ozl.dao"/>
            <!--只有一个SqlSessionFactory的bean可以省略-->
            <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        </bean>

4.配置Service

<bean id="userService" class="cn.ozl.service.UserServiceImpl">
            <property name="userDao" ref="userDao"/>
        </bean>

事务

applicationContext.xml

  <!--引入一个事务管理器,其中依赖DataSource,借以获得连接,进而控制事务逻辑-->
        <bean id="tx" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource"/>
         </bean>

        <!--事务通知-->
        <tx:advice id="txManager" transaction-manager="tx">
            <!--事务属性-->
            <tx:attributes>
                <!--<tx:method name="queryUser" isolation="DEFAULT" propagation="SUPPORTS" read-only="true" timeout="-1" rollback-for="Exception"/>-->
                <tx:method name="queryUser"  propagation="SUPPORTS" />
                <!--<tx:method name="insertUser" isolation="DEFAULT" propagation="REQUIRED" read-only="false" timeout="-1" rollback-for="Exception"/>-->
                <tx:method name="*User"  rollback-for="Exception"/>
                <!--剩余的所有方法-->
                <tx:method name="*"/>
            </tx:attributes>
        </tx:advice>

        <!--编织 声明式事务控制-->
        <aop:config>
            <aop:pointcut id="pzl_tx" expression="execution(* cn.ozl.service.UserServiceImpl.*(..))"/>
            <aop:advisor advice-ref="txManager" pointcut-ref="pzl_tx"/>
        </aop:config>

UserServiceImpl

public class UserServiceImpl implements UserService{
    
    
    private UserDao userDao;

    public UserDao getUserDao() {
    
    
        return userDao;
    }

    public void setUserDao(UserDao userDao) {
    
    
        this.userDao = userDao;
    }

    public List<User> queryUsers() {
    
    
        return userDao.queryUsers();
    }

    public void insertUser(User user) {
    
    
        userDao.insertUser(user);
    }

    public void updateUser(User user) {
    
    
        userDao.updateUser(user);
    }

    public Integer deleteUser(Integer id) {
    
    
        Integer integer=userDao.deleteUser(id);
        System.out.println(integer);
        if (1==1){
    
    
            try {
    
    
                throw new SQLException("test 事务");
            } catch (SQLException e) {
    
    
                e.printStackTrace();
                throw new RuntimeException("test 事务!!");
            }
        }
        return integer;
    }
}

test测试

  @Test
    public void testtx(){
    
    
        ApplicationContext context = new ClassPathXmlApplicationContext("/applicationContext.xml");
        UserService userService = (UserService) context.getBean("userService");
        userService.deleteUser(1002);
    }

1.配置DataSourceTransactionManager

事务管理器,其中持有DataSoure,可以控制事务功能(rollback,commit等)
  <!--引入一个事务管理器,其中依赖DataSource,借以获得连接,进而控制事务逻辑-->
        <bean id="tx" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource"/>
         </bean>

注意:DataSourceTransactionManager和SqlSessionFactoryBean要注入同一个DataSource的bean,否则事务控制会失败

2.配置事务通知

基于事务管理,进一步控制,生成一个额外的功能:advice
此Advice可以切入任何的需要事务的方法,通过事务管理器为方法控制事务
 <!--事务通知-->
        <tx:advice id="txManager" transaction-manager="tx">
            <!--事务属性-->
            <tx:attributes>
                <!--<tx:method name="queryUser" isolation="DEFAULT" propagation="SUPPORTS" read-only="true" timeout="-1" rollback-for="Exception"/>-->
                <tx:method name="queryUser"  propagation="SUPPORTS" />
                <!--<tx:method name="insertUser" isolation="DEFAULT" propagation="REQUIRED" read-only="false" timeout="-1" rollback-for="Exception"/>-->
                <tx:method name="*User"  rollback-for="Exception"/>
                <!--剩余的所有方法-->
                <tx:method name="*"/>
            </tx:attributes>
        </tx:advice>

3.事务属性

3.1隔离级别

isolation

1.default (默认值)(采取数据库的默认设置)(建议)
2.read-uncommited 读未提交
3.read-commited 读提交
4.repeatable-read 可重复读
5.serialized-read 序列化读

隔离级别由低到高:read-uncommited<read-commited<repeatable-read<serialized-read

安全性:级别越高,多事务并发时,越安全,因为共享的数据越来越少,事务彼此之间干扰减少
并发性:级别越高,多事务并发时,并发越差,因为共享的数据越来越少,事务间阻塞情况增多

事务并发时的安全问题
1.脏读:一个事务读取到另一个事务还未提交的数据
大于read-uncommited可防止
2.不可重复读:一个事务内多次读取一行数据的相同内容,其结果不一致
大于read-commited可防止
3,幻读:一个事务内多次读取一张表中相同的内容,其结果不一致
大于repeatale-read可防止

 <!--<tx:method name="insertUser" isolation="DEFAULT" propagation="REQUIRED" read-only="false" timeout="-1" rollback-for="Exception"/>-->

3.2传播行为

propagation

当涉及到事务的嵌套(Service调用Service)中,可能存在的问题
1.SUPPORTS=不存在外部事务,则不开启新的事务,存在外部事务,则合并到外部事务中(适合查询)
2.REQUIRED=不存在外部事务,则开启事务,存在外部事务,则合并到外部事务中(默认值)(适合增删改)

 <!--<tx:method name="insertUser" isolation="DEFAULT" propagation="REQUIRED" read-only="false" timeout="-1" rollback-for="Exception"/>-->

3.3读写性

readonly

1.true:只读,可提交查询效率(适合查询)
2.false:可读可写 (默认值)(适合增删改)

 <!--<tx:method name="insertUser" isolation="DEFAULT" propagation="REQUIRED" read-only="false" timeout="-1" rollback-for="Exception"/>-->

3.4事务超时

timeout

当事务所需操作的数据被其他事务占用,则等待
1.100:自定义等待时间100(秒)
2.-1:由数据库指定等待时间,默认值(建议)

 <!--<tx:method name="insertUser" isolation="DEFAULT" propagation="REQUIRED" read-only="false" timeout="-1" rollback-for="Exception"/>-->

3.5事务回滚

rollback-for

1.如果事务中抛出 RuntimeException,则自动回滚
2.如果事务中抛出 CheckException(非运行时异常 Exception),不会自动回滚,而是默认提交事务
3.处理方案:将CheckException转换成RuntimeException上抛,或设置rollback-for=“Exception”

<tx:method name="*User"  rollback-for="Exception"/>
   public Integer deleteUser(Integer id) {
    
    
        Integer integer=userDao.deleteUser(id);
        System.out.println(integer);
        if (1==1){
    
    
            try {
    
    
                throw new SQLException("test 事务");
            } catch (SQLException e) {
    
    
                e.printStackTrace();
                throw new RuntimeException("test 事务!!");
            }
        }
        return integer;
    }

4.编织

将管理的advice切入需要事务的业务中
  <!--编织 声明式事务控制-->
        <aop:config>
            <aop:pointcut id="pzl_tx" expression="execution(* cn.ozl.service.UserServiceImpl.*(..))"/>
            <aop:advisor advice-ref="txManager" pointcut-ref="pzl_tx"/>
        </aop:config>

猜你喜欢

转载自blog.csdn.net/ozl520/article/details/109028746