Mybatis入门基础篇

Mybatis有什么用

Mybatis是一个ORM(Object Relational Mapper/对象相关映射)框架,可同时支持多数据源,通过封装JDBC,提供了对象和记录的转换,连接数据库,以及完成记录在数据库的操作。

使用

注意

由于springboot的出现,配置文件可以不写了,这里留下只是为了后续Configuration解析不抽象。

Mybatis的配置文件

1 数据源
通过environment,可以配置多个数据源,并且可以指定默认数据源
如果sql语句不想走默认数据源,需要在sql语句上注明数据源的选择
2 别名
提供了实体类的别名,这样在Mapper中使用时就不需要写全限定名了
3 Mapper文件位置
Mapper文件是sql语句的具体放置位置,通过文件位置,Mybatis可以找到所有Mapper文件
以下是网上随便找的一个demo

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>


  <!-- 默认使用的环境 ID(比如:default="development")
  也就是说我们可以配置多套<environment>环境-->
  <environments default="development">
    <!--
       每个 environment 元素定义的环境 ID
       -->
    <environment id="development">
      <!--
          transactionManager 事务管理器
          type的值有JDBC和MANAGED
              JDBC – 这个配置直接使用了 JDBC 的提交和回滚设施,它依赖从数据源获得的连接来管理事务作用域。
      -->
      <transactionManager type="JDBC"/>
      <!--
        dataSourcedataSource 数据源 dbcp c3p0 druid
        type="[UNPOOLED|POOLED|JNDI]"
        POOLED意思有连接池的连接
        UNPOOLED意思没有连接池的连接
        -->
      <dataSource type="POOLED">
        <!--                JDBC 驱动-->
        <property name="driver" value="${driver}"/>
        <!--                url数据库的 JDBC URL地址。-->
        <property name="url" value="${url}"/>
        <property name="username" value="${username}"/>
        <property name="password" value="${password}"/>

        <!--            defaultTransactionIsolationLevel – 默认的连接事务隔离级别。&ndash;&gt;-->
        <!--            <property name="defaultTransactionIsolationLevel" value=""/>-->

        <!--            defaultNetworkTimeout – 等待数据库操作完成的默认网络超时时间(单位:毫秒)&ndash;&gt;-->
        <!--            <property name="efaultNetworkTimeout" value=""/>-->

      </dataSource>
    </environment>
  </environments>

  <mappers>
    <!-- 使用相对于类路径的资源引用 -->
    <!--        <mapper resource="asia/xiaojiang/mybatis03/dao/UserMapper.xml"/>-->
    <!-- 使用完全限定资源定位符(URL)
    不推荐使用
    <mapper url="E:\JetBrains\mybatis学习\Mybatis-study\Mybatis-03\src\main\java\asia\xiaojiang\mybatis03\dao\UserMapper.xml"/>
    -->

    <!-- 使用映射器接口实现类的完全限定类名
     使用注意点:
        接口和其配置文件必须同名, 必须在同一个包下
     -->
    <mapper class="asia.xiaojiang.mybatis03.dao.UserMapper"/>
    <!-- 将包内的映射器接口实现全部注册为映射器
    使用包扫描注意点:
        接口和其配置文件必须同名, 必须在同一个包下
    -->
    <!--        <package name="asia.xiaojiang.mybatis03.dao"/>-->
  </mappers>

</configuration>

Mybatis操作基本步骤

1 创建表
2 创建实体类
3 创建DAO接口类,定义需要的sql操作接口
4 创建Mapper文件,命名空间指向DAO接口类

使用之下

Mybatis的实质

提供缓存与其它机制,使用XpathParser作为XML读取工具,读取XML,初始化数据,并使用完成SqlSession的创建,调用SqlSession通过JDBC完成底层数据库查询

//首先读取并解析xml文件,把xml内容加载进工厂
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

//使用工厂生成自带属性的数据库连接
SqlSession sqlSession = sqlSessionFactory.openSession();

//JDK动态代理技术,动态生成一个UserDao接口的实现类
UserDAO userDAO = sqlSession.getMapper(UserDAO.class);
List<User> users = userDAO.queryAllUsers();

初始化数据结构

配置类Configuration

