SSM-Mybatis篇

SSM中的Mybatis篇(1):

Mybatis是针对数据库进行操作的一个框架,基于jdbc产生的一个便捷的操作数据库的框架,底层是对jdbc进行封装,简化操作数据库的操作量。

Mybatis针对数据库进行操作的两种方式分别是

  1. 通过对主配置文件的解析,解析出配置文件中的数据,连接数据库。然后解析配置文件中的sql语句,通过sql语句对数据可进行增删改查,完成对数据库的操作

  2. 通过注解的形式解析出sql语句,再对数据库进行操作

这两种方式原理都是相同的,通过对主配置文件的解析来连接数据库,然后通过xml文件或者注解得到sql语句

这里我们先分析通过解析xml文件操作数据库的方式,首先在主配置文件SqlMapConfig.xml中配置连接数据库的数据库,username,password等…

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gTcv4apb-1597062842773)(C:\Users\cgw\AppData\Roaming\Typora\typora-user-images\image-20200804105303177.png)]

然后再配置持久层Dao层接口的xml文件(这里数据库的实体类自行编写)注意:Mybatis在resource资源中的xml配置文件,必须和dao接口的包结构一致

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K2rYbt2q-1597062842781)(C:\Users\cgw\AppData\Roaming\Typora\typora-user-images\image-20200804105103246.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Nez3LsYi-1597062842789)(C:\Users\cgw\AppData\Roaming\Typora\typora-user-images\image-20200804111003002.png)]

编写到这里,我们就不用编写dao层的实现类了,因为Mybatis通过代理类的方式内部生成代理类,大致的步骤就完成了

接下来就可以先读取主配置文件,

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CV6X8Kik-1597062842803)(C:\Users\cgw\AppData\Roaming\Typora\typora-user-images\image-20200804110812093.png)]

写到这里就完成了我们对数据库查找所有的功能,到这里我们对于SqlSession和SqlSessionFactory的用途还不是很了解,下面看一下SqlSession和SqlSessionFactory的代码

SqlSession:

public interface SqlSession extends Closeable {
    //以上时查询方法的接口
    <T> T selectOne(String var1);
    <T> T selectOne(String var1, Object var2);
    <E> List<E> selectList(String var1);
    <E> List<E> selectList(String var1, Object var2);
    <E> List<E> selectList(String var1, Object var2, RowBounds var3);
    <K, V> Map<K, V> selectMap(String var1, String var2);
    <K, V> Map<K, V> selectMap(String var1, Object var2, String var3);
    <K, V> Map<K, V> selectMap(String var1, Object var2, String var3, RowBounds var4);
    void select(String var1, Object var2, ResultHandler var3);
    void select(String var1, ResultHandler var2);
    void select(String var1, Object var2, RowBounds var3, ResultHandler var4);
    //增
    int insert(String var1);
    int insert(String var1, Object var2);
    int update(String var1);
    int update(String var1, Object var2);
    //删
    int delete(String var1);
    int delete(String var1, Object var2);
    //事务提交
    void commit();
    void commit(boolean var1);
    //事务回滚
    void rollback();
    void rollback(boolean var1);
    List<BatchResult> flushStatements();
    void close();
    void clearCache();
    Configuration getConfiguration();
    <T> T getMapper(Class<T> var1);
    Connection getConnection();
}

这样看来SqlSession就是数据库crud的接口,
SqlSessionFactory:

//这个类的主要作用就是通过SqlSessionFactory的openSession方法得到一个SqlSession
public interface SqlSessionFactory {
    SqlSession openSession();
    SqlSession openSession(boolean var1);
    SqlSession openSession(Connection var1);
    SqlSession openSession(TransactionIsolationLevel var1);
    SqlSession openSession(ExecutorType var1);
    SqlSession openSession(ExecutorType var1, boolean var2);
    SqlSession openSession(ExecutorType var1, TransactionIsolationLevel var2);
    SqlSession openSession(ExecutorType var1, Connection var2);
    Configuration getConfiguration();
}

这个接口的主要作用就是通过openSession方法得到一个SqlSession
我们可以清楚的通过idea查看SqlSession和SqlSessionFactory的结构图,通过结构图的查找我们可以清楚的看到
SqlSession的实现类是DefaultSqlSession和SqlSessionManager
SqlSessionFactory实现类是–DefaultSqlSessionFactory和SqlSessionManager

