Mybatis ?? ?jdbc与mybatis ?? ??? ?1 传统JDBC开发时,需要频繁的创建数据库连接对象,释放,容易造成系统资源浪费,影响系统性能。mybatis--解决方式:可以配置mybatis-config.xml数据库连接池解决这个问题。2 sql语句定义,参数设置,结果集处理存在硬编码。实际项目中sql语句变化可能性较大,一旦发生变化,需要修改Java代码,系统需要重新编译,重新发布,不易维护。mybatis--解决方法:将sql语句配置在mapper.xml文件中和Java代码分离。 3 使用perparedStatement向占有为符号传参数存在硬编码,因为sql语句的where条件不一定,可能多可能少,修改sql还要修改代码,系统不易维护。mybatis--解决方式:mybatis 将Java对象映射到sql语句 。 4结果集处理存在重复代码,处理麻烦。mybatis--解决方法:mybatis将sql执行结果映射到Java对象。 ?? ?mybatis的缓存 ?? ??? ?1 batis的一级缓存:基于PerpetualCache的HashMap本地缓存,其存储作用域为session,当session 刷新或关闭后,该session中所有的缓存就会清空,默认打开以及缓存。2级缓存与以及缓存机制相同,默认也是采用PerpetualCache,HashMap存储,不同是在存储作用域为Mapper或namespace,并且可自定义存储源,如Ehcache。默认不打开二级缓存,要开启二级缓存,使用二级缓存属性类需要实现serializable序列化接口(用来保存对象的状态)在它映射文件中配<cache>3 对于缓存数据更新机制,当某一个作用域(以及缓存session、二级缓存namespace)进行增删改后,默认该作用域所有的select中的缓存清空 ?? ?mybatis实现一对一,一对多的几种方式 ?? ??? ?联合查询和嵌套查询,联合查询通过resultMap中的association,collection节点配置一对一,一对多。嵌套查询就是先查一个表,根据表中的外键,去另一个表里查询数据,也是通过association,collection,另一个表的查询通过select节点配置 ?? ?DAO接口中的方工作原理和 对应的xml映射文件 ?? ??? ?DAO接口就是mapper接口,就是映射文件中的namespace的值,DAO接口中的方法不能重载,DAO接口的工作原理就是JDK的动态代理。映射文件--》不同的映射文件,如果配置了namespace,那么id可以重复,如果没有配置namespace,那么id不能重复,namespace不是必须的,只是最佳实践。 ?? ?mapper编写有哪几种方式? ?? ??? ?第一种:接口实现类继承SqlSessionDaoSupport:使用这个方法要编写mapper接口,mapper实现类,mapper.xml-->1 在sqlMapConfig.xml中配置mapper.xml位置 2 定义mapper接口 3 实现类继承SqlSessionDaoSupport mapper方法中可以this.getSqlSession()进行数据增删改查 4配置spring 第二种使用org.mybatis.spring.mapper.MapperFactoryBean:-->1 在sqlMapConfig.xml中配置mapper.xml的位置,如果mapper.xml和mapper接口的名称相同并且在同一个目录,这里可以不用配置 2定义mapper接口 3 mapper.xml中的namespace为mapper接口的地址 4 mapper接口中的方法名和mapper.xml中定义的statement的id保持一致 5 spring定义 第三种 --》1mapper.xml编写:mapper.xml中namespace为mapper接口的地址mapper接口中的方法名和mapper.xml中定义的statement的id 保持一致 2 定义imapper接口 3 配置mapper扫描器 4 使用扫描器后从spring中获取mapper的实现对象 ?? ?当实体类中属性名和表中字段名不一致怎么办? ?? ??? ?1 通过查询的sql语句中定义字段名的别名,让字段名的别名和实体类的属性名一致 . 2通过<resultMap>来映射字段名和实体类属性名一一对应的关系、 ?? ?mybatis如何执行批量操作 ?? ??? ?使用foreach标签--》foreach的主要用在构建in条件中,它可以在sql语句中进行迭代一个集合。foreach标签的属性主要有item,index,collection,open,separator,close. ?item:表示集合中每一个元素进行迭代时的别名,随便起的变量名;index:指定一个名字,用于表示在迭代过程中,每次迭代到的位置,不常用;open:表示该语句以什么开始,常用‘’(‘’separator:表示以什么结束,常用‘’)‘’。在使用foreach的时候最关键也是最容易出错的就是collection属性,该属性是必须指定的,但是在不同情况下,该属性的值是不一样,主要有3种情况:1 如果传入的是单参数并且参数类型是一个List的时候,collection属性值为list 。2 如果传入的是单参数并且参数类型是一个array数组的时候,collection的属性值为array。 3 如果传入的参数是多个的时候,我们就需要把它们封装成Map,单参数也能封装成Map,实际你传入参数的时候,在mybatis中会把它封装成一个Map ,map的key就是参数名,所以这个时候coollection属性值就是传入的List或array对象在自己封装的map中key。 ?? ?mybatis 中mapper如何传送多个参数 ?? ??? ?方法1:顺序传参法:#{}中的数字代表传入参数的顺序,一旦顺序调整容易出错,不推荐使用。方法2:@Param注解传参法#{}中的名称对应的是@Param括号中的名称 。方法3:Map传参法#{}中名称对应的是Map中key的名称,这种方法适合传递多个参数,并且参数能灵活传递。方法4:Java Bean传参法:#{}中的名称对应的是实体类的成员属性。这种更加直观,需要创建实体类,不容易扩展,但代码可读性强,业务逻辑处理方便。 ?? ?mybatis 概念 ?? ??? ?Mybatis 是一款优秀的持久层框架,一个半ORM(对象关系映射)框架,它支持自定义sql语句,存储过程以及高级映射.它几乎避免了jdbc代码和设置参数以及获取结果集的操作,并且可以通过简单的注解和xml文件来配置和映射原生类型,接口,和Java的POJO(plain Old java objects ,普通老式Java对象) 为数据库中的记录 ?? ??? ??? ?ORM是什么?ORM:Object Relational Mapping 首字母简写,中文意思是:对象关系映射,是一种为了解决关系型数据库与简单Java对象(POJO:Plain Old Java Objects ,普通老式Java对象)的映射关系的技术。简单来说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的 对象自动持久化到关系型数据库中。? ?? ?mybatis的优点和缺点 ?? ??? ?mybatis优点:与jdbc比较,代码减少了50%以上。2简单易学。3 sql代码从程序代码中分。提高了代码的重用性。4 提供xml标签,支持动态sql。5 提供mapper映射标签,支持对象和数据库的ORM字段关系映射。6 可以很好的与各种数据库兼容(因为mybtis使用JDBC来连接数据库,所以只要JDBC支持的数据库mybtis都支持)。7 能与spring很好的集成 ?? ??? ?mybaties缺点:1 移植性差,一旦切换数据库,sql语句需要根据数据库进行变更 。2 sql语句编写量大 ?? ?mybatis与全自动ORM映射工具hibernate的区别 ?? ??? ?hibernate的概念:hibernate是一款开源的对象关系框架,它具有关系对象持久性和查询服务,hibernate将java类映射到数据库表中,在java类型中映射到sql数据类型中,减少了持续编写重复代码的繁重操作,hibernate是传统Java对象和数据库服务之间的桥梁,用于处理基于o/r映射机制和模式的那些对象 ?? ??? ?hibernate优势:1使用xml处理映射Java类别到数据库表中,不用编写任何代码。2为数据库中直接存储和检索Java对象提供简单的API 。3数据库中表发生变化,只需要改变xml文件就可以了。4抽象不熟悉的sql类型,为我们提供熟悉的java对象。5hibernate不需要应用程序服务器来操作。6操作数据库中对象复杂的关联。7最小化和访问数据库的智能提取策略8提供简单的数据询问。 ?? ??? ?hibernate缺点:hibernate完全封装无法使用数据的一些功能。2缓存问题。3耦合高。4寻找bug困难。5批量数据操作浪费内存空间并且执行中需要的对象多。 ?? ??? ?mybatis与hibernate的相同点:都是对jdbc的封装,都是持久层框架,都是用于dao层开发。 ?? ??? ?mybatis与hibernate的不同点:1 映射关系:mybatis是一个半自动映射的框架,配置Java对象与sql语句执行结果的对应关系,多表关联关系配置简单。hibernate是一个全表映射的框架,配置Java对象与数据库表的对应关系,多表关联关系配置复杂。2 sql优化和移植性:hibernate对sql语句封装,提供了日志,缓存,级联(级联比mybatis强大)等特性,此外还提供HQL(Hibernate query language)操作数据库,数据库无关性支持好,但会多消耗性能。如果项目需要支持多种数据库,代码开发量少,但sql语句优化困难。mybatis需要手动编写sql,支持动态sql,处理列表,动态生成表名,支持存储过程,开发工作量大,直接使用sql语句操作数据库,不支持数据库无关性,但sql语句优化容易。3开发难易程度和学习成本:hibernate是重量级框架,学习使用门槛高,适合需求相对稳定,中小型项目,比如:办公自动化系统。mybatis是轻量级框架,学习门槛低,适合与需求变化频繁,大型项目例如:互联网电子商务系统。总结:mybatis是一个小巧,方便,高效,简单,直接,半自动化的持久层框架,hibernate是一个强大,方便,高效,复杂,间接,全自动的持久层框架。 ?? ?mybatis的解析和运行原理: ?? ??? ?mybatis编程步骤-->1 创建sqlSessionFactory 2 通过SqlSessionFactory创建SqlSession 3通过SqlSession执行数据库操作 4调用sessoin.commit()提交事务 5 调用session.close()关闭会话 。mybatis工作原理视图和文字描述:1 读取配置文件:mybatis-config.xml为mybatis的全局配置文件,配置了mybatis的运行环境等信息,例如:数据库连接信息。 2 加载映射文件。映射文件即sql映射文件,该文件中配置了操作数据库的sql语句,需要在mybatis配置文件mybatis-config.xml中加载。mybatis-config.xml文件可以加载多个映射文件,每个文件对应数据库中的一张表。 3 构建会话工厂:通过mybatis的环境等配置信息构建会话工厂SqlSessionFactory. 4 创建会话对象:由会话工厂创建sqlSession对象,该对象中包含了执行sql语句的所有方法。5 Executor 执行器:mybatis底层定义了一个Executor接口来操作数据库,它将根据SqlSession传递的参数动态的生成需要执行的sql语句,同时负责查询缓存的维护。 6 MapperedStatement对象:在Executor接口的执行方法中有一个MapperedStatement类型的参数,该参数是对应映射信息的封装,用于存储要映射的sql语句的id,参数等信息。7 输入参数映射:输入参数类型可以是Map,List,等集合类型,也可以是基本数据类型和POJO类型。输入参数映射过程类似于JDBC对preparedStatement对象设置参数的过程。 8 输出结果映射:输出结果类型可以是Map,List等集合类型,也可以是基本数据类型和POJO类型。输出结果映射过程类似于JDBC对结果集的解析过程。 ?? ?mybatis使用场景: ?? ??? ?1 mybatis专注sql本身,是一个足够灵活的DAO层解决方案。2 对性能要求很高,或者需求变化多的项目。比如互联网项目,mybatis 是不错的选择。 ?? ?mybatis的功能架构以及视图 ?? ??? ?mybatis的功能框架分为三层:第一层-->API接口层:提供给外部使用的接口API,开发人员通过这些本地API来操纵数据库。接口层一接收到调用请求就会调用数据处理层来完成具体的数据处理。第二层-->数据处理层:负责具体的sql查找,sql解析,sql执行和执行结果映射处理等。它主要的目的是根据调用的请求完成一次数据库操作。第三层-->基础支持层:负责最基础的功能支撑,包括连接管理,事务管理,配置加载和缓存处理,这些都是公用的东西,将他们抽取出来作为最基础的组件。为上层的数据处理层提供最基础的支撑 ?? ?mybatis框架架构设计概述以及视图 ?? ??? ? ?? ??? ?从上面这张图从上到下看。mybatis的初始化,会从mybatis-config.xml配置文件,解析构造成Configuration这个类,就是图中的红框。1 加载配置:配置来自两个地方,一个是Java代码的注解。一个是sql配置信息加载成一个个MapperStatement对象(包括传入参数映射配置,执行的sql语句,结果映射配置)存储在内存中。 2 sql 解析:当API接口层接收到调用请求是收到传入sql的id和传入的对象(可以是Map,javaBean或者基本数据类型),mybatis会根据sql的id找到对应的MapperedStatement,然后根据传入参数对象对MapperStatement进行解析,解析后可以得到最终要执行的sql语句和参数。3 sql执行:将最终得到的sql和参数拿到数据库进行执行,得到操作数据库的结果。 4 结果映射:将操作数据库的结果按照映射的配置进行转换,可以转化成HashMap,JavaBean或者基本数据类型,并将最终结果返回。 ?? ?mybatis的Executor执行器 ?? ??? ?mybatis有三种基本的Executor执行器,默认的是SimpleExecutor,还有ReuseExecutor,BatchExecutor。SimpleExecutor:执行一次update或select,就开启一个Statement对象,用完就立即关闭Statement对象。ReuseExecutor:执行update或select,以sql作为key查找Statement对象,存在就使用,不存在就创建,用完后,不关闭Statement,而是放置于Map<String,Statement>内,供下一次使用。简单说就是重复使用Statement对象。BatchExecutor:执行update(没有select,JDBC批处理不支持select),将所有sql都添加到批处理中(addBatch()),等待统一执行(executBatch()),它缓存了多个Statement对象,每个Statement对象都是addBatch()完毕后,等待逐一执行executorBatch()批处理,与JDBC批处理相同。Executor都严格限制在SqlSession生命周期范围内。 ?? ??? ??? ?mybatis中如何指定使用哪种Executor执行器?在mybatis配置文件中,在设置(settings)可以指定默认的ExecutorType执行器类型,也可以手动给DefaultSqlSessionFactory的创建SqlSession的方法传递ExecutorType类型参数,如SqlSession openSession(ExecutorType execType)。配置默认的执行器。SIMPLE就是普通的执行器;REUSE执行器会重用预处理语句(prepared statement);BATCH执行器将重用语句并执行批量更新。 ?? ?mybatis是否支持延迟加载?如果支持,它的实现原理是什么? ?? ??? ?mybatis仅支持assoction关联对象和collection关联集合对象的延迟加载,association指的就是一对一,collection指的就是一对多查询。在mybatis配置文件中,可以配置是否启用延迟加载lazyLoadingEnabled=true\false。它的原理是,使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用a.getB().getName(),拦截器invoke()方法发现a.getB()是null值,那么就会单独发送事先保存的查询关联B对象的sql,把B查询上来,然后调用a.setB(b),于是a的对象b属性就有值了,接着完成a.getB(),getName()方法的调用。这就是延迟加载的基本原理。 ?? ?mybatis映射器中#{}和${}的区别 ?? ??? ?#{}是占位符,预编译处理;${}是拼接符,字符串替换,没有预编译处理。mybatis在处理#{}时,#{}传入参数是以字符串传入,会将sql中的#{}替换为?号,调用PrepaerdStatement的set方法来赋值。mybatis在处理时,是原值传入,就是把{}替换成变量的值,相当于JDBC中的Statement编译。变量替换后,#{}对应的变量自动加上单引号‘’变量替换后${}对应变量不会加上单引号‘’#{}可以有效的防止sql注入,提高系统安全性,${}不能防止sql注入。#{}的变量替换是在DBMS中,${}的变量替换是在DBMS外 ?? ?xml映射文件中常见的标签 ?? ??? ?select ,insert ,update ,delete ,resultMap,parameterMap,sql,include,selectKey,加动态sql9个标签,trim,where,foreach,if,choose,when,otherwise,bind ,sql是片段标签需要include引入,selectKey为不支持自增主键生成策略标签。 ?? ?逆向工程 ?? ??? ?什么是逆向工程?mybatis需要程序员自己编写sql语句,mybatis官方提供逆向工程,可以针对单表自动生成mybatis执行所需要的代码。应用场景:企业开发中,常用于由数据库的表生成Java代码。
|