spring与mybatis的整合

关于spring与mybatis的整合,总所周知,spring是管理组件的创建,使用和删除的,那么当spring与mybatis进行整合时,则需要将mybatis的核心对象交给spring进行管理,包括SqlsessionFactory、Sqlsession等。
这样做的好处是不需要在编写mybatis-config.xml配置文件,简化了开发。

1. 首先需要引入依赖

spring依赖 mybatis依赖 mybatis-spring依赖 mysql依赖 druid依赖

2. 编写spring的配置文件

让spring管理SqlsessionFactory对象

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" >
            <!--数据源的配置-->
            <property name="dataSource" ref="dataSource" />
            <!--mapper的配置-->
            <property name="mapperLocations" >
                <array>
                    <value>classpath:mapper/UserDaoMapper.xml</value>
                </array>
            </property>
       </bean>

其中sqlSessionFactory需要数据源的配置和要对mapper进行注册。
数据源也是一个对象

<!--datasource通常有c3p0,druid,docp这些-->
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" >
            <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/test?serverTimezone=UTC"/>
            <property name="username" value="root"/>
            <property name="password" value="root"/>
        </bean>

sqlSessionFactory可以进行优化,不用写详细的mapper文件以及起别名

 <!--创建sqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--依赖数据源-->
        <property name="dataSource" ref="dataSource"/>
        <!--注入mapper配置文件-->
        <!--<property name="mapperLocations">
            <array>
                <value>classpath:com/baizhi/mapper/UserDAOMapper.xml</value>
                <value>classpath:com/baizhi/mapper/EmpDAOMapper.xml</value>
            </array>
        </property>-->
        <!--注入mapper文件通用方式-->
        <property name="mapperLocations" value="classpath:com/baizhi/mapper/*.xml"/>

        <!--注入别名相关配置 typeAliasesPackage:用来给指定包中所有类起别名 默认的别名: 类名|类名首字母小写-->
        <property name="typeAliasesPackage" value="com.baizhi.entity"/>
    </bean>

3.尝试获取sqlsessionFactory对象

ApplicationContext Context = new ClassPathXmlApplicationContext("spring.xml");
        SqlSessionFactory sqlSessionFactory = (SqlSessionFactory) Context.getBean("sqlSessionFactory");
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserDao userDao = sqlSession.getMapper(UserDao.class);
        List<User> users = userDao.findAll();
        users.forEach(user-> System.out.println(user));

4.进行优化

通过上述代码可以看出当我们获取到sqlSessionFactory后,我们还要通过这个对象获取sqlSession,
然后sqlsession再获取mapper(dao),才能进行数据库的操作。
因此spring和mybatis进行优化,将mapper(dao)的获取进行简化,将他们交给spring来进行管理
 <!--通过mapper-spring依赖快速的获取Dao,避免先获取factory在获取dao,造成代码的冗余-->
        <bean id="userDao" class="org.mybatis.spring.mapper.MapperFactoryBean">
            <!--注入sqlSessionFactory-->
            <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
            <!--要创建的dao或者mapper-->
            <property name="mapperInterface" value="dao.UserDao"/>
        </bean>

这样就能轻松的获取到mapper(dao)进行操作。
但这样每个dao都要写一个bean,比较麻烦,因此可以使用

<!--一次项目创建项目中所有DAO对象 MapperScannerConfigurer
        MapperScannerConfigurer:
            默认创建对象在工厂中唯一标识: 接口的首字母小写
            UserDAO=====> userDAO  Userdao====>  userdao
            OrderDAO====> orderDAO Orderdao====> orderdao
            EmpDAO  ===>  empDAO
     -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!--注入sqlSessionFactory-->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        <!--扫描DAO接口所在包-->
        <property name="basePackage" value="com.dao"/>
    </bean>

5. sqlsessionFactory的原始获取方式。

因为spring-mybatis依赖的缘故,我们能快速的获取到sqlsessionFactory的对象。
如果没有这个依赖,我们想要获取sqlsessionFactory是要通过sqlsessionFactoryBuilder来获取的。