Mybatis在一开始就完成静态文件的读取。
org.apache.ibatis.session.Configuration是mybatis-config.xml和里面指向的Mapper的对象封装型。
除了初始化变量,它还定义了connection,statement,resultset的实例化方法
以下是它所有完成的初始化变量

	//配置类的数据源信息保存
	protected Environment environment;

	//配置类其它setting
    protected boolean safeRowBoundsEnabled;
    protected boolean safeResultHandlerEnabled;
    protected boolean mapUnderscoreToCamelCase;
    protected boolean aggressiveLazyLoading;
    protected boolean multipleResultSetsEnabled;
    protected boolean useGeneratedKeys;
    protected boolean useColumnLabel;
    protected boolean cacheEnabled;
    protected boolean callSettersOnNulls;
    protected boolean useActualParamName;
    protected boolean returnInstanceForEmptyRow;
    protected boolean shrinkWhitespacesInSql;
    protected boolean nullableOnForEach;

    protected String logPrefix;
    protected Class<? extends Log> logImpl;
    protected Class<? extends VFS> vfsImpl;
    protected Class<?> defaultSqlProviderType;
    protected LocalCacheScope localCacheScope;
    protected JdbcType jdbcTypeForNull;
    protected Set<String> lazyLoadTriggerMethods;
    protected Integer defaultStatementTimeout;
    protected Integer defaultFetchSize;
    protected ResultSetType defaultResultSetType;
    protected ExecutorType defaultExecutorType;
    protected AutoMappingBehavior autoMappingBehavior;
    protected AutoMappingUnknownColumnBehavior autoMappingUnknownColumnBehavior;
    protected Properties variables;
    protected ReflectorFactory reflectorFactory;
    protected ObjectFactory objectFactory;
    protected ObjectWrapperFactory objectWrapperFactory;
    protected boolean lazyLoadingEnabled;
    protected ProxyFactory proxyFactory;
    protected String databaseId;
    protected Class<?> configurationFactory;
	//配置类的Mapper信息保存
    protected final MapperRegistry mapperRegistry;
    protected final InterceptorChain interceptorChain;
    protected final TypeHandlerRegistry typeHandlerRegistry;
	//配置类的实体类别名设置
    protected final TypeAliasRegistry typeAliasRegistry;
    protected final LanguageDriverRegistry languageRegistry;

    //与mapper有关
    protected final Map<String, MappedStatement> mappedStatements;
    protected final Map<String, Cache> caches;
	//resultMap和parameterMap的承装,String为DAO全限定名+sql的id来保证唯一
    protected final Map<String, ResultMap> resultMaps;
    protected final Map<String, ParameterMap> parameterMaps;

    protected final Map<String, KeyGenerator> keyGenerators;
    protected final Set<String> loadedResources;
    protected final Map<String, XNode> sqlFragments;
    protected final Collection<XMLStatementBuilder> incompleteStatements;
    protected final Collection<CacheRefResolver> incompleteCacheRefs;
    protected final Collection<ResultMapResolver> incompleteResultMaps;
    protected final Collection<MethodResolver> incompleteMethods;
    protected final Map<String, String> cacheRefMap;

Mapper的sql信息承装

MappedStatement用来承装单条sql的信息

	private String resource;
	//拥有一个指回的Configuration
    private Configuration configuration;
    private String id;
    private Integer fetchSize;
    private Integer timeout;
	//分为callable(存储过程使用),prepared(prepareStatement),statement,
    private StatementType statementType;
    private ResultSetType resultSetType;
    private SqlSource sqlSource;
    private Cache cache;
    private ParameterMap parameterMap;
    private List<ResultMap> resultMaps;
    private boolean flushCacheRequired;
    private boolean useCache;
    private boolean resultOrdered;
    private SqlCommandType sqlCommandType;
    private KeyGenerator keyGenerator;
    private String[] keyProperties;
    private String[] keyColumns;
    private boolean hasNestedResultMaps;
    private String databaseId;
    private Log statementLog;
    private LanguageDriver lang;
    private String[] resultSets;

执行过程

初始化信息的加载

在new SqlSessionFactoryBuilder().build(inputStream)中,不仅完成了对mybatis-config.xml的解析,同时完成了其中mapper的解析。在这个方法中,mybatis-config.xml被解析为了Configuration,mapper.xml被解析为了MappedStatement,作为SqlSessionFactory的初始属性。

XML解析工具

使用了XpathParser,将XML标签解析为一个个XNode节点,并提供eval作为节点目录的访问,比如eval(“/*”)会返回所有XML一级标签

代理的封装

userDAO.queryAllUsers()实际上是对sqlSession.selectList(“com.baizhiedu.dao.UserDAO.queryAllUsers”)的封装。
之所以使用了代理模式封装,是因为表达概念更清晰,使用了对象,既方便查看,有条理清晰,好过字符串 ,而且在编程上方便很多。
userDAO.queryAllUsers()的调用中,实际上会使用invokeHandler的方法,根据userDao全限定名+方法名作为key,去查询Configuration中MappedStatements,获取对应XML中对应方法的各种标签参数,外层只是一个空实现。

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    try {
        return Object.class.equals(method.getDeclaringClass()) ? method.invoke(this, args) : this.cachedInvoker(method).invoke(proxy, method, args, this.sqlSession);
    } catch (Throwable var5) {
        throw ExceptionUtil.unwrapThrowable(var5);
    }
}

SqlSession底层调用

SqlSession是一次对数据库的Connection,它屏蔽了下层的具体实现,只提供了类似select,update,insert这样的接口,给上层反复调用。
以下是SqlSession提供的操作接口
d959be687ffdf2637c47f20c6221f17.png
在SqlSession创建时,就会根据ExecType创建自己独有的Excecutor
Executor主要任务是,完成sql执行,完成事务提交与回滚操作,完成sql缓存的保存
Executor是经典的模板模式,BaseExecutor实现了Executor接口,在增删查改的方法中实现了对一级缓存的更新,并留下抽象方法等子类来实现。SimpleExecutor,ReuseExecutor,BatchExecutor都是它的实现类。
StatementHandler是Executor内部用于完成sql执行的工具,它有着具体sql参数ParameterHandler和承装结果的结果集ResultSetHandler。
TypeHandler不从属于某一个Executor,它提供Java和数据库类型的转化,比如Java的int和数据库的int
1677577913599.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值