參考:html
SqlSessionFactory和SqlSession的介紹和運用mysql
SqlSessionFactoryBean 源碼解析spring
Java中JDBC的使用
使用JDBC
的步驟包括安全
-
設置好數據庫的url,用戶名,密碼等常量mybatis
-
加載驅動類,例如
MySQL
的com.mysql.cj.jdbc.Driver
。app加載
com.mysql.cj.jdbc.Driver
時會執行此驅動類靜態代碼塊java.sql.DriverManager.registerDriver(new Driver());
,將驅動註冊進DriverManager
框架 -
使用
Driver
或DriverManager
建立Connection
對象 -
使用
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
對象 - 用
SqlSessionFactoryBuilder
的build()
方法建立。這個方法被重載屢次,其核心是將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
爲例)使用FactoryBean
爲UserMapper
接口建立一個聲明類型是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
對象)