我们再来看看MyBatis使用流程:
InputStream inputStream = Resources.getResourceAsStream("myBatis_config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession();
User user = new User();
user.setUser_name("abd");
user.setUser_id(99);
user.setPassword("12345");
UserDao userDao = session.getMapper(UserDao.class);
上一篇我们搞清楚了MyBatis通过动态代理创建Dao接口的实现类,关注点在后面一句代码,动态代理底层是调用SqlSession的方法实现数据库操作。那么SqlSession是怎么创建的呢?
接下来我们来解决这个问题。
将目光放在这几句代码上:
InputStream inputStream = Resources.getResourceAsStream("myBatis_config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession();
第一句代码非常明显:通过IO方式打开输入流读取myBatis_config.xml和Mapper.xml文件。
那么读取到虚拟机之后是怎么处理xml文件的呢,还是通过标签和字符串的形式展现的吗?一定不是的。一切皆对象!MyBatis将这些标签形式的信息封装成对象进行保存。这个将xml文件映射成对象的过程叫做OXM(Obiect XML Mapping)。
第二行代码就是执行这个过程:具体来说SqlSessionFactoryBuilder().build(inputStream);有俩个作用:
- 读取xml文件:将myBatis的xml文件解析映射成Configuration对象;将Mapper.xml文件映射成MappedStatement对象同时放入Configuration对象。
- 创建SqlSesisonFactory。
接下来我们来研究这个过程:
SqlSessionFactoryBuilder().build()方法探究
XML文件封装成对象的过程
整个过程有专门的技术实现:XML解析。主要有三种方式:DOM,SAX,XPath。MyBatis通过XPath进行实现。具体来说封装了XNode和XPathParser来进行实现
import org.apache.ibatis.parsing.XNode;
import org.apache.ibatis.parsing.XPathParser;
接下来我们将使用这俩个类来将一个XML文件映射成一个对象:
自定义映射一个XML文件
要解析的XML文件:
<users>
<user>
<name>sy</name>
<password>123</password>
</user>
<user>
<name>curry</name>
<password>30</password>
</user>
</users>
要映射的对象的实体类:
package com.example.spring_suns.XPathParser;
/**
* @ClassName User
* @Description 测试MyBatis XML解析的实体类
* @Author 86153
* @Date 2024/5/31 11:08
* @Version 1.0
**/
public class User {
private String name;
private String password;
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", password='" + password + '\'' +
'}';
}
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;
}
}
具体映射过程:
/**
* @ClassName XMLParserTest
* @Description OXM过程
* @Author 86153
* @Date 2024/5/31 11:04
* @Version 1.0
**/
public class XMLParserTest {
@Test
void xpathParsertest() throws IOException {
InputStream inputStream = Resources.getResourceAsStream("users.xml");
XPathParser xPathParser = new XPathParser(inputStream);
// /users是目标xml文件的根标签,/*表示根标签下的所有子标签
List<XNode> xNodes = xPathParser.evalNodes("/users/*");
List<User> users = new ArrayList<>();
for(XNode xNode : xNodes) {
List<XNode> children = xNode.getChildren();
User user = new User();
user.setName(children.get(0).getStringBody());
user.setPassword(children.get(1).getStringBody());
users.add(user);
}
for (User user : users) {
System.out.println(user);
}
}
}
MyBatis将MyBatis的XML配置文件映射成Configuration对象的过程
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream)
SqlSessionFactory的build方法将XML配置文件解析封装成对象:
我们一步一步进行往下调试:
将Mapper.xml映射成MapperedStatement过程:
上面在读取标签MyBatis配置文件标签时读取了一个“mappers”标签,这是Mapper.xml文件的注册信息,由此读取Mapper.xml文件
创建SqlSessionFactory:
我们刚才关注的是build方法里的parse方法,现在来关注创建SqlSessionFactory的build方法
可以发现,最后通过Configuration对象创建了DefaultSqlSesisonFactory
SqlSession创建
接下来终于到我们最终的目的:创建SqlSession:
SqlSession session = sqlSessionFactory.openSession();
注意上面创建SqlSession时有一个参数Executor,这个类是SqlSession执行数据库操作的实现类
由此和我们上一篇内容连起来了,MyBatis通过jdk动态代理创建Dao接口实现类,代理调用SqlSession的数据库操作,而SqlSession操作数据库的具体实现类就是Executor
总结:
本篇文章实际上就是围绕三行代码:
InputStream inputStream = Resources.getResourceAsStream("myBatis_config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession();
第一行代码:通过IO方式打开输入流读取myBatis_config.xml和Mapper.xml文件。
第二行代码:
1.OXM。将MyBatis的xml配置文件映射成Configuration对象,将Mapper.xml文件映射成MapperedStatement对象同时封装在Configuration对象中。
2.通过Configuration对象创建SqlSessionFactory。
第三行代码:创建SqlSession。