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群 微信
  • 相关阅读:
    JavaScript中的闭包
    SQL 备忘
    SqlServer 2005 升级至SP2过程中出现"身份验证"无法通过的问题
    unable to start debugging on the web server iis does not list an application that matches the launched url
    Freebsd 编译内核
    Freebsd 6.2中关于无线网络的设定
    【Oracle】ORA01219
    【Linux】Windows到Linux的文件复制
    【Web】jar命令行生成jar包
    【Linux】CIFS挂载Windows共享
  • 原文地址:https://www.cnblogs.com/hoaprox/p/14565714.html
Copyright © 2011-2022 走看看