下面我们分析一下这两个实现类的部分用到的源码
org.apache.ibatis.session.defaults.DefaultSqlSessionFactory.java部分源码:

public class DefaultSqlSessionFactory implements SqlSessionFactory {

  private final Configuration configuration;

  public DefaultSqlSessionFactory(Configuration configuration) {
    this.configuration = configuration;
  }
    private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
    Transaction tx = null;
    try {
      final Environment environment = configuration.getEnvironment();
      final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
      tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
      final Executor executor = configuration.newExecutor(tx, execType);
      return new DefaultSqlSession(configuration, executor, autoCommit);
    } catch (Exception e) {
      closeTransaction(tx); // may have fetched a connection so lets call close()
      throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
    } finally {
      ErrorContext.instance().reset();
    }
  }
  //...

DefaultSqlSession的有参构造的第一步就是注入了一个类Configuration,这个类就是解析主配置文件后,存放连接数据库的username,password等等,创建一个DefaultSqlSession并返回

org.apache.ibatis.session.defaults.DefaultSqlSession.java部分源码:

private Configuration configuration;
private Executor executor;

 @Override
  public void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) {
    try {
      MappedStatement ms = configuration.getMappedStatement(statement);
      executor.query(ms, wrapCollection(parameter), rowBounds, handler);
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error querying database.  Cause: " + e, e);
    } finally {
      ErrorContext.instance().reset();
    }
  }
  
  @Override
  public int update(String statement, Object parameter) {
    try {
      dirty = true;
      MappedStatement ms = configuration.getMappedStatement(statement);
      return executor.update(ms, wrapCollection(parameter));
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error updating database.  Cause: " + e, e);
    } finally {
      ErrorContext.instance().reset();
    }
  }

都是从配置对象Configuration中取出属性来,委托给执行器Executor去处理。

SqlSessionManager同时实现了SqlSession和SqlSessionFactory接口。
org.apache.ibatis.session.SqlSessionManager.java部分源码。

public class SqlSessionManager implements SqlSessionFactory, SqlSession {

  private final SqlSessionFactory sqlSessionFactory;
  // proxy
  private final SqlSession sqlSessionProxy;
  // 保持线程局部变量SqlSession的地方
  private ThreadLocal<SqlSession> localSqlSession = new ThreadLocal<SqlSession>();

  private SqlSessionManager(SqlSessionFactory sqlSessionFactory) {
    this.sqlSessionFactory = sqlSessionFactory;
    // 这个proxy是重点
    this.sqlSessionProxy = (SqlSession) Proxy.newProxyInstance(
        SqlSessionFactory.class.getClassLoader(),
        new Class[]{SqlSession.class},
        new SqlSessionInterceptor());
  }

  public static SqlSessionManager newInstance(Reader reader) {
    return new SqlSessionManager(new SqlSessionFactoryBuilder().build(reader, null, null));
  }

  public static SqlSessionManager newInstance(Reader reader, String environment) {
    return new SqlSessionManager(new SqlSessionFactoryBuilder().build(reader, environment, null));
  }
  //...
  // 设置线程局部变量sqlSession的方法
  public void startManagedSession() {
    this.localSqlSession.set(openSession());
  }

  public void startManagedSession(boolean autoCommit) {
    this.localSqlSession.set(openSession(autoCommit));
  }
  //...
  @Override
  public <T> T selectOne(String statement, Object parameter) {
    return sqlSessionProxy.<T> selectOne(statement, parameter);
  }

  @Override
  public <K, V> Map<K, V> selectMap(String statement, String mapKey) {
    return sqlSessionProxy.<K, V> selectMap(statement, mapKey);
  }
  //...

变量sqlSessionFactory:相当于DefaultSqlSessionFactory的实例(不是proxy)。

变量sqlSessionProxy:是JDK动态代理出来的proxy(是proxy)。

动态代理的目的,是为了通过拦截器InvocationHandler,增强目标target的方法调用。

target:DefaultSqlSession的实例。

所有的调用sqlSessionProxy代理对象的C、R、U、D及事务方法,都将经过SqlSessionInterceptor拦截器,并最终由目标对象target实际完成数据库操作。

sqlSessionProxy代理对象一次性执行了一系列的方法业务,最后统一异常回滚,统一关闭sqlSession,没时间了下次再更改

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值