参考: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
对象)