春に統合MyBatisの

SQLSESSION MyBatisのの使用

MyBatisのは、SQL文を実行し、トランザクションをコミットまたはロールバックし、マッパーインスタンスメソッドを取得しています。SQLSESSIONクラスファクトリSqlSessionFactoryによって作成されたが、SqlSessionFactoryは SqlSessionFactoryBuilderクラスのコンストラクタを作成しています。

InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();

のSQLSESSIONのMyBatisのスプリングを使用します

統合MyBatisのスプリング春を使用する場合は、SqlSessionFactoryは春の実装クラスSqlSessionFactoryBean FactoryBeanのを使用し作成するSqlSessionFactoryBuilder間接的に呼び出します。そのスレッドセーフな実装クラスSqlSessionTemplateに置き換えSQLSESSION、それは自動的にコミットすることができ、ロールバックは、春のセッションベースのトランザクション・メカニズムを閉じました。SqlSessionTemplate Springコンテナを使用するには、それが容器に注がなければなりません。

// 注入 SqlSessionTemplate
@Bean
public SqlSessionTemplate sqlSession() throws Exception {
    return new SqlSessionTemplate(sqlSessionFactory());
}

public SqlSessionFactory sqlSessionFactory() throws Exception {
    SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
    // 指定数据源连接信息
    factoryBean.setDataSource(dataSource());
    // 指定 mapper 文件路径
    InputStream inputStream = Resources.getResourceAsStream("mapper/UserSpringMapper.xml");
    factoryBean.setMapperLocations(new InputStreamResource(inputStream));
    return factoryBean.getObject();
}

// 使用 Spring 事务机制
@Bean
PlatformTransactionManager getTransactionManager() {
    return new DataSourceTransactionManager(dataSource());
}

MyBatisのスプリング・ブート・スターター自動注射器を使用してください

Springboot、導入した場合mybatis-spring-boot-starterMyBatisのコンポーネントを自動的にSpringコンテナに注入され、スタータが導入されるmybatis-spring-boot-autoconfigure(自分のSpringbootスタータ開発する方法を参照)、重要な構成クラスがあり、パッケージMybatisAutoConfigurationのソースコードを見ては、それを見ることができますそこ2つの静的内部クラスであるMapperScannerRegistrarNotFoundConfigurationAutoConfiguredMapperScannerRegistrar請求、MybatisAutoConfiguration及びMapperScannerRegistrarNotFoundConfiguration@Configurationスプリング注釈に追加されるので、春が始まったとき、それらは容器にロードされ、そしてAutoConfiguredMapperScannerRegistrarによりMapperScannerRegistrarNotFoundConfiguration注釈@import間接的容器に注入しました。

AutoConfiguredMapperScannerRegistrarコンテナの起動時に達成ImportBeanDefinitionRegistrarのでメソッドregisterBeanDefinitions()は、次の二つの主な効果が実行されます。

  1. 走査経路から取得したBeanFactoryパケット
  2. 初期化および構成MapperScannerConfigurer(指定された注釈型@Mapper、等、パケットの経路を指定し)たBeanFactoryを登録します

MapperScannerConfigurerは BeanDefinitionRegistryPostProcessor、コンテナが開始は、この方法によってサブクラスClassPathBeanDefinitionScannerを初期化するときに、その方法はpostProcessBeanDefinitionRegistry()が実行されるように実現ClassPathMapperScannerすべてのインタフェースのノート@Mapper、呼び出しスキャン(文字列... basePackages)、スキャンパッケージパス、登録たBeanFactoryに、後処理が続きます。

  1. 変更の種類はBeanDefinitionあるMapperFactoryBean
  2. 指定MapperFactoryBeanのコンストラクタ引数は、インターフェイスクラスの完全なクラス名である@Mapper
  3. 型オートワイヤリングに従って、sqlSessionFactory、sqlSessionTemplateを提供
  4. 反射によって作成MapperFactoryBean例えば、コンストラクタが呼び出すためのパラメータ、着信インターフェイス@Mapper、クラスキャッシュさがあります フォルダのインタフェース

下図のように:MapperFactoryBean継承関係

フォルダファクトリービーン

初期化とコンフィギュレーションの解析

DaoSupportはInitializingBean.afterPropertiesSet()は、この方法によって、マッパーがキャッシュ実現MapperRegistryMap<Class<?>, MapperProxyFactory<?>> knownMappers工場マッパープロキシクラスMapperProxyFactoryとして、値をインターフェイスをマッパーには、キーと、最後に、MapperAnnotationBuilder.parse()XML構成ファイルまたは注釈付きメソッドを解析するために、キャッシュされたコンフィギュレーションMap<String, MappedStatement> mappedStatements次のようにソースコードのプロセスは、次のとおりです。

