Spring基础-整合持久层

1、为什么要整合持久层

持久层是帮助我们对数据库进行操作的

常见的持久层框架有:

  • JDBC
  • Hibernate
  • MyBatis

但是这三个持久层技术有大量的代码重复

2、Spring整合MyBatis

Spring对MyBatis进行了代码封装,简便我们的开发过程过程

MyBatis的开发步骤

  1. 实体
  2. 实体别名
  3. 创建Dao接口
  4. 创建Mapper文件
  5. 注册Mapper文件
  6. MyBatisAPI调用

下面,我们通过代码来演示一遍

添加依赖

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-jdbc</artifactId>
	<version>5.1.4.RELEASE</version>
</dependency>

<dependency>
	<groupId>com.alibaba</groupId>
	<artifactId>druid-spring-boot-starter</artifactId>
	<version>1.1.9</version>
</dependency>
<dependency>
	<groupId>org.mybatis</groupId>
	<artifactId>mybatis-spring</artifactId>
	<version>1.3.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
	<version>5.1.40</version>
</dependency>

<dependency>
	<groupId>org.mybatis</groupId>
	<artifactId>mybatis</artifactId>
	<version>3.5.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-context</artifactId>
	<version>5.1.4.RELEASE</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-web</artifactId>
	<version>5.1.4.RELEASE</version>
</dependency>

<!-- slf4j日志 -->
<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>slf4j-log4j12</artifactId>
	<version>1.7.25</version>
</dependency>
<dependency>
	<groupId>log4j</groupId>
	<artifactId>log4j</artifactId>
	<version>1.2.17</version>
</dependency>

编写实体类

public class User {

    private Integer id;
    private String name;
    private String password;

    public User(Integer id, String name, String password) {
        this.id = id;
        this.name = name;
        this.password = password;
    }

    public User() {
    }

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

编写实体别名

<?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>
        <!--为了后面书写mapper的时候不需要再重复写全限定名-->
        <typeAlias alias="user" type="com.wx.mybatis.entity.User"></typeAlias>
    </typeAliases>
</configuration>

创建表

创建Dao接口

public interface UserDao {
    