InputStream is = Resources.getResourceAsStream(“mybatis-config.xml”);
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(is);

因为SqlSessionFactory是接口的缘故,属于复杂对象,因此想要得到它就需要创建一个SqlSessionFactoryBean类并继承FactoryBean接口来实现。

public class SqlsessionFactoryBean implements FactoryBean<SqlSessionFactory> {

    private String configLocations;

    public void setConfigLocations(String configLocations) {
        this.configLocations = configLocations;
    }

    @Override
    public SqlSessionFactory getObject() throws Exception {
        InputStream is = Resources.getResourceAsStream(configLocations);
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(is);
        return sessionFactory;
    }

    @Override
    public Class<?> getObjectType() {
        return SqlSessionFactory.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}

在spring配置文件中注册SqlsessionFactoryBean

<!--初始方式获取sqlSessionFactory的方法,因为sqlSessionFactory是接口,因此要再写一个类才能获取它-->
        <bean id="sqlSessionFactory" class="sqlsession.SqlsessionFactoryBean" >
            <property name="configLocations" value="mybatis-config.xml"/>
        </bean>

通过这样的方式就能获取sqlSessionFactory对象了。

6.service层中进行事务的管理(编程方式)

在spring和mybatis框架中,提供了一个类DataSourceTransactionManager用来通一调度业务层使用的线程和dao层使用的线程一致。

 <!--数据源事务管理-->
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--注入数据源对象-->
        <property name="dataSource" ref="dataSource"/>
        </bean>

为serviceImpl添加TransactionManager

private PlatformTransactionManager transactionManager;

    public void setTransactionManager(PlatformTransactionManager transactionManager) {
        this.transactionManager = transactionManager;
    }

业务层编写

@Override
    public void save(User user) {
        //创建事务配置对象
        TransactionDefinition transactionDefinition = new DefaultTransactionDefinition();
        //获取事务状态
        TransactionStatus status = transactionManager.getTransaction(transactionDefinition);
        try {
            int i = 1/0;
            userDao.save(user);
            transactionManager.commit(status);
        } catch (Exception e) {
            e.printStackTrace();
            transactionManager.rollback(status);
        }
    }

7.使用AOP思想来处理事务(声明方式)

开发基于事务的环绕通知
首先创建基于环绕事务的类

public class TransactionAdvice implements MethodInterceptor {

    private PlatformTransactionManager platformTransactionManager;

    public void setPlatformTransactionManager(PlatformTransactionManager platformTransactionManager) {
        this.platformTransactionManager = platformTransactionManager;
    }

    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        System.out.println("进入事务管理");
        //创建事务配置对象
        TransactionDefinition transactionDefinition = new DefaultTransactionDefinition();
        //获取事务状态
        TransactionStatus status = platformTransactionManager.getTransaction(transactionDefinition);
        try {
            Object result = methodInvocation.proceed();
            platformTransactionManager.commit(status);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
            platformTransactionManager.rollback(status);
        }
        return null;
    }
}

然后再spring配置文件中配置事务类以及切面,并且建立联系

		<!--数据源事务管理-->
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--注入数据源对象-->
        <property name="dataSource" ref="dataSource"/>
        </bean>


        <!--配置事务环绕通知类-->
        <bean id="tx" class="transaction.TransactionAdvice" >
            <property name="platformTransactionManager" ref="transactionManager" />
        </bean>

        <!--配置事务的切面-->
        <aop:config>
            <aop:pointcut id="pc" expression="execution(* service.UserServiceImpl2.*(..))"/>
            <aop:advisor advice-ref="tx" pointcut-ref="pc" />
        </aop:config>

完成

8.spring对声明式事务的优化

spring框架提供了 tx:advice标签
作用
1.可以根据事务管理器创建一个基于事务的环绕通知对象,就不用自己写了
2.tx:advice标签可以对事务进行细粒度控制,即是细化事务,例如查询不需要事务处理

		<!--创建一个基于事务管理器的事务环绕通知类-->
        <tx:advice id="txAdvice" transaction-manager="transactionManager">
        </tx:advice>

