mybatiss学习之路1
来源:互联网 发布:阿里云更换系统 编辑:程序博客网 时间:2024/06/08 08:44
SqlSessionFactoryBean 是一个Factory类,主要是用来生成SqlSessionFactory的。以下是SqlSessionFactoryBean的主要属性
private Resource configLocation;///////mapper文件Resource 对象数组
private Resource[] mapperLocations;
////数据源private DataSource dataSource;/////事务工厂private TransactionFactory transactionFactory;private Properties configurationProperties;private SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();//////根据给的入参实例化的 sqlSessionFactory 实例对象 ,getObjec() 方法返回的就是这个对象private SqlSessionFactory sqlSessionFactory;//EnvironmentAware requires spring 3.1private String environment = SqlSessionFactoryBean.class.getSimpleName();private boolean failFast;/////拦截器 可以在生成执行sql语句之前 修改sql语句或者是修改数据源private Interceptor[] plugins;private TypeHandler<?>[] typeHandlers;private String typeHandlersPackage;private Class<?>[] typeAliases;private String typeAliasesPackage;private Class<?> typeAliasesSuperType;//issue #19. No default provider.private DatabaseIdProvider databaseIdProvider;private ObjectFactory objectFactory;private ObjectWrapperFactory objectWrapperFactory;
spring中定义的 sqlsessionFactoryBean 对象通过 Application.getBean 方法获得的对象实际上是 sqlsessionFactoryBean.getObject()方法返回的对象(如果想获得sqlsessionFactoryBean本身的话在对象id前面加一个 & 因为spring 在生成 FactoryBean 对象的时候会在bean id的前面加一个 &) 。
public SqlSessionFactory getObject() throws Exception { if (this.sqlSessionFactory == null) { afterPropertiesSet(); } return this.sqlSessionFactory;}
返回的实际上就是sqlsessionFactoryBean 本身的 sqlsessionFactory 这个对象的实例化是 afterPropertiesSet() 方法中 (实现了InitalizingBean 接口)
public void afterPropertiesSet() throws Exception { notNull(dataSource, "Property 'dataSource' is required"); notNull(sqlSessionFactoryBuilder, "Property 'sqlSessionFactoryBuilder' is required"); this.sqlSessionFactory = buildSqlSessionFactory();}进入 buildsqlsessinofactory() 方法
protected SqlSessionFactory buildSqlSessionFactory() throws IOException { Configuration configuration; XMLConfigBuilder xmlConfigBuilder = null; if (this.configLocation != null) { xmlConfigBuilder = new XMLConfigBuilder(this.configLocation.getInputStream(), null, this.configurationProperties); configuration = xmlConfigBuilder.getConfiguration(); } else { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Property 'configLocation' not specified, using default MyBatis Configuration"); } configuration = new Configuration(); configuration.setVariables(this.configurationProperties); } if (this.objectFactory != null) { configuration.setObjectFactory(this.objectFactory); } if (this.objectWrapperFactory != null) { configuration.setObjectWrapperFactory(this.objectWrapperFactory); } if (hasLength(this.typeAliasesPackage)) { String[] typeAliasPackageArray = tokenizeToStringArray(this.typeAliasesPackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); for (String packageToScan : typeAliasPackageArray) { configuration.getTypeAliasRegistry().registerAliases(packageToScan, typeAliasesSuperType == null ? Object.class : typeAliasesSuperType); if (LOGGER.isDebugEnabled()) { LOGGER.debug("Scanned package: '" + packageToScan + "' for aliases"); } } } if (!isEmpty(this.typeAliases)) { for (Class<?> typeAlias : this.typeAliases) { configuration.getTypeAliasRegistry().registerAlias(typeAlias); if (LOGGER.isDebugEnabled()) { LOGGER.debug("Registered type alias: '" + typeAlias + "'"); } } }////////添加拦截器 if (!isEmpty(this.plugins)) { for (Interceptor plugin : this.plugins) { configuration.addInterceptor(plugin); if (LOGGER.isDebugEnabled()) { LOGGER.debug("Registered plugin: '" + plugin + "'"); } } } if (hasLength(this.typeHandlersPackage)) { String[] typeHandlersPackageArray = tokenizeToStringArray(this.typeHandlersPackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); for (String packageToScan : typeHandlersPackageArray) { configuration.getTypeHandlerRegistry().register(packageToScan); if (LOGGER.isDebugEnabled()) { LOGGER.debug("Scanned package: '" + packageToScan + "' for type handlers"); } } } if (!isEmpty(this.typeHandlers)) { for (TypeHandler<?> typeHandler : this.typeHandlers) { configuration.getTypeHandlerRegistry().register(typeHandler); if (LOGGER.isDebugEnabled()) { LOGGER.debug("Registered type handler: '" + typeHandler + "'"); } } } if (xmlConfigBuilder != null) { try { xmlConfigBuilder.parse(); if (LOGGER.isDebugEnabled()) { LOGGER.debug("Parsed configuration file: '" + this.configLocation + "'"); } } catch (Exception ex) { throw new NestedIOException("Failed to parse config resource: " + this.configLocation, ex); } finally { ErrorContext.instance().reset(); } } if (this.transactionFactory == null) { this.transactionFactory = new SpringManagedTransactionFactory(); } configuration.setEnvironment(new Environment(this.environment, this.transactionFactory, this.dataSource)); if (this.databaseIdProvider != null) { try { configuration.setDatabaseId(this.databaseIdProvider.getDatabaseId(this.dataSource)); } catch (SQLException e) { throw new NestedIOException("Failed getting a databaseId", e); } }////////根据我们配置的mapper.xml文件 if (!isEmpty(this.mapperLocations)) { for (Resource mapperLocation : this.mapperLocations) { if (mapperLocation == null) { continue; } try { XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(mapperLocation.getInputStream(), configuration, mapperLocation.toString(), configuration.getSqlFragments());
/////////1. 在这个方法中会去把 mapper 文件中的namespace 转化成Class对象并把 该类存到 configuration对象的mapperRegistry属性中
用来记录 通过接口的函数名字和xml的id关连的 mapper接口/////////2. 转化结果集 resultmap 并把他记录在 configuration 的resultMaps中
/////////3.
/////////4. 将每个sql 语句转化成 MappedStatement 并把他存在 configuration的 mappedStatements中 xmlMapperBuilder.parse(); } catch (Exception e) { throw new NestedIOException("Failed to parse mapping resource: '" + mapperLocation + "'", e); } finally { ErrorContext.instance().reset(); } if (LOGGER.isDebugEnabled()) { LOGGER.debug("Parsed mapper file: '" + mapperLocation + "'"); } } } else { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Property 'mapperLocations' was not specified or no matching resources found"); } } return this.sqlSessionFactoryBuilder.build(configuration);}
了解下 Configuration 这个类 的主要属性 这个类包含了mybatis 的所有配置
//////对应<environment> 标签 可以配置数据源 及数据源和环境的关系,可以根据环境切换数据源
protected Environment environment;protected boolean safeRowBoundsEnabled = false;protected boolean safeResultHandlerEnabled = true;protected boolean mapUnderscoreToCamelCase = false;protected boolean aggressiveLazyLoading = true;protected boolean multipleResultSetsEnabled = true;protected boolean useGeneratedKeys = false;protected boolean useColumnLabel = true;protected boolean cacheEnabled = true;protected boolean callSettersOnNulls = false;protected String logPrefix;protected Class <? extends Log> logImpl;protected LocalCacheScope localCacheScope = LocalCacheScope.SESSION;protected JdbcType jdbcTypeForNull = JdbcType.OTHER;protected Set<String> lazyLoadTriggerMethods = new HashSet<String>(Arrays.asList(new String[] { "equals", "clone", "hashCode", "toString" }));protected Integer defaultStatementTimeout;protected Integer defaultFetchSize;protected ExecutorType defaultExecutorType = ExecutorType.SIMPLE;protected AutoMappingBehavior autoMappingBehavior = AutoMappingBehavior.PARTIAL;protected Properties variables = new Properties();protected ReflectorFactory reflectorFactory = new DefaultReflectorFactory();protected ObjectFactory objectFactory = new DefaultObjectFactory();protected ObjectWrapperFactory objectWrapperFactory = new DefaultObjectWrapperFactory();protected MapperRegistry mapperRegistry = new MapperRegistry(this);protected boolean lazyLoadingEnabled = false;protected ProxyFactory proxyFactory = new JavassistProxyFactory(); // #224 Using internal Javassist instead of OGNLprotected String databaseId;/** * Configuration factory class. * Used to create Configuration for loading deserialized unread properties. * * @see <a href='https://code.google.com/p/mybatis/issues/detail?id=300'>Issue 300</a> (google code) */protected Class<?> configurationFactory;//插件链
protected final InterceptorChain interceptorChain = new InterceptorChain();protected final TypeHandlerRegistry typeHandlerRegistry = new TypeHandlerRegistry();protected final TypeAliasRegistry typeAliasRegistry = new TypeAliasRegistry();protected final LanguageDriverRegistry languageRegistry = new LanguageDriverRegistry();//mappedStatements Map 每个sql语句对应yige MappedStatement对象 包括 入参 对象 出参对象 (都是String 即id)protected final Map<String, MappedStatement> mappedStatements = new StrictMap<MappedStatement>("Mapped Statements collection");protected final Map<String, Cache> caches = new StrictMap<Cache>("Caches collection");
///////sql语句和结果集 之间的映射关系protected final Map<String, ResultMap> resultMaps = new StrictMap<ResultMap>("Result Maps collection");
//////sql语句和 入参集 之间的映射关系protected final Map<String, ParameterMap> parameterMaps = new StrictMap<ParameterMap>("Parameter Maps collection");protected final Map<String, KeyGenerator> keyGenerators = new StrictMap<KeyGenerator>("Key Generators collection");protected final Set<String> loadedResources = new HashSet<String>();
//一些sql 碎片 自定义的一些sql片段protected final Map<String, XNode> sqlFragments = new StrictMap<XNode>("XML fragments parsed from previous mappers");//未解析处理的statementsprotected final Collection<XMLStatementBuilder> incompleteStatements = new LinkedList<XMLStatementBuilder>();protected final Collection<CacheRefResolver> incompleteCacheRefs = new LinkedList<CacheRefResolver>();
//未解析处理的ResultMapsprotected final Collection<ResultMapResolver> incompleteResultMaps = new LinkedList<ResultMapResolver>();
//未解析处理的Methodsprotected final Collection<MethodResolver> incompleteMethods = new LinkedList<MethodResolver>();/* * A map holds cache-ref relationship. The key is the namespace that * references a cache bound to another namespace and the value is the * namespace which the actual cache is bound to. */protected final Map<String, String> cacheRefMap = new HashMap<String, String>();
(插一句工厂类的好处,有些类的属性比较多,一个一个配置会比较麻烦,还有些属性是不想暴露给外面的 使用Factory来生成bean会更好,如果想 生成代理类的话也比较方便,直接在工厂类生成bean的时候修改就好了)
一般我们拿到的sqlSessionFactory 是 DefaultSqlSessionFactory类型的
public DefaultSqlSessionFactory(Configuration configuration) { this.configuration = configuration;}
把所有的配置都放在了configuration对象中 这里只是生成了sqlsessionfactory对象
再看看如何直接用配置文件中的id直接访问数据库 主要是利用session来操作数据库的 默认实现是DefaultSqlSession
主要有这几个属性
///mybatis的配置都在这对象中
pivate Configuration configuration;////执行器,实际对数据库操作的对象
private Executor executor;//是否自动提交private boolean autoCommit;private boolean dirty;以查询为例 最后调用的方法是 selectList()public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) { try { MappedStatement ms = configuration.getMappedStatement(statement); return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER); } catch (Exception e) { throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e); } finally { ErrorContext.instance().reset(); }}在xml配置文件中 一条sql 对应一个 MappedStatement 这个映射是存在configuration中的mappedStatements中的 key是 (如果启用了namespace
是namespace+id)id value是对应的MappedStatement对象 看下MappedStatement属性
真正的执行方法是 executor的queryprivate String resource;private Configuration configuration;private String id;private Integer fetchSize;private Integer timeout;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;
执行器 executor有三种 默认的是simpleExecutor 其中query方法
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException { BoundSql boundSql = ms.getBoundSql(parameter); CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql); return query(ms, parameter, rowBounds, resultHandler, key, boundSql);}MappedStatement中的getBoundSql 的作用是给入参并解析出 BoundSql BoundSql中的属性//解析好的sql 语句
private String sql;private List<ParameterMapping> parameterMappings;private Object parameterObject;private Map<String, Object> additionalParameters;private MetaObject metaParameters;mybatis访问数据最终还是通过jdbc的方式去访问的 StatementHandler
回顾下jdbc连接数据库
http://www.cnblogs.com/centor/p/6142775.html 转载
看mybatis 是如何获取数据库连接的
通过 Exector中的Transaction获取连接Transaction中存有Datasource 数据源
如果是根据接口去访问 则还需要配置 MapperScannerConfigurer 这类实现了 BeanDefinitionRegistryPostProcessor会将配置的那个包下的所有接口都转成代理类
阅读全文
0 0
- mybatiss学习之路1
- maven 学习之路之二(1)
- java学习之路之接口(1)
- 【札记】spring+mybatiss+c3p0整合访问MySQL的URL配置(有批量修改信息时)
- Grails学习之路(1)
- java学习之路1
- ioctl 学习之路 (1)
- nginx学习之路(1)
- csdn学习之路--1
- bootstrap学习之路1
- python学习之路1
- OpenGL学习之路1
- html5学习之路-------1
- LINUX学习之路-1
- 数据库学习之路1
- Qt学习之路(1)
- Lua学习之路-1
- android学习之路1
- osu
- 使用servlet编程,解决输出到页面的中文显示乱码问题。
- 数据结构-01
- xml的Web服务
- C++开发笔记
- mybatiss学习之路1
- ajax接受servlet传送json数据中文乱码
- PHP之Linux(五) 进程管理与系统命令
- Python自定义大小截屏
- 深度学习模型压缩方法综述(三)
- Java设计模式之工厂模式
- JQuery
- 线程同步(9种同步方式)
- AFN3.0设置请求头Header