经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 数据库/运维 » MyBatis » 查看文章
MyBatis配置文件解析与MyBatis实例演示
来源:jb51  时间:2022/4/7 10:49:35  对本文有异议

MyBatis介绍

MyBatis是一个持久层的ORM框架,使用简单,学习成本较低。可以执行自己手写的SQL语句,比较灵活。但是MyBatis的自动化程度不高,移植性也不高,有时从一个数据库迁移到另外一个数据库的时候需要自己修改配置,所以称只为半自动ORM框架

传统JDBC和Mybatis相比的弊病

传统JDBC

  1. @Test
  2. public void test() throws SQLException {
  3. Connection conn=null;
  4. PreparedStatement pstmt=null;
  5. try {
  6. // 1.加载驱动
  7. Class.forName("com.mysql.jdbc.Driver");
  8.  
  9. // 2.创建连接
  10. conn= DriverManager.
  11. getConnection("jdbc:mysql://localhost:3306/mybatis_example", "root", "123456");
  12.  
  13.  
  14. // SQL语句
  15. String sql="select id,user_name,create_time from t_user where id=?";
  16.  
  17. // 获得sql执行者
  18. pstmt=conn.prepareStatement(sql);
  19. pstmt.setInt(1,1);
  20.  
  21. // 执行查询
  22. //ResultSet rs= pstmt.executeQuery();
  23. pstmt.execute();
  24. ResultSet rs= pstmt.getResultSet();
  25.  
  26. rs.next();
  27. User user =new User();
  28. user.setId(rs.getLong("id"));
  29. user.setUserName(rs.getString("user_name"));
  30. user.setCreateTime(rs.getDate("create_time"));
  31. System.out.println(user.toString());
  32. } catch (Exception e) {
  33. e.printStackTrace();
  34. }
  35. finally{
  36. // 关闭资源
  37. try {
  38. if(conn!=null){
  39. conn.close();
  40. }
  41. if(pstmt!=null){
  42. pstmt.close();
  43. }
  44. } catch (SQLException e) {
  45. e.printStackTrace();
  46. }
  47. }
  48. }

传统JDBC的问题如下:

1.数据库连接创建,释放频繁造成西戎资源的浪费,从而影响系统性能,使用数据库连接池可以解决问题。
2.sql语句在代码中硬编码,造成代码的不已维护,实际应用中sql的变化可能较大,sql代码和java代码没有分离开来维护不方便。
3.使用preparedStatement向有占位符传递参数存在硬编码问题因为sql中的where子句的条件不确定,同样是修改不方便/
4.对结果集中解析存在硬编码问题,sql的变化导致解析代码的变化,系统维护不方便。

mybatis对传统的JDBC的解决方案

1、数据库连接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库连接池可解决此问题。
解决:在SqlMapConfig.xml中配置数据连接池,使用连接池管理数据库链接。

2、Sql语句写在代码中造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码。
解决:将Sql语句配置在XXXXmapper.xml文件中与java代码分离。

3、向sql语句传参数麻烦,因为sql语句的where条件不一定,可能多也可能少,占位符需要和参数一一对应。
解决:Mybatis自动将java对象映射至sql语句,通过statement中的parameterType定义输入参数的类型。

4、对结果集解析麻烦,sql变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成pojo对象解析比较方便。
解决:Mybatis自动将sql执行结果映射至java对象,通过statement中的resultType定义输出结果的类型。

Mybaits整体体系图

在这里插入图片描述

 

在这里插入图片描述

一个Mybatis最简单的使用例子如下:

  1. public class App {
  2. public static void main(String[] args) {
  3. String resource = "mybatis-config.xml";
  4. Reader reader;
  5. try {
  6. //将XML配置文件构建为Configuration配置类
  7. reader = Resources.getResourceAsReader(resource);
  8. // 通过加载配置文件流构建一个SqlSessionFactory DefaultSqlSessionFactory
  9. SqlSessionFactory sqlMapper = new SqlSessionFactoryBuilder().build(reader);
  10. // 数据源 执行器 DefaultSqlSession
  11. SqlSession session = sqlMapper.openSession();
  12. try {
  13. // 执行查询 底层执行jdbc
  14. //User user = (User)session.selectOne("com.tuling.mapper.selectById", 1);
  15.  
  16. UserMapper mapper = session.getMapper(UserMapper.class);
  17. System.out.println(mapper.getClass());
  18. User user = mapper.selectById(1L);
  19. System.out.println(user.getUserName());
  20. } catch (Exception e) {
  21. e.printStackTrace();
  22. }finally {
  23. session.close();
  24. }
  25. } catch (IOException e) {
  26. e.printStackTrace();
  27. }
  28. }
  29. }

