一、原生jdbc操作
使用jdbc进行数据库操作: 首先加载驱动driverManager,然后通过DriverManager获取数据库连接,创建statement,然后执行sql获取结果集,处理结果集,然后关闭连接。
代码语言:javascript复制@SpringBootApplication
代码语言:javascript复制public class DemoApplication {
public static void main(String[] args) throws Exception {
String url = "jdbc:mysql://127.0.0.1:3306/jdbcTest?serverTimezone=UTC";
String userName = "root";
String password = "root";
User userParam = new User();
userParam.setSchoolName("Sunny School");
// 第一步:加载驱动程序
Class.forName("com.mysql.jdbc.Driver");
// 第二步:获得数据库的连接
Connection conn = DriverManager.getConnection(url, userName, password);
// 第三步:创建语句并执行
Statement stmt = conn.createStatement();
ResultSet resultSet = stmt.executeQuery("SELECT * FROM `user` WHERE schoolName = '" userParam.getSchoolName() "';");
// 第四步:处理数据库操作结果
List<User> userList = new ArrayList<>();
while(resultSet.next()){
User user = new User();
user.setId(resultSet.getInt("id"));
user.setName(resultSet.getString("name"));
user.setEmail(resultSet.getString("email"));
user.setAge(resultSet.getInt("age"));
user.setSex(resultSet.getInt("sex"));
user.setSchoolName(resultSet.getString("schoolName"));
userList.add(user);
}
// 第五步:关闭连接
stmt.close();
for (User user : userList) {
System.out.println("name : " user.getName() " ; email : " user.getEmail());
}
}
}
二、使用mybatis执行sql操作
下面是一个mybatis的简单例子:
代码语言:javascript复制@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
// 第一阶段:MyBatis的初始化阶段
String resource = "mybatis-config.xml";
// 得到配置文件的输入流
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
} catch (IOException e) {
e.printStackTrace();
}
// 得到SqlSessionFactory
SqlSessionFactory sqlSessionFactory =
new SqlSessionFactoryBuilder().build(inputStream);
// 第二阶段:数据读写阶段
try (SqlSession session = sqlSessionFactory.openSession()) {
// 找到接口对应的实现
UserMapper userMapper = session.getMapper(UserMapper.class);
// 组建查询参数
User userParam = new User();
userParam.setSchoolName("Sunny School");
// 调用接口展开数据库操作
List<User> userList = userMapper.queryUserBySchoolName(userParam);
// 打印查询结果
for (User user : userList) {
System.out.println("name : " user.getName() " ; email : " user.getEmail());
}
}
}
}
从上面我们可以看到首先加载资源文件,然后通过资源流加载,通过创建sqlSessionBuilder来构建sqlSessionFactory。然后通过sqlSessionFactory打开session,基于打开的session获取mapper。接着操作mapper,最后关闭session。
其过程可以概括为:
mybatis流程图
获取资源文件流操作:可以看到在Resource类中获取资源配置有几种方式:
代码语言:javascript复制inputStream = Resources.getResourceAsStream(resource);
getResourceAsProperties(String resource);
getResourceAsReader(String resource);
getResourceAsFile(String resource);
getUrlAsReader(String urlString);
getUrlAsProperties(String urlString);
重点放在sqlSessionFactory上,可以从测试类中可以看到其构建的过程:
流程图:
sqlSessionFactory构建过程
测试代码:
代码语言:javascript复制//前置操作构建sqlSessionFactory
@BeforeAll
static void setup() throws Exception {
createBlogDataSource();
final String resource = "org/apache/ibatis/builder/MapperConfig.xml";
final Reader reader = Resources.getResourceAsReader(resource);
//构建sqlMapper
sqlMapper = new SqlSessionFactoryBuilder().build(reader);
}
执行SqlSessionFactory构建:执行构建,首先创建xml配置构建对象进行解析,而解析的过程中涉及到将配置解析成xnode,然后进行配置解析,最后执行构建操作,从而获取到sqlSessionFactory。
代码语言:javascript复制//sqlSessionFactory构造操作
public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
try {
//创建xml配置构建器对象
XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
//进行构建
return build(parser.parse());
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error building SqlSession.", e);
} finally {
ErrorContext.instance().reset();
try {
reader.close();
} catch (IOException e) {
// Intentionally ignore. Prefer previous error.
}
}
}
其涉及的过程:
代码语言:javascript复制//执行解析操作
public Configuration parse() {
//如果已经解析,则抛异常
if (parsed) {
throw new BuilderException("Each XMLConfigBuilder can only be used once.");
}
parsed = true;
//首先将其解析成XNode,然后解析配置
parseConfiguration(parser.evalNode("/configuration"));
return configuration;
}
执行的具体过程:调用底层的xpath操作
代码语言:javascript复制//evaluate
private Object evaluate(String expression, Object root, QName returnType) {
try {
//xpath
return xpath.evaluate(expression, root, returnType);
} catch (Exception e) {
throw new BuilderException("Error evaluating XPath. Cause: " e, e);
}
}
执行解析配置:
代码语言:javascript复制//解析配置
private void parseConfiguration(XNode root) {
try {
// issue #117 read properties first
//配置元素
propertiesElement(root.evalNode("properties"));
//setting配置
Properties settings = settingsAsProperties(root.evalNode("settings"));
//加载自定义vfs
loadCustomVfs(settings);
//加载自定义log实现
loadCustomLogImpl(settings);
//类型别名元素
typeAliasesElement(root.evalNode("typeAliases"));
//插件元素
pluginElement(root.evalNode("plugins"));
//对象工厂元素
objectFactoryElement(root.evalNode("objectFactory"));
//对象包装工厂元素
objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
//反射工厂元素
reflectorFactoryElement(root.evalNode("reflectorFactory"));
//setting元素
settingsElement(settings);
// read it after objectFactory and objectWrapperFactory issue #631
//环境元素
environmentsElement(root.evalNode("environments"));
//databaseId提供者元素
databaseIdProviderElement(root.evalNode("databaseIdProvider"));
//类型处理器元素
typeHandlerElement(root.evalNode("typeHandlers"));
//映射元素
mapperElement(root.evalNode("mappers"));
} catch (Exception e) {
throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " e, e);
}
}
解析获取了sqlSessionFactory对象,从而通过openSqlSession获取sqlSession对象,而通过sqlSession这个对象,就可以执行查询操作。
执行查询的流程:
首先通过默认的sqlSessionFactory可以拿到执行器executor、配置信息和事务,然后通过指向query操作,首先会去缓存执行器中进行查询,如果有,则进行返回,如果没有,则执行查询操作,然后在查询的过程中将结果返回的同时,将缓存信息写入到缓存中。
sqlsession操作过程
从mabatis的源码测试中可以看到:
代码语言:javascript复制@Test
void shouldSelectAllAuthors() {
try (SqlSession session = sqlMapper.openSession(TransactionIsolationLevel.SERIALIZABLE)) {
List<Author> authors = session.selectList("org.apache.ibatis.domain.blog.mappers.AuthorMapper.selectAllAuthors");
assertEquals(2, authors.size());
}
}
执行的过程可以通过上面的列子可以进行追踪。除了这些,还有很多值得我们去学习的地方。