(十)Spring与持久化(MyBatis)

参考:html

Mybatis初始化流程及其重要的几个类java

SqlSessionFactory和SqlSession的介绍和运用mysql

SqlSessionFactoryBean 源码解析spring

@Mapper和@MapperScan的区别sql

Spring整合Mybatis原理数据库

Java中JDBC的使用

使用JDBC的步骤包括安全

  1. 设置好数据库的url,用户名,密码等常量mybatis

  2. 加载驱动类,例如MySQLcom.mysql.cj.jdbc.Driverapp

    加载com.mysql.cj.jdbc.Driver时会执行此驱动类静态代码块java.sql.DriverManager.registerDriver(new Driver());,将驱动注册进DriverManager框架

  3. 使用DriverDriverManager建立Connection对象

  4. 使用Connection对象控制事务是否自动提交,手动提交,回滚或建立Statement对象执行sql语句

MyBatis

MyBatis的初始化和简单使用

下述代码完成了 将mybatis的xml配置文件加载到Conguration对象中,建立SqlSessionFactory对象,建立SqlSession对象,调用指定mapper中的方法完成一次数据库查询

String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
List list = sqlSession.selectList("com.foo.bean.BlogMapper.queryAllBlogInfo");

Configuration类的结构和mybatis的xml配置文件的结构是一一对应的

SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
    try {
        // 此对象用于解析
        XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
        // parser.parse()实现将mybatis的xml配置文件解析到Java中的Configuration对象,并返回此对象
        return build(parser.parse());
    } catch (Exception e) {
        throw ...
    } finally {
        ErrorContext.instance().reset();
        try {
            inputStream.close();
        } catch (IOException e) {
            // Intentionally ignore. Prefer previous error.
        }
    }
}

// 建立并返回一个DefaultSqlSessionFactory对象
public SqlSessionFactory build(Configuration config) {
    return new DefaultSqlSessionFactory(config);
}

上述使用mybatis的过程当中,将解析mybatis配置文件的流程封装到了SqlSessionFactoryBuilder.build()方法内部

咱们也可使用重载方法,将Configuration对象做为参数传入build方法,并显式解析配置文件

String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
// 手动建立XMLConfigBuilder,并解析建立Configuration对象
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, null,null);
Configuration configuration=parse();
// 使用Configuration对象建立SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
// 使用MyBatis
SqlSession sqlSession = sqlSessionFactory.openSession();
List list = sqlSession.selectList("com.foo.bean.BlogMapper.queryAllBlogInfo");

SqlSessionFactory

SqlSessionFactory的做用

SqlSessionFactory是个单个数据库映射关系通过编译后的内存镜像。每个MyBatis的应用程序都以一个SqlSessionFactory对象的实例为核心。SqlSessionFactory提供建立SqlSession对象的方法

SqlSessionFactory的建立方式

  • 直接new一个对象,并为它配置所须要的Configuration对象
  • SqlSessionFactoryBuilderbuild()方法建立。这个方法被重载屡次,其核心是将mybatis的xml文件解析到Configuration对象中,在此基础上建立一个SqlSessionFactory对象

SqlSessionFactory的线程安全性

SqlSessionFactory是线程安全的,SqlSessionFactory一旦被建立,应该在应用执行期间都存在。在应用运行期间不要重复建立屡次,建议使用单例模式,SqlSessionFactory是建立SqlSession的工厂

SqlSession

SqlSession的做用

SqlSession是执行持久化操做的对象。相似于JDBC中的Connection

SqlSession的实现

SqlSession接口提供CURD方法和对事务的管理方法和获取mapper代理对象的方法,它底层封装了JDBC

SqlSession的线程安全性

它是应用程序与持久层之间执行交互的一个单线程对象。每一个线程都应该有本身的SqlSession实例。SqlSession的实例不能被共享,同时SqlSession也是线程不安全的

Spring整合MyBatis的工做原理

SqlSessionFactoryBean

SqlSessionFactoryBean的定义信息常常这样使用

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <!-- 指定mybatis全局配置文件的位置 -->
    <property name="configLocation" value="classpath:mybatis-config.xml"/>
    <!-- 指定数据源 -->
    <property name="dataSource" ref="pooledDataSource"/>
    <!-- 指定mybatis,mapper文件的位置 -->
    <property name="mapperLocations" value="classpath:mapper/*.xml"/>
</bean>

SqlSessionFactoryBean类实现了InitializingBean接口。调用其afterPropertiesSet()方法时建立SqlSessionFactory对象并赋给成员变量this.sqlSessionFactory

Spring IoC整合MyBatis

Spring项目中使用MyBatis后是这样使用的

@Component
public class UserService {
    @Autowired
    private UserMapper userMapper;

    public User getUserById(Integer id) {
        return userMapper.selectById(id);
    }
}

咱们关注的就是Spring IoC是怎么将UserMapper这个接口实例化并添加到容器中的

解决方案:(以UserMapper为例)使用FactoryBeanUserMapper接口建立一个声明类型是UserMapper,实际类型是动态代理的对象

并将对象添加到容器中

可是自定义的XxxMapper是你本身写的,是不肯定的。框架不会为每一个XxxMapper建立一个XxxFactoryBean,因此这个FactoryBean持有一个成员变量,保存它将要建立的对象的类型。以此作到建立各类Mapper类的代理对象

Spring整合MyBatis的项目中,这个FactoryBean就是MapperFactoryBean

如今还有一个问题,每一个Mapper都要有一个MapperFactoryBean。那MapperFactoryBean在哪里被建立?

MapperFactoryBean@MapperScan来实现

@Import(MapperScannerRegistrar.class)
public @interface MapperScan {
    String[] basePackages() default {};
    ...
}

@MapperScan的做用是向容器中添加一个MapperScannerRegistrar对象,并记录须要被扫描的包

这些包下的XxxMapper将会被MapperScannerRegistrar扫描到并为其建立一个MapperFactoryFactoryBean类型的BeanDefinition对象)

相关文章
相关标签/搜索