zoukankan      html  css  js  c++  java
  • 浅跟mybatis

    写在开篇:建议自己建个简单的项目,使用idea跟跟,实践下,我的这篇文章纯属自己记录

    ------------------------------------------------------------------------------------------------------------------------

    目前市面上主流的实现mvc的框架就是SSM,mybatis就是那个M,他是实现ORM的轻量级连接数据库的框架,与spring结合使用。他底层操作数据库的代码也是调用的java原生的jdbc。

    在使用mybatis时,我们只需要配置mybaits的配置信息在spring配置文件中,应用启动时会自动加载配置,为我们自动装配使用mybatis所需要的bean。

    使用mybatis我们需要实现配置的信息有sqlSessionFactory和工厂类中需要的参数,dataSource、ConfigLocation和mapperLocations

    其中dataSource中配置了数据库连接信息和数据库连接池信息,可以使用原生的mybatis数据源配置,也支持使用外部数据源,我们公司使用的是阿里的druidDataSource。

    应用启动加载mybatis配置的时候会为我们初始化mybatis运行时的参数,在创建dataSource bean的时候会测试连接数据库,,执行一个测试sql,以保证数据库可以正常访问。

    因为sqlSession工厂bean实现了spring的initializingBean接口,所以在初始化的时候,会执行sqlSessionFactoryBean的afterPropertiesSet方法初始化参数,在这时就会扫描配置,当然也包括mappe.xml文件,为没有mapper.xml文件都生成一个mapperProxy代理类对象,然后作为mapper接口的初始化bean,为每一个mapper.xml中的方法都创建一个MapperMethod方法对象,同时将每个方法中的标签内容转换成对应sqlNode的对象。

    InitializingBean,实现这个接口后,spring容器在创建了对象后会去执行这个对象实现了的afterPropertiesSet()方法,初试化被创建的bean。
    --------------------------------------------题外话---------------------------------------------------
    所以,如果我们有类似的需求,也可以参照实现
    引用别人整理的:
    1)设置属性值;
    2)调用Bean中的BeanNameAware.setBeanName()方法,如果该Bean实现了BeanNameAware接口;
    3)调用Bean中的BeanFactoryAware.setBeanFactory()方法,如果该Bean实现了BeanFactoryAware接口;
    4)调用BeanPostProcessors.postProcessBeforeInitialization()方法;@PostConstruct注解后的方法就是在这里被执行的
    5)调用Bean中的afterPropertiesSet方法,如果该Bean实现了InitializingBean接口;
    6)调用Bean中的init-method,通常是在配置bean的时候指定了init-method,例如:<bean class="beanClass" init-method="init"></bean>
    7)调用BeanPostProcessors.postProcessAfterInitialization()方法;
    8)如果该Bean是单例的,则当容器销毁并且该Bean实现了DisposableBean接口的时候,调用destory方法;如果该Bean是prototype,则将准备好的Bean提交给调用者,后续不再管理该Bean的生命周期。
    
    原文链接:https://blog.csdn.net/t194978/article/details/81515986
    spring初始化bean

      ------------------------------------------------------------------------------------------------------------------------

        public void afterPropertiesSet() throws Exception {
            Assert.notNull(this.dataSource, "Property 'dataSource' is required");
            Assert.notNull(this.sqlSessionFactoryBuilder, "Property 'sqlSessionFactoryBuilder' is required");
            this.sqlSessionFactory = this.buildSqlSessionFactory();
        }
    
        protected SqlSessionFactory buildSqlSessionFactory() throws IOException {
            XMLConfigBuilder xmlConfigBuilder = null;
            Configuration configuration;
            if (this.configLocation != null) {
                xmlConfigBuilder = new XMLConfigBuilder(this.configLocation.getInputStream(), (String)null, this.configurationProperties);
                configuration = xmlConfigBuilder.getConfiguration();
            } else {
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Property 'configLocation' not specified, using default MyBatis Configuration");
                }
    
                configuration = new Configuration();
                configuration.setVariables(this.configurationProperties);
            }
    
            String[] typeHandlersPackageArray;
            String[] arr$;
            int len$;
            int i$;
            String packageToScan;
            if (StringUtils.hasLength(this.typeAliasesPackage)) {
                typeHandlersPackageArray = StringUtils.tokenizeToStringArray(this.typeAliasesPackage, ",; 	
    ");
                arr$ = typeHandlersPackageArray;
                len$ = typeHandlersPackageArray.length;
    
                for(i$ = 0; i$ < len$; ++i$) {
                    packageToScan = arr$[i$];
                    configuration.getTypeAliasRegistry().registerAliases(packageToScan);
                    if (this.logger.isDebugEnabled()) {
                        this.logger.debug("Scanned package: '" + packageToScan + "' for aliases");
                    }
                }
            }
    
            int len$;
            if (!ObjectUtils.isEmpty(this.typeAliases)) {
                Class[] arr$ = this.typeAliases;
                len$ = arr$.length;
    
                for(len$ = 0; len$ < len$; ++len$) {
                    Class<?> typeAlias = arr$[len$];
                    configuration.getTypeAliasRegistry().registerAlias(typeAlias);
                    if (this.logger.isDebugEnabled()) {
                        this.logger.debug("Registered type alias: '" + typeAlias + "'");
                    }
                }
            }
    
            if (!ObjectUtils.isEmpty(this.plugins)) {
                Interceptor[] arr$ = this.plugins;
                len$ = arr$.length;
    
                for(len$ = 0; len$ < len$; ++len$) {
                    Interceptor plugin = arr$[len$];
                    configuration.addInterceptor(plugin);
                    if (this.logger.isDebugEnabled()) {
                        this.logger.debug("Registered plugin: '" + plugin + "'");
                    }
                }
            }
    
            if (StringUtils.hasLength(this.typeHandlersPackage)) {
                typeHandlersPackageArray = StringUtils.tokenizeToStringArray(this.typeHandlersPackage, ",; 	
    ");
                arr$ = typeHandlersPackageArray;
                len$ = typeHandlersPackageArray.length;
    
                for(i$ = 0; i$ < len$; ++i$) {
                    packageToScan = arr$[i$];
                    configuration.getTypeHandlerRegistry().register(packageToScan);
                    if (this.logger.isDebugEnabled()) {
                        this.logger.debug("Scanned package: '" + packageToScan + "' for type handlers");
                    }
                }
            }
    
            if (!ObjectUtils.isEmpty(this.typeHandlers)) {
                TypeHandler[] arr$ = this.typeHandlers;
                len$ = arr$.length;
    
                for(len$ = 0; len$ < len$; ++len$) {
                    TypeHandler<?> typeHandler = arr$[len$];
                    configuration.getTypeHandlerRegistry().register(typeHandler);
                    if (this.logger.isDebugEnabled()) {
                        this.logger.debug("Registered type handler: '" + typeHandler + "'");
                    }
                }
            }
    
            if (xmlConfigBuilder != null) {
                try {
                    xmlConfigBuilder.parse();
                    if (this.logger.isDebugEnabled()) {
                        this.logger.debug("Parsed configuration file: '" + this.configLocation + "'");
                    }
                } catch (Exception var23) {
                    throw new NestedIOException("Failed to parse config resource: " + this.configLocation, var23);
                } finally {
                    ErrorContext.instance().reset();
                }
            }
    
            if (this.transactionFactory == null) {
                this.transactionFactory = new SpringManagedTransactionFactory();
            }
    
            Environment environment = new Environment(this.environment, this.transactionFactory, this.dataSource);
            configuration.setEnvironment(environment);
            if (this.databaseIdProvider != null) {
                try {
                    configuration.setDatabaseId(this.databaseIdProvider.getDatabaseId(this.dataSource));
                } catch (SQLException var22) {
                    throw new NestedIOException("Failed getting a databaseId", var22);
                }
            }
    
            if (!ObjectUtils.isEmpty(this.mapperLocations)) {
                Resource[] arr$ = this.mapperLocations;
                len$ = arr$.length;
    
                for(i$ = 0; i$ < len$; ++i$) {
                    Resource mapperLocation = arr$[i$];
                    if (mapperLocation != null) {
                        try {
                            XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(mapperLocation.getInputStream(), configuration, mapperLocation.toString(), configuration.getSqlFragments());
                            xmlMapperBuilder.parse();
                        } catch (Exception var20) {
                            throw new NestedIOException("Failed to parse mapping resource: '" + mapperLocation + "'", var20);
                        } finally {
                            ErrorContext.instance().reset();
                        }
    
                        if (this.logger.isDebugEnabled()) {
                            this.logger.debug("Parsed mapper file: '" + mapperLocation + "'");
                        }
                    }
                }
            } else if (this.logger.isDebugEnabled()) {
                this.logger.debug("Property 'mapperLocations' was not specified or no matching resources found");
            }
    
            return this.sqlSessionFactoryBuilder.build(configuration);
        }
    主要实现代码

      在这里还做了一件事,就是给我们的每个mapper接口都初始化了一个动态代理类MapperProxy<T> implements InvocationHandler, Serializable。同时将mapper接口中的每个方法信息都初始化到了org.apache.ibatis.session.Configuration中

    当我们在程序中调用一个数据库执行方法去操作数据库时,就会在代理类中查询到实现加载好的方法对应的mapperMethod类,拿到方法信息,通过动态sqlSource(DynamicSqlSource)类循环sqlNode对象执行 getBoundSql方法进行sql拼接。通过debug我们会发现sql拼接的时候会将example中的参数转换成#{},而#{}会被转化成?占位符,使用jdbc的statement进行参数赋值,最终在sql是用引号引起来作为参数拼接到sql中的,而${}是直接将内容作为一个可执行的sql放进去的,所以前两种方式传递sql是比较安全的。处理完sql之后openSession 打开事务,操作数据库








  • 相关阅读:
    推荐一个c++小巧开源且跨平台的图像解码库
    设计模式---桥接模式
    redis数据结构及其使用场景、持久化、缓存淘汰策略
    mysql------explain工具
    mysql索引数据结构
    java8(2)--- Stream API
    java8(1)--- lambda
    springboot自动装配(2)---实现一个自定义自动装配组件
    springboot自动装配(1)---@SpringBootApplication注解怎么自动装配各种组件
    自己挖的坑跪着也要填完---mapper配置文件和java源文件在同一包下
  • 原文地址:https://www.cnblogs.com/tianhaichao/p/12146049.html
Copyright © 2011-2022 走看看