mybatis-config.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  3. "http://mybatis.org/dtd/mybatis-3-config.dtd">
  4. <configuration>
  5. <!--properties 扫描属性文件.properties -->
  6. <properties resource="db.properties"></properties>
  7.  
  8.  
  9. <settings>
  10. <setting name="mapUnderscoreToCamelCase" value="true"/>
  11. </settings>
  12.  
  13. <plugins>
  14. <plugin interceptor="com.tuling.plugins.ExamplePlugin" ></plugin>
  15. </plugins>
  16.  
  17. <environments default="development">
  18. <environment id="development">
  19. <transactionManager type="JDBC"/>
  20. <!--// mybatis内置了JNDI、POOLED、UNPOOLED三种类型的数据源,其中POOLED对应的实现为org.apache.ibatis.datasource.pooled.PooledDataSource,它是mybatis自带实现的一个同步、线程安全的数据库连接池 一般在生产中,我们会使用c3p0或者druid连接池-->
  21. <dataSource type="POOLED">
  22. <property name="driver" value="${mysql.driverClass}"/>
  23. <property name="url" value="${mysql.jdbcUrl}"/>
  24. <property name="username" value="${mysql.user}"/>
  25. <property name="password" value="${mysql.password}"/>
  26. </dataSource>
  27. </environment>
  28. </environments>
  29.  
  30.  
  31.  
  32. <mappers>
  33. <!--1.必须保证接口名(例如IUserDao)和xml名(IUserDao.xml)相同,还必须在同一个包中-->
  34. <package name="com.tuling.mapper"/>
  35.  
  36. <!--2.不用保证同接口同包同名
  37. <mapper resource="com/mybatis/mappers/EmployeeMapper.xml"/>
  38.  
  39. 3.保证接口名(例如IUserDao)和xml名(IUserDao.xml)相同,还必须在同一个包中
  40. <mapper class="com.mybatis.dao.EmployeeMapper"/>
  41.  
  42. 4.不推荐:引用网路路径或者磁盘路径下的sql映射文件 file:///var/mappers/AuthorMapper.xml
  43. <mapper url="file:E:/Study/myeclipse/_03_Test/src/cn/sdut/pojo/PersonMapper.xml"/>-->
  44.  
  45. </mappers>
  46. </configuration>

总结下就是分为下面四个步骤:

  • 从配置文件(通常是XML文件)得到SessionFactory;
  • 从SessionFactory得到SqlSession;
  • 通过SqlSession进行CRUD和事务的操作;
  • 执行完相关操作之后关闭Session。

MyBatis 源码编译

1.下载mybatis源码

下载地址:https://github.com/mybatis/mybatis-3

这里写图片描述

我下载的最新的 mybatis-3-mybatis-3.4.6,下载完后解压。打开pom.xml

  1. <parent>
  2. <groupId>org.mybatis</groupId>
  3. <artifactId>mybatis-parent</artifactId>
  4. <version>30</version>
  5. <relativePath />
  6. </parent>

发现mybatis源码依赖mybatis-parent 所以编译前要先下载mybatis-parent

2.下载mybatis-parent源码

下载地址:https://github.com/mybatis/parent

这里写图片描述

下载的mybatis-parent版本要和mybatis源文件pom.xml 版本一致。

3.编译mybatis-parent源码

切换到你下载的mybatis-parent目录:

  1. mvn clean install

3.编译mybatis源码

切换到你下载的mybatis源码目录:

  1. mvn clean
  2.  
  3. mvn install -Dmaven.test.skip=true

如果出现如下错误:

这里写图片描述

打开pom.xml 文件注释掉 maven-pdf-plugin 插件

  1. <!--
  2. <plugin>
  3. <groupId>org.apache.maven.plugins</groupId>
  4. <artifactId>maven-pdf-plugin</artifactId>
  5. </plugin>
  6. -->

然后重新编译

4.导入IDEA

导入方式就不多说,按maven项目导入即可!导入成功后:

这里写图片描述

如果希望在spring源码中引入你自己的这份源码,可以做如下操作

1.修改你mybatis源码的pom的 这样可以和官方的区分开来

  1. <version>3.5.3-xsls</version>

