Spring11:Spring整合持久层

1.持久层整合

1.1Spring框架为什么要与持久层技术进行整合

1.Spring框架为什么要与持久层技术进行整合

1.JavaEE开发需要持久层进行数据库的访问操作------>需要
2.JDBC,Hibernate,Mybatis进行持久层开发过程中存在大量的代码冗余------>但是有冗余
3.Spring基于模版设计模式对于上述的持久层技术进行了封装------>我要改进,整合

2.Spring可以与哪些持久层技术进行整合

1. JDBC
 	|-  JDBCTemplate 
2. Hibernate (JPA)
     |-  HibernateTemplate
3. MyBatis
     |-  SqlSessionFactoryBean MapperScannerConfigure 

1.2.MyBatis开发步骤回顾

MyBatis开发步骤回顾

1. 实体
2. 实体别名  
3. 表
4. 创建DAO接口
5. 实现Mapper文件
6. 注册Mapper文件
7. MybatisAPI调用
  • 1.添加pom坐标

            <!--添加mysql驱动-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.6</version>
            </dependency>
            <!--mybatis-->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.4.5</version>
            </dependency>
    
  • 2.2个配置文件:
    1.映射文件:xxxMapper.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper>
    
    </mapper>
    

    2.Mybatis配置文件:mybatis-config1.xml。
    注意:我这里起名mybatis-config1.xml,是因为mybatis-config.xml这个名字会被解析成一个普通文本文件,而且没有代码提示。

    在这里插入图片描述

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
        <typeAliases>
        </typeAliases>
    
        <environments default="mysql">
            <environment id="mysql">
                <transactionManager type="JDBC"></transactionManager>
                <dataSource type="POOLED">
                    <property name="dirver" value="com.mysql.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql://localhost:3306/test_db?useSSL=false"/>
                    <property name="username" value="root"/>
                    <property name="password" value="root"/>
                </dataSource>
            </environment>
        </environments>
    
        <mappers>
    
        </mappers>
    </configuration>
    
  • 3.实体类

    public class User implements Serializable {
    
        private Integer id;
        private String name;
        private String password;
    
        public User() {
        }
    
        public User(Integer id, String name, String password) {
            this.id = id;
            this.name = name;
            this.password = password;
        }
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    }
    
    
  • 4.设置实体别名:之后在映射文件xxxMapper.xml中,就不用在写全限定类名了。
    在这里插入图片描述

  • 5.MySQL中创建user表:
    在这里插入图片描述

  • 6.定义DAO接口

    public interface UserDao {
    
        void save(User user);
    }
    
    
  • 7.创建对应的Dao的Mapper:UserMapper.xml
    注意这里的parameterType="user"中的user,就是在mybatis-config1中配置的别名:<typeAlias type="com.txl.example.mybatis.User" alias="user"/>

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.txl.example.mybatis.UserDao">
        <insert id="save" parameterType="user">
            insert into user(name, password) values (#{name}, #{password})
        </insert>
    </mapper>
    
  • 8.在mybatis-config1注册刚才写的Mapper

    注意:这个Mapper直接放在了resources根下面

    在这里插入图片描述

  • 9.测试:获得对应Dao接口的实现类UserDao userDao = sqlSession.getMapper(UserDao.class);

    public class TestMybatis {
        public static void main(String[] args) throws IOException {
            InputStream inputStream = Resources.getResourceAsStream("mybatis-config1.xml");
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            SqlSession sqlSession = sqlSessionFactory.openSession();
    
            UserDao userDao = sqlSession.getMapper(UserDao.class);
    
            User user = new User();
            user.setName("ttxxll");
            user.setPassword("123456");
            userDao.save(user);
    
            sqlSession.commit();
        }
    }
    
    

1.3.MyBatis开发过程中存在的问题

1.配置繁琐:配置很多的实体别名,每个Mapper文件都还要注册

2.代码冗余:

  • 创建SqlSession的代码是固定的:但是每次获取SqlSession 时都要写一遍。
    InputStream inputStream = Resources.getResourceAsStream("mybatis-config1.xml");
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    SqlSession sqlSession = sqlSessionFactory.openSession();
    

2.Spring与MyBatis整合

思路:主要是对这4行冗余的代码进行封装
在这里插入图片描述

2.1SqlSessionFactoryBean封装获得SqlSessionFactory

1.Spring整合Mybatis后,就不用通过这两行代码获取SqlSessionFactory

InputStream inputStream = Resources.getResourceAsStream("mybatis-config1.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

通过一个Spring提供的类SqlSessionFactoryBean,获得这个对象。

2.分析一下:mybatis-config.xml主要帮我做了哪些事:

在这里插入图片描述
3.所以即使通过Spring提供的类SqlSessionFactoryBean,获得SqlSessionFactory对象。还是需要数据源,别名配置,Mapper注册。那么SqlSessionFactoryBean是怎么获得这些信息呢?

4.向SqlSessionFactoryBean对象注册对应的成员变量:那么就可以省略mybatis-config.xml配置文件了。

<bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
  <property name="dataSource" ref="dataSource"></property>
  <property name="typeAliasesPackage" value="com.baizhiedu.entity">		 </property>
  <property name="mapperLocations">
    <list>
      <value>classpath:com.baizhiedu.mapper/*Mapper.xml</value>
    </list>
	</property>
</bean>

5.减少了配置:

  • <property name="typeAliasesPackage" value="com.baizhiedu.entity">为整个包配置别名,减少了别名的配置。
  • 通配注册方式Mapepr:注册以Mapper结尾的文件,减少了注册Mapper的配置
      <property name="mapperLocations">
        <list>
          <value>classpath:com.baizhiedu.mapper/*Mapper.xml</value>
        </list>
    	</property>
    

2.2获得SqlSession和对应Dao接口的实现类

1.拿到SqlSessionFactoryBean创建的SqlSessionFactory
2.提供Dao接口的.class

在这里插入图片描述

3.Spring提供了一个类MapperScannerConfigure来帮我们做到上述过程。

MapperScannerConfigure封装好了上面两句代码。

<!--创建DAO对象 MapperScannerConfigure-->
<bean id="scanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
  <property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryBean"></property>
  <!--设置Dao接口所在包:并且创建Dao接口的实现类-->
  <property name="basePackage" value="com.baizhiedu.dao"></property>
</bean>
  • 注意:MapperScannerConfigure可以帮我们创建Dao对象,它的id值是接口手单词字母小写。
    在这里插入图片描述

  • 注意:为什么在注入sqlSessionFactoryBeanName属性时,要用value注入sqlSessionFactoryBean而不是ref注入sqlSessionFactoryBean?

    1.首先MapperScannerConfigure类中的sqlSessionFactoryBeanName这个属性本身就是String类型的,所以用value注入。
    在这里插入图片描述

  • 按理说这个属性应该是SqlSessionFactoryBeanName类型的属性,为什么这里定义成String的呢?

    在mybatis-spring 1.1.0以前,是通过将SqlSessionFactory对象注入到sqlSessionFactory,这样做可能会有一个问题,就是在初始化MyBatis时,jdbc.properties文件还没被加载进来,dataSource的属性值没有被替换,就开始构造sqlSessionFactory类,属性值就会加载失败。在1.1.0以后,MapperScannerConfigure提供了String类型的sqlSessionFactoryBeanName,这样将bean name注入到sqlSessionFactoryBeanName,这样就会等到spring初始化完成后,再构建sqlSessionFactory。因为value 属性需要一个正确并且存在的值。如果配置文件出错,或者没被加载,整个dataSource 就不存在,那么sqlSessionFactory 也是错误的,不存在的值, value值就不存在,不会在这个地方抛出异常;但是使用ref 属性,就会出现,不管这个引入的值对不对,都会被使用。但实际会因为这个值不存在,导致异常。

2.3分析小结

在这里插入图片描述

2.4Spring整合Mybatis的开发步骤

1.配置文件相关的配置

#配置 是需要配置一次 
<bean id="dataSource" class=""/> 

<!--创建SqlSessionFactory-->
<bean id="ssfb" class="SqlSessionFactoryBean">
    <property name="dataSource" ref=""/>
    <property name="typeAliasesPackage">
         指定 实体类所在的包  com.baizhiedu.entity  User
                                                 Product
    </property>
    <property name="mapperLocations">
          指定 配置文件(映射文件)的路径 还有通用配置 
          com.baizhiedu.mapper/*Mapper.xml 
    </property>
</bean>

<!--DAO接口的实现类
    session ---> session.getMapper() --- xxxDAO实现类对象 
    XXXDAO  ---> xXXDAO
-->
<bean id="scanner" class="MapperScannerConfigure">
    <property name="sqlSessionFactoryBeanName" value="ssfb"/>
    <property name="basePacakge">
        指定 DAO接口放置的包  com.baizhiedu.dao 
    </property>
</bean>

2.编码步骤:只剩4步了

1. 实体
//2. 实体别名  
3. 表
4. 创建DAO接口
5. 实现Mapper文件
//6. 注册Mapper文件
//7. MybatisAPI调用

2.5Spring整合Mybatis的编码

1.导入jar包:pom

        <!--添加mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.5</version>
        </dependency>
        <!--jdbc-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.1.14.RELEASE</version>
        </dependency>
        <!--Spring整合mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.2</version>
        </dependency>
        <!--druid连接池-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.18</version>
        </dependency>

2.Spring配置文件

<!--1.配置连接池-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/test_db?useSSL=false"/>
    <property name="username" value="root"/>
    <property name="password" value="root"/>
</bean>
<!--2.配置创建SqlSessionFactory的SqlSessionFactoryBean-->
<bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="typeAliasesPackage" value="com.txl.example.mybatis.entity"/>
    <property name="mapperLocations">
        <list>
            <value>classpath:mappers/*.xml</value>
        </list>
    </property>
</bean>
<!--3.MapperScannerConfigure创建Dao接口的实现对象-->
<bean id="scanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryBean"/>
    <property name="basePackage" value="com.txl.example.mybatis.dao"/>
</bean>

3.编码

1.实体
2.表
3.Dao接口
4.Mapper文件配置
  • 注意:在编写Mapper文件配置,注意到我们在applicationContext配置了实体类的别名默认是类名。
    在这里插入图片描述

4.测试

    @org.junit.Test
    public void test0(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/applicationContext.xml");
        UserDao userDao = (UserDao)applicationContext.getBean("userDao");
        User user = new User();
        user.setName("txl");
        user.setPassword("123");
        userDao.save(user);
    }

3.整合mybatis细节

1.原来在单纯的应用mybatis时,增删改操作要加上事务。

2.现在发现Spring的工厂给我创建的Dao对象,我们执行了save操作后,没有进行事务提交。

在这里插入图片描述
3.没有事务操作,这个是怎么能完整无误的插入到数据库中呢?

4.核心是连接对象:Connection,连接对象控制事务,控制了连接对象,就相当于控制了事务。

5.谁控制了连接对象呢?

  • Spring没有控制连接对象
    在这里插入图片描述
  • 本质上控制连接对象的是:连接池

5.以前单纯运用mybatis进行开发的时候,Mybatis提供了一个连接池对象,进而创建连接对象。现在整合后,是Druid连接池创建连接对象。

6.两者的差别:

  • Mybatis提供的连接池对象连接池在创建连接对象是会将:Connection.setAutoCommit(false)设置为false,意味着需要手工的控制事务 ,操作完成后,手工提交。
  • 而Druid(C3P0也是的)连接池设置Connection.setAutoCommit(true) true且是默认值,保持自动控制事务,一条sql 自动提交 。

7.因为Spring与Mybatis整合时,引入了外部连接池对象,保持自动的事务提交这个机制(Connection.setAutoCommit(true)),不需要手工进行事务的操作,也能进行事务的提交 。

8.一个业务涉及多条sql时,我们想把这多条sql当作一个整体,一起成功一起失败。后续Spring会通过事务控制来解决这个问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值