DaoSupport.afterPropertiesSet()
->MapperFactoryBean.checkDaoConfig()
->Configuration.addMapper(this.mapperInterface)
->MapperRegistry.addMapper(type)
->knownMappers.put(type, new MapperProxyFactory<>(type))
// 解析 SQL 配置
->MapperAnnotationBuilder.parse()
-->configuration.addMappedStatement(statement)

プロキシオブジェクトを生成します

インターフェイスマップMapperProxyFactoryマッパーknownMappersキャッシュから削除FactoryBean.getObject器具()、のMapperFactoryBeanは、ファクトリクラスMapperProxyプロキシクラスを作成し、これを使用して、MapperProxy<T> implements InvocationHandler次のようにJDK動的プロキシの見かけの使用は、ソース・プロセスです。

MapperFactoryBean.getObject()
->SqlSessionTemplate.getMapper(mapperInterface)
->Configuration.getMapper(mapperInterface, this)
->MapperRegistry.getMapper(mapperInterface, sqlSession)
->MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
->mapperProxyFactory.newInstance(sqlSession)

public T newInstance(SqlSession sqlSession) {
  final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);
  return newInstance(mapperProxy);
}
protected T newInstance(MapperProxy<T> mapperProxy) {
  return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}

ここで、プロキシオブジェクトが生成され、単にSpringbootによって適用することができる@Autowired容易注釈の容器からインタフェースプロキシオブジェクトマッパー(MapperProxy)にアクセスします。

実装プロセス

@Mapper UserDaoクラスの注釈があると仮定すると。

@Mapper
public interface UserDao {
  @Select("select * from t_user where id = #{id}")
  Optional<UserEntity> findOne(String id);
}

@Autowiredで豆を取得します。上記から明らかなように、実際にはプロキシオブジェクトのMapperProxyになります。

@Autowired
UserDao userDao;

プロキシオブジェクトは、メソッド呼び出しUserDao方法が実際に実行される()を呼び出すをMapperProxy。

// 调用 findOne
userDao.findOne(id);

// 实际执行的方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  final MapperMethod mapperMethod = cachedMapperMethod(method);
  return mapperMethod.execute(sqlSession, args);
}

呼び出し()メソッドは、実質的に次のようにソースプロセスは実行されます。

MapperMethod.execute(sqlSession, args)
sqlSessionProxy.selectOne(statement, parameter)

ことに注意してくださいSqlSessionSqlSessionTemplateのコンストラクタパラメータが初期化され、そしてそれはまた、あるプロキシクラス、あるSqlSessionInterceptorのエージェント

this.sqlSessionProxy = (SqlSession) newProxyInstance(SqlSessionFactory.class.getClassLoader(),
    new Class[] { SqlSession.class }, new SqlSessionInterceptor());

方法は、したがってselectOne SqlSessionInterceptor.invoke()反射行わSqlSession.selectOne()メソッドは、ソース・プロセスを傍受され、以下の通りであります:

private class SqlSessionInterceptor implements InvocationHandler {
  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    // 打开获取 DefaultSqlSession;
    SqlSession sqlSession = getSqlSession(SqlSessionTemplate.this.sqlSessionFactory,
        SqlSessionTemplate.this.executorType, SqlSessionTemplate.this.exceptionTranslator);
    try {
      // 反射执行 SqlSession 的方法 selectOne(String statement, Object parameter) 进行查询
      Object result = method.invoke(sqlSession, args);
      if (!isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) {
        // 提交
        sqlSession.commit(true);
      }
      // 返回查询结果
      return result;
    } catch (Throwable t) {
      // 异常时释放连接
      closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
    } finally {
      if (sqlSession != null) {
        // 释放连接
        closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
      }
    }
  }
}

注釈と構成ファイル

Springbootアプリケーションはまた、アノテーションを使用するように選択することができ、またはコンフィギュレーションファイルの方法は、設定ファイルの多くを減らすことができ、することができMyBatisの、直接(SelectProvider @、などを選択し、@など)アノテーションを使用して、一般的に、単純なCRUDを使用するように、複雑なSQLまだかもしれませんいくつかの特定を動作させるために、より便利な方法プロファイルを使用し、まだ選択して、実際の状況を見ている、各DAOモード注釈と構成が存在する可能性があることに注意しますが、ノートや構成で説明したのと同じ方法では同時に存在することはできません。

コンフィギュレーション・ファイルを経由している場合は、application.yml DAOコンフィギュレーションファイルに設定ファイルの場所を指定することができます。

# 使用基于配置文件的 MyBatis 时指定 Mapper 配置的路径
mybatis:
  mapper-locations: mapper/*Dao.xml

おすすめ

転載: www.cnblogs.com/bigshark/p/11374857.html