2.这样你在spring源码中就可以引入这份mybatis源码了.

  • 如果引入mybatis-spring 同样需要做1、3步骤
  1. compile("org.mybatis:mybatis-spring:2.0.3-xsls")
  2. compile("org.mybatis:mybatis:3.5.3-xsls")

3.当然,如果你想在spring这边看到你mybatis源码相关的注释,还得在mybatis源码的pom里面加入plugin,使它生成 jar 的同时 生成 sources 包

  1. <plugin>
  2. <artifactId>maven-source-plugin</artifactId>
  3. <version>3.0.1</version>
  4. <configuration>
  5. <attach>true</attach>
  6. </configuration>
  7. <executions>
  8. <execution>
  9. <phase>compile</phase>
  10. <goals>
  11. <goal>jar</goal>
  12. </goals>
  13. </execution>
  14. </executions>
  15. </plugin>

Mybatis启动流程分析

  1. String resource = "mybatis-config.xml";
  2. //将XML配置文件构建为Configuration配置类
  3. reader = Resources.getResourceAsReader(resource);
  4. // 通过加载配置文件流构建一个SqlSessionFactory DefaultSqlSessionFactory
  5. SqlSessionFactory sqlMapper = new SqlSessionFactoryBuilder().build(reader);

通过上面代码发现,创建SqlSessionFactory的代码在SqlSessionFactoryBuilder中,进去一探究竟:

  1. //整个过程就是将配置文件解析成Configration对象,然后创建SqlSessionFactory的过程
  2. //Configuration是SqlSessionFactory的一个内部属性
  3. public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
  4. try {
  5. XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
  6. return build(parser.parse());
  7. } catch (Exception e) {
  8. throw ExceptionFactory.wrapException("Error building SqlSession.", e);
  9. } finally {
  10. ErrorContext.instance().reset();
  11. try {
  12. inputStream.close();
  13. } catch (IOException e) {
  14. // Intentionally ignore. Prefer previous error.
  15. }
  16. }
  17. }
  18. public SqlSessionFactory build(Configuration config) {
  19. return new DefaultSqlSessionFactory(config);
  20. }

下面我们看下解析配置文件过程中的一些细节。
先给出一个配置文件的例子:

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE configuration
  3. PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-config.dtd">
  5. <configuration>
  6. <!--SqlSessionFactoryBuilder中配置的配置文件的优先级最高;config.properties配置文件的优先级次之;properties标签中的配置优先级最低 -->
  7. <properties resource="org/mybatis/example/config.properties">
  8. <property name="username" value="dev_user"/>
  9. <property name="password" value="F2Fa3!33TYyg"/>
  10. </properties>
  11.  
  12. <!--一些重要的全局配置-->
  13. <settings>
  14. <setting name="cacheEnabled" value="true"/>
  15. <!--<setting name="lazyLoadingEnabled" value="true"/>-->
  16. <!--<setting name="multipleResultSetsEnabled" value="true"/>-->
  17. <!--<setting name="useColumnLabel" value="true"/>-->
  18. <!--<setting name="useGeneratedKeys" value="false"/>-->
  19. <!--<setting name="autoMappingBehavior" value="PARTIAL"/>-->
  20. <!--<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>-->
  21. <!--<setting name="defaultExecutorType" value="SIMPLE"/>-->
  22. <!--<setting name="defaultStatementTimeout" value="25"/>-->
  23. <!--<setting name="defaultFetchSize" value="100"/>-->
  24. <!--<setting name="safeRowBoundsEnabled" value="false"/>-->
  25. <!--<setting name="mapUnderscoreToCamelCase" value="false"/>-->
  26. <!--<setting name="localCacheScope" value="STATEMENT"/>-->
  27. <!--<setting name="jdbcTypeForNull" value="OTHER"/>-->
  28. <!--<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>-->
  29. <!--<setting name="logImpl" value="STDOUT_LOGGING" />-->
  30. </settings>
  31.  
  32. <typeAliases>
  33.  
  34. </typeAliases>
  35.  
  36. <plugins>
  37. <plugin interceptor="com.github.pagehelper.PageInterceptor">
  38. <!--默认值为 false,当该参数设置为 true 时,如果 pageSize=0 或者 RowBounds.limit = 0 就会查询出全部的结果-->
  39. <!--如果某些查询数据量非常大,不应该允许查出所有数据-->
  40. <property name="pageSizeZero" value="true"/>
  41. </plugin>
  42. </plugins>
  43.  
  44. <environments default="development">
  45. <environment id="development">
  46. <transactionManager type="JDBC"/>
  47. <dataSource type="POOLED">
  48. <property name="driver" value="com.mysql.jdbc.Driver"/>
  49. <property name="url" value="jdbc:mysql://10.59.97.10:3308/windty"/>
  50. <property name="username" value="windty_opr"/>
  51. <property name="password" value="windty!234"/>
  52. </dataSource>
  53. </environment>
  54. </environments>
  55.  
  56. <databaseIdProvider type="DB_VENDOR">
  57. <property name="MySQL" value="mysql" />
  58. <property name="Oracle" value="oracle" />
  59. </databaseIdProvider>
  60.  
  61. <mappers>
  62. <!--这边可以使用package和resource两种方式加载mapper-->
  63. <!--<package name="包名"/>-->
  64. <!--<mapper resource="./mappers/SysUserMapper.xml"/>-->
  65. <mapper resource="./mappers/CbondissuerMapper.xml"/>
  66. </mappers>
  67.  
  68. </configuration>