配置切面

 	<aop:config>
        <aop:pointcut id="pc" expression="execution(* service.UserServiceImpl2.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pc" />
    </aop:config>

完成上述两步后可以说已经为service添加了事务,但由于没有进行细化,因此spring将不会进行回滚的操作,即需要进一步的配置spring的事务环绕通知类,告诉spring如何处理事务。

<!--创建一个基于事务管理器的事务环绕通知类-->
        <tx:advice id="txAdvice" transaction-manager="transactionManager">
            <tx:attributes>
                <tx:method name="save*"/>
            </tx:attributes>
        </tx:advice>

9.SM整合步骤

引入依赖
建表
建实体类
Dao接口
Mapper配置文件
service接口
service接口实现类
编写SM整合配置spring.xml或者ApplicationContext.xml

10.整合步骤的优化,添加注解

spring.xml
1.开启注解扫描

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

2.创建数据源对象

		<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" >
            <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/test?serverTimezone=UTC"/>
            <property name="username" value="root"/>
            <property name="password" value="root"/>
        </bean>

3.创建sqlsessionFactory

		<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--注入dataSource mapperlocation 别名-->
        <property name="dataSource" ref="dataSource"/>
        <property name="mapperLocations" value="classpath:com/baizhi/mapper/*.xml"/>
        <property name="typeAliasesPackage" value="com.baizhi.entity"/>
    </bean>

4.创建Dao对象

 	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        <property name="basePackage" value="com.baizhi.dao"/>
    </bean>

5.创建事务管理器

	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

6.开启注解式事务生效

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

11.spring当中的注释

1.实例化相关注解

# 1. @Component(value="beanid")
				修饰范围:    用在类上
				注解作用:    通用的创建实例的注解,用来创建当前这个类的实例
				value属性:	用来指定创建的对象在工厂中的唯一标识   如果不指定默认创建对象在工厂中的标识为类名首字母小写
				
# 2. @Repository 
				修饰范围:    用在类上
				注解作用:    @component的子类注解专用于DAO组件的创建,通常加在DAO组件上
				value属性:	用来指定创建的对象在工厂中的唯一标识   如果不指定默认创建对象在工厂中的标识为类名首字母小写

# 3. @Service
				修饰范围:    用在类上
				注解作用:    @component的子类注解专用于Service组件的创建,通常加在Service组件上
				value属性:	用来指定创建的对象在工厂中的唯一标识   如果不指定默认创建对象在工厂中的标识为类名首字母小写

# 4. @Controller
			  修饰范围:    用在类上
				注解作用:    @component的子类注解专用于Action组件的创建,通常加在Action组件上
				value属性:	用来指定创建的对象在工厂中的唯一标识   如果不指定默认创建对象在工厂中的标识为类名首字母小写

2.控制对象的创建次数的注解

# 1. @Scope(value="singleton|prototype")
 			  修饰范围:    用在类上
				注解作用:    用来控制这个实例在工厂中的创建次数
				value属性:	singleton为单例,prototype为多例   默认单例

3.注入相关的注解

# 1. @Autowired(Spring提供)
				修饰范围:    用在成员变量或成员变量的GET/SET方法上
				注解作用:		 用来给类中成员变量赋值
				注入原则:    默认根据类型自动注入

# 2. @Resource(JAVAEE提供)
				修饰范围:    用在成员变量或成员变量的GET/SET方法上
				注解作用:		 用来给类中成员变量赋值
				注入原则:    默认根据名称自动注入名称找不到根据类型自动注入

4.控制事务的相关注解

# 1. @Transactional
			  修饰范围:    用在类上主要用在业务层组件类上或者是方法上
				注解作用:		 用来给类中方法加入事务,当类上和方法上同时存在该注解时局部优先
				注解属性:    
							propagation  用来控制传播属性
							Isolation    用来控制隔离级别
							timeout      用来设置超时性
							rollback-for 用来设置什么异常回滚
							norollback-for 用来设置什么异常不会滚
							readonly     用来设置事务读写性
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值