(十)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對象)

相關文章
相關標籤/搜索