下面是解析配置文件的核心方法:

  1. private void parseConfiguration(XNode root) {
  2. try {
  3. //issue #117 read properties first
  4. //解析properties标签,并set到Configration对象中
  5. //在properties配置属性后,在Mybatis的配置文件中就可以使用${key}的形式使用了。
  6. propertiesElement(root.evalNode("properties"));
  7. //解析setting标签的配置
  8. Properties settings = settingsAsProperties(root.evalNode("settings"));
  9. //添加vfs的自定义实现,这个功能不怎么用
  10. loadCustomVfs(settings);
  11. //配置类的别名,配置后就可以用别名来替代全限定名
  12. //mybatis默认设置了很多别名,参考附录部分
  13. typeAliasesElement(root.evalNode("typeAliases"));
  14. //解析拦截器和拦截器的属性,set到Configration的interceptorChain中
  15. //MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用。默认情况下,MyBatis 允许使用插件来拦截的方法调用包括:
  16. //Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
  17. //ParameterHandler (getParameterObject, setParameters)
  18. //ResultSetHandler (handleResultSets, handleOutputParameters)
  19. //StatementHandler (prepare, parameterize, batch, update, query)
  20. pluginElement(root.evalNode("plugins"));
  21. //Mybatis创建对象是会使用objectFactory来创建对象,一般情况下不会自己配置这个objectFactory,使用系统默认的objectFactory就好了
  22. objectFactoryElement(root.evalNode("objectFactory"));
  23. objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
  24. reflectorFactoryElement(root.evalNode("reflectorFactory"));
  25. //设置在setting标签中配置的配置
  26. settingsElement(settings);
  27. //解析环境信息,包括事物管理器和数据源,SqlSessionFactoryBuilder在解析时需要指定环境id,如果不指定的话,会选择默认的环境;
  28. //最后将这些信息set到Configration的Environment属性里面
  29. environmentsElement(root.evalNode("environments"));
  30. //
  31. databaseIdProviderElement(root.evalNode("databaseIdProvider"));
  32. //无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时, 都会用类型处理器将获取的值以合适的方式转换成 Java 类型。解析typeHandler。
  33. typeHandlerElement(root.evalNode("typeHandlers"));
  34. //解析Mapper
  35. mapperElement(root.evalNode("mappers"));
  36. } catch (Exception e) {
  37. throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
  38. }
  39. }

在这里插入图片描述

上面解析流程结束后会生成一个Configration对象,包含所有配置信息,然后会创建一个SqlSessionFactory对象,这个对象包含了Configration对象。

简单总结

对于MyBatis启动的流程(获取SqlSession的过程)这边简单总结下:

  • SqlSessionFactoryBuilder解析配置文件,包括属性配置、别名配置、拦截器配置、环境(数据源和事务管理器)、Mapper配置等;解析完这些配置后会生成一个Configration对象,这个对象中包含了MyBatis需要的所有配置,然后会用这个Configration对象创建一个SqlSessionFactory对象,这个对象中包含了Configration对象;

这里解析的东西比较多,大致概况:会把所有的信息都解析到Configration对象中,比较简单不多介绍。

更多关于MyBatis配置文件解析MyBatis实例演示以及怎样编译安装MyBatis请查看下面的相关链接

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号