    public void save(User user);
}

创建Mapper文件

<?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.chenxin.spring5.mybatis.dao.UserDao">
    <insert id="save" parameterType="user">
        insert into t_user(name, password) values (#{name}, #{password})
    </insert>
</mapper>

注册Mapper文件

<?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>
        <!--为了后面书写mapper的时候不需要再重复写全限定名-->
        <typeAlias alias="user" type="com.wx.mybatis.entity.User"></typeAlias>
    </typeAliases>
    
    <environments default="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"></property>
                <property name="url" value="jdbc:mysql://localhost:3306/users?useSSL=false"></property>
                <property name="username" value="root"></property>
                <property name="password" value="root"></property>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="mapper/UserMapper.xml"></mapper>
    </mappers>
</configuration>

调用MyBatisAPI测试

public class TestMyBatis {

    public static void main(String[] args) throws IOException {
        //获取文件流
        InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
        //创建sqlsessionFactory工厂对象
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
        //得到会话对象
        SqlSession sqlSession = factory.openSession();

        //获取mapper对象
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        User user = new User("wx", "123");

        mapper.save(user);
        //执行完需要提交事务
        sqlSession.commit();

    }
}

注意的坑:lineNumber:1 columnNumber:1 前言中不允许有内容

有两种情况:

3、MyBatis开发存在的问题

重复的代码非常多

  1. 实体
  2. 实体别名
  3. 创建Dao接口
  4. 创建Mapper文件
  5. 注册Mapper文件
  6. MyBatisAPI调用

第二步,编写实例别名,是十分繁琐且复杂的一个操作。我们除了名称不一样,其他的基本都一样。

<typeAliases>
	<!--为了后面书写mapper的时候不需要再重复写全限定名-->
	<typeAlias alias="user" type="com.wx.mybatis.entity.User"></typeAlias>
	<typeAlias alias="user1" type="com.wx.mybatis.entity.User1"></typeAlias>
	<typeAlias alias="user2" type="com.wx.mybatis.entity.User2"></typeAlias>
	...
</typeAliases>

随着我们的项目越来越大,实体类越来越多,每一个实体类对应一个别名。这样写,显然是不可取的,而且还很容易漏掉注册mapper文件

第六步,注册mapper文件也是一样

<mappers>
	<mapper resource="UserMapper.xml"></mapper>
	<mapper resource="UserMapper1.xml"></mapper>
	<mapper resource="UserMapper2.xml"></mapper>
	...
</mappers>

第七步,调用MyBatis的API也有很多重复的代码

为了执行自己的业务逻辑,我们这几行代码是不是每个业务逻辑都需要写一遍呢?这也太麻烦了吧

//获取文件流
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
//创建sqlsessionFactory工厂对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
//得到会话对象
SqlSession sqlSession = factory.openSession();
//获取mapper对象
UserDao mapper = sqlSession.getMapper(UserDao.class);

只有最后获取mapper对象的时候不同,根据传入的类文件,获取到对应的mapper文件

Spring整合MyBatis的核心就是减少我们的第二步、第六步、第七步的代码重复

4、Spring整合MyBatis思路做法

Spring真核MyBatis的整合,其实是对这段代码的封装

//获取文件流
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
//创建sqlsessionFactory工厂对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
//得到会话对象
SqlSession sqlSession = factory.openSession();
//获取mapper对象
UserDao mapper = sqlSession.getMapper(UserDao.class);

前两行是通过文件流创建出来SqlSessionFactory工厂对象,那么这个对象直接交由Spring来进行管理,<baean id='sqlSessionFactoryBean' class='SqlSessionFactoryBean全类路径'></bean>

第一行是读取配置文件,然后根据配置创建我们的工厂对象,既然spring现在管理了工厂对象,我们只需要将配置注入到对象中即可。

配置文件中主要是三部分:

  1. typeAliases别名
  2. dataSource数据源
  3. mappers文件

整合之前,需要先添加几个maven坐标

<dependency>
	<groupId>com.alibaba</groupId>
	<artifactId>druid-spring-boot-starter</artifactId>
	<version>1.1.9</version>
</dependency>
<dependency>
	<groupId>org.mybatis</groupId>
	<artifactId>mybatis-spring</artifactId>
	<version>1.2.2</version>
</dependency>
<!-- slf4j日志 -->
<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>slf4j-log4j12</artifactId>
	<version>1.7.25</version>
</dependency>
<dependency>
	<groupId>log4j</groupId>
	<artifactId>log4j</artifactId>
	<version>1.2.17</version>
</dependency>

Log4j的配置文件

resources # resources⽂件夹根⽬录下
### ### 配置根
log4j.rootLogger = debug,console
### ### ⽇志输出到控制台显示
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Target=System.out
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n

既然是SqlSessionFactory工厂对象的依赖,我们可以将他作为属性,注入进来

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--    连接池-->
    <bean id="dataSource"
          class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver">
        </property>
        <property name="url" value="jdbc:mysql://localhost:3306/users?useSSL=false"></property>
        <property name="username" value="root"></property>
        <property name="password" value="527713"></property>
    </bean>
    <!--创建SqlsessionFactoryBean-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <!--        执行实体对应的包-->
        <property name="typeAliasesPackage" value="com.wx.mybatis.entity"></property>
        <property name="mapperLocations">
            <list>
                <value>classpath:mapper/*Mapper.xml</value>
            </list>
        </property>
    </bean>
</beans>

前面两行,Spring通过注入的方式来帮我们管理,再来看看后面两行

//得到会话对象
SqlSession sqlSession = factory.openSession();
//获取mapper对象
UserDao mapper = sqlSession.getMapper(UserDao.class);

我们可以通过SqlSessionFactoryBean工厂对象创建除了SqlSessionFactory对象,我们只需要在获取SqlSession对象和Dao接口的class。这样我们就可以使用依赖,将我们需要的这两个对象依赖进来,spring为我们提供了一个对象,叫MapperScannerConfigure

<bean id="scanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
	<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
	<!--设置dao所在的包路径-->
	<property name="basePackage" value="com.wx.mybatis.entity"></property>
</bean>

这个MapperScannerConfigure类最后帮我们创建好了dao对象,我们只需要ctx.getBean("beanid")即可,他是采用的驼峰命名

5、Spring和MyBatis整合开发步骤

去掉上面的开发步骤,我们只剩下以下的步骤:

  • 实体
  • 创建Dao接口
  • 创建Mapper文件

其实这里的实体和表,我们也是无法省略的。spring整合mybatis的完整配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--    连接池-->
    <bean id="dataSource"
          class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver">
        </property>
        <property name="url" value="jdbc:mysql://localhost:3306/users?useSSL=false"></property>
        <property name="username" value="root"></property>
        <property name="password" value="527713"></property>
    </bean>
    <!--创建SqlsessionFactoryBean-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <!--        执行实体对应的包-->
        <property name="typeAliasesPackage" value="com.wx.mybatis.entity"></property>
        <property name="mapperLocations">
            <list>
                <value>classpath:mapper/*Mapper.xml</value>
            </list>
        </property>
    </bean>

    <bean id="scanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
        <!--设置dao所在的包路径-->
        <property name="basePackage" value="com.wx.mybatis.entity"></property>
    </bean>
</beans>

其实我们的创建dao接口,就是我们之前经常使用ctx.getBean()获取到的,下面我们来测试下

6、Spring和MyBatis整合细节

在我们还没有整合spring的时候,我们的是使用sqlSession手动sqlSession.commit();提交事务的

2021-04-27 22:00:06 DEBUG SpringManagedTransaction:89 - JDBC Connection [com.mysql.jdbc.JDBC4Connection@366ef90e] will not be managed by Spring

控制台的这个信息告诉我们,事务不会被spring进行管理,那么到底是谁在帮助我们管理事务呢?

事务不是由MbBatis来控制的,因为我们没有执行commit()操作;Spring也告诉我们,事务不是有它来控制的。

其实我们的事务是由连接池来控制的。Connection.setAutoCommit(ture);来控制事务自动提交。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值