zoukankan      html  css  js  c++  java
  • Spring入门二:整合mybatis

    一、SM思路分析

    1、引入核心依赖及相关依赖:

     spring(略)、mybatis、mysql、mybatis-spring(减少自己实现FactoryBean接口)、druid
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.22</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>2.0.6</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.6</version>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.2.5</version>
    </dependency>
    

    2、如何整合?

    通过spring框架接管mybatis框架中核心对象的创建

    3、mybatis中的核心对象

    SqlSessionFactory

    4、SM整合实质

    通过spring框架接管mybatis中核心的SqlSessionFactory对象的创建。Spring如何管理SqlSessionFactory对象的创建?SqlSessionFactory是一个接口类型的复杂对象。

    is=Resource.getResourceAsStrem("mybatis-config.xml);

    sqlSessionFactory=new SqlSessionFactoryBuilder().build(is);

    1)手动配置:

    (0)在类路径下配置mybatis-config.xml的数据源:

    <dataSource type="POOLED">
        <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://127.0.0.1:3306/springboot?characterEncoding=UTF-8&amp;serverTimezone=UTC"/>
        <property name="username" value="root"/>
        <property name="password" value="xroot"/>
    </dataSource>
    

    1)在spring中可以新建类SqlSessionFactoryBean实现FactoryBean接口

    //自定义SqlSessionFactory
    public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory> {
        private String configLocations;//通过参数注入配置文件名
    
        public void setConfigLocations(String configLocations) {
            this.configLocations = configLocations;
        }
    
        public SqlSessionFactory getObject() throws Exception {
            //InputStream rs = Resources.getResourceAsStream("mybatis-config.xml");
            InputStream rs = Resources.getResourceAsStream(configLocations);
            SqlSessionFactory build = new SqlSessionFactoryBuilder().build(rs);
            return build;
        }
    
        public java.lang.Class<?> getObjectType() {
            return SqlSessionFactory.class;
        }
    
        public boolean isSingleton() {
            return true;
        }
    }
    

    2)工厂管理SqlSessionFactory

    <bean id="sqlSessionFactory" class="com.icucoder.SqlSessionFactoryBean">
       <property name="configLocations" value="mybatis-config.xml"/>
    </bean>
    

    3)工厂获取

    ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
    SqlSessionFactory sqlSessionFactory = (SqlSessionFactory) context.getBean("sqlSessionFactory");
    System.out.println(sqlSessionFactory.openSession());
    

    2)spring自动配置(使用mybatis-spring依赖:Mybatis-spring.jar封装了SqlSessionFactory对象的创建)

    0)加入mybatis-spring依赖、druid依赖(简单类型)

    1)工厂管理SqlSessionFactory并配置druid数据源对象dataSource

    <!--创建数据源对象 druid c3p0 dbcp-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://127.0.0.1:3306/springboot?characterEncoding=UTF-8"/>
        <property name="username" value="root"/>
        <property name="password" value="xroot"/>
    </bean>
    
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--依赖数据源-->
        <property name="dataSource" ref="dataSource"/>
        <!--依赖mapper文件注册-->
        <property name="mapperLocations">
            <array>
                <value>com/icucoder/mapper/UserDaoMapper.xml</value>
            </array>
        </property>
    </bean>
    

     上述配置每创建一个Mapper文件,需要配置一个array,可以使用mapperLocations配置某个具体类路径下xml的自动扫描。

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 依赖数据源 -->
        <property name="dataSource" ref="dataSource"/>
        <!-- 注入mapper通用方式 -->
        <property name="mapperLocations" value="classpath:mapper/*.xml"></property>
        <!-- 取别名 -->
        <property name="typeAliasesPackage" value="com.icucoder.entity"></property>
    </bean>
     

    2)工厂获取

    ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
    SqlSessionFactory sqlSessionFactory = (SqlSessionFactory) context.getBean("sqlSessionFactory");
    System.out.println(sqlSessionFactory.openSession());
    

    二、DAO层开发

    1、建实体类(前提数据库中有表)

    public class User {
        private Integer id;
        private String name;
        private Integer age;
        private Integer email;
        //省略有参和无参构造 setter和getter方法
    }
    

    2、DAO接口

    public interface UserDao {
        List<User>findAll();
    }
    

    3、开发mapper(dao的实现类)

    <mapper namespace="com.icucoder.dao.UserDao">
        <select id="findAll" resultType="com.icucoder.entity.User">
            select id,name,age,email
            from user
      </select>
    </mapper>
    

    4、spring配置文件中注册mapper配置文件

    <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>
    

    上述配置每创建一个Mapper文件,需要配置一个array,可以使用mapperLocations配置某个具体类路径下xml的自动扫描(见上)。

    5、启动工厂获SqlSessionfactory

    1)手动获取DAO:

    ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
    SqlSessionFactory sqlSessionFactory = (SqlSessionFactory) context.getBean("sqlSessionFactory");
    SqlSession sqlSession = sqlSessionFactory.openSession();
    UserDao userDao = sqlSession.getMapper(UserDao.class);
    System.out.println(userDao.findAll());
    

     2)使用MapperFactoryBean获取DAO:

    1)在MapperFactoryBean中注入SqlSessionFactory和Dao路径

    <!--创建Dao组件类-->
    <bean id="userDao" class="org.mybatis.spring.mapper.MapperFactoryBean">
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        <!--注入dao类型-->
        <property name="mapperInterface" value="com.icucoder.dao.UserDao"/>
    </bean>
    

     上述配置每创建一个Dao组件类,需要配置一个bean,可以使用MapperScannerConfigurer配置某个具体累计下dao的自动扫描

    <!--创建Dao组件类-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>>
        <!--扫描DAO接口所在包-->
        <property name="basePackage" value="com.icucoder.dao"/>
    </bean>
    

     2)调用bean

    ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
    UserDao userDao = (UserDao) context.getBean("userDao");
    System.out.println(userDao.findAll());
    

    三、Service层事务控制

    在上述dao的基础上:

    1、常规做法(使用默认的事务)

    1)创建Service及其实现类

    //UserService省略
    public class UserServiceImpl implements UserService {
        private UserDao userDao;
        //private DataSource dataSource;//手动注入 dataSoruce无法保证service与dao层事务的连接性
        public void setUserDao(UserDao userDao) {
            this.userDao = userDao;
        }
    
        @Override
        public List<User> findAll() {
            return userDao.findAll();
        }
    }
    

     2)在spring配置文件中管理service组件

    <bean id="userService" class="com.icucoder.service.impl.UserServiceImpl">
       <property name="userDao" ref="userDao"/>
    </bean>
    

     3)调用Bean

    ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
    UserService userService = (UserService) context.getBean("userService");
    System.out.println(userService.findAll());
    

    2、mybatis框架中事物控制分析

    SqlSession,提交:sqlSession.commit);回滚:sqlSessioin.rollback();

    真正负责数据库事物控制的对象:Connection(java.sql.Connection)对象。

    注意:数据源DruidDataSource是一个连接池,里面都是Connection对象。

    Connection conn=DruidDataSource().getConnection();

    可以在业务层手动注入dataSource对象来控制事务,但是无法保证业务层(Sevice)和Dao事务的连接性。

    3、数据源事务管理器:DataSourceTransactionManager

    在spring和mybatis框架中提供了一个类DataSourceTransactionManager(数据源事务管理器)来全局创建一个事务管理器,用来统一调度业务层当前线程使用连接对象和DAO层实现连接对象一致。它依赖于数据源。

    在spring.xml文件中添加DataSourceTransactionManager的bean。

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

    4、给现有业务层加入事务控制(手动配置事务)

     1)重写service实现类

    public class UserServiceImpl implements UserService {
        private PlatformTransactionManager transactionManager;
    
        public void setTransactionManager(PlatformTransactionManager transactionManager) {
            this.transactionManager = transactionManager;
        }
    
        private UserDao userDao;
    
        public void setUserDao(UserDao userDao) {
            this.userDao = userDao;
        }
    
        @Override
        public List<User> findAll() {
            return userDao.findAll();
        }
    
        @Override
        public void save(User user) {
            TransactionDefinition transactionDefinition = new DefaultTransactionDefinition();
            TransactionStatus status = transactionManager.getTransaction(transactionDefinition);
    
            //控制事物
            try {
                //处理业务
                //调用业务
                userDao.save(user);
                int i=1/0;
                transactionManager.commit(status);
                System.out.println("save success");
            }catch (Exception e){
                e.printStackTrace();
                transactionManager.rollback(status);
            }
        }
    }
    

     2)在spring配置文件的service的bean标签中注入数据源事务管理器

    <bean id="userService" class="com.icucoder.service.impl.UserServiceImpl">
        <property name="userDao" ref="userDao"/>
        <property name="transactionManager" ref="transactionManager"/>
    </bean>
    

    3)调用Bean

    ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
    UserService userService = (UserService) context.getBean("userService");
    User user=new User(7,"test",12,"admin@qq.com");
    System.out.println(user);
    userService.save(user);
    

    四、Service层事务控制优化(自动配置事务)

    1、spring中处理事务的两种方式

    编程式事务处理:通过在业务层中农注入事务管理器对象,然后通过编码的方式进行事务控制。

    声明式事务处理:通过利用aop切面编程进行事务控制,并对事务属性在配置文件中完成细粒度配置。

    2、给现有业务层加入事务控制(手动配置事务优化)

    开发一个基于事务的通知(环绕通知)TransactionAdvice实现MethodInterceptor。

    1)创建环绕通知

    2)配置切面

    3)使用环绕通知

    3、给现有业务层加入事务控制(自动配置事务-使用aop)

     spring框架提供了<tx:advice/>标签,该标签可以根据事务管理器创建一个基于事务环绕通知对象,并对业务层方法进行细粒度事务控制。

     1)在spring配置文件中加入声明式事务管理

    <!--声明式事务管理-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <!--事务细粒度控制,不控制则事务不生效-->
        <tx:attributes>
            <tx:method name="save*"/>
        </tx:attributes>
    </tx:advice>
    

    2)配置切面

    <!--配置事务切面-->
    <aop:config>
        <aop:pointcut id="pc" expression="within(com.icucoder.service.impl.*ServiceImpl)"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pc"/>
    </aop:config>
    

     3)重写service实现类

    public class UserServiceImpl implements UserService {
    
        private UserDao userDao;
    
        public void setUserDao(UserDao userDao) {
            this.userDao = userDao;
        }
    
        @Override
        public List<User> findAll() {
            return userDao.findAll();
        }
    
        @Override
        public void save(User user) {
            //控制事物
            //处理业务
            //调用业务
            userDao.save(user);
            int i = 1 / 0;
            System.out.println("save");
        }
    }
    

    4、给现有业务层加入事务控制(自动配置事务-开启注解式事务驱动管理器)

    1)在spring配置文件中加入tx:annotation-driven,这样就不要<tx:advice/>和<aop:config>,可以直接使用注解@Transactional

    <!--开启注解式事务驱动管理器@Transactional-->
    <tx:annotation-driven transaction-manager="transactionManager"/>
    

    2)重写service实现类

    @Transactional
    public class UserServiceImpl implements UserService {
    
        private UserDao userDao;
    
        public void setUserDao(UserDao userDao) {
            this.userDao = userDao;
        }
    
        @Override
        public List<User> findAll() {
            return userDao.findAll();
        }
    
        @Override
        public void save(User user) {
            //控制事物
            //处理业务
            //调用业务
            userDao.save(user);
            int i = 1 / 0;
            System.out.println("save");
    
        }
    }
    
     注:
    也可以使用easycode直接对数据的表生成entity,controller,service,dao,mapper,无需任何编码。
     

    如果你真心觉得文章写得不错,而且对你有所帮助,那就不妨小小打赏一下吧,如果囊中羞涩,不妨帮忙“推荐"一下,您的“推荐”和”打赏“将是我最大的写作动力!

    本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接.
    qq群 微信
  • 相关阅读:
    Java程序员之JS(一) 入门
    Java虚拟机(一)之开篇
    JDK/JRE/JVM区别与联系
    web开发视频(一)之环境准备
    Spring MVC 教程,快速入门,深入分析
    Java中“==和equals”的区别
    如何查看电脑最大支持多少GB内存
    win10 计算器calc命令打不开
    Win10图标显示不正常解决办法
    在系统右键菜单上添加程序
  • 原文地址:https://www.cnblogs.com/hoaprox/p/14565714.html
Copyright © 2011-2022 走看看