Mybatis部分(重要)

1.mybatis 中 #{}和 ${}的区别是什么?

1. #将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。如:order by #user_id#,如果传入的值是111,那么解析成sql时的值为order by "111", 如果传入的值是id,则解析成的sql为order by "id".

2. $将传入的数据直接显示生成在sql中。如:order by $user_id$,如果传入的值是111,那么解析成sql时的值为order by user_id,  如果传入的值是id,则解析成的sql为order by id.

3. #方式能够很大程度防止sql注入。

4.$方式无法防止Sql注入。

5.$方式一般用于传入数据库对象,例如传入表名.

6.一般能用#的就别用$.

但是MyBatis排序时使用order by 动态参数时需要注意,用$而不是#


2.mybatis 有几种分页方式? mybatis 分页插件的实现原理是什么?

mybatis框架分页实现,有几种方式,最简单的就是利用原生的sql关键字limit来实现,还有一种就是利用interceptor来拼接sql,实现和limit一样的功能,再一个就是利用PageHelper分页插件来实现。这里讲解这三种常见的实现方式:无论哪种实现方式,我们返回的结果,不能再使用List了,需要一个自定义对象Pager。

分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数


3. Mybatis是如何将sql执行结果封装为目标对象并返回的?都有哪些映射形式?

第一种是使用<resultMap>标签,逐一定义数据库列名和对象属性名之间的映射关系。

第二种是使用sql列的别名功能,将列的别名书写为对象属性名。

有了列名与属性名的映射关系后,Mybatis通过反射创建对象,同时使用反射给对象的属性逐一赋值并返回,那些找不到映射关系的属性,是无法完成赋值的。


4.mybatis 逻辑分页和物理分页的区别是什么?

Mybatis可以通过传递RowBounds对象,来进行数据库数据的分页操作,然而遗憾的是,该分页操作是对ResultSet结果集进行分页,这就是逻辑分页

物理分页性能是最好的。下面就是物理分页的结果

1. Sql中带有offset,limit参数,自己控制参数值,直接查询分页结果。

2. 使用第三方开发的Mybatis分页插件。

3. 修改Mybatis源码,给Sql追加自己的物理分页Subsql。

1:逻辑分页 内存开销比较大,在数据量比较小的情况下效率比物理分页高;在数据量很大的情况下,内存开销过大,容易内存溢出,不建议使用

2:物理分页 内存开销比较小,在数据量比较小的情况下效率比逻辑分页还是低,在数据量很大的情况下,建议使用物理分页


5.mybatis 是否支持延迟加载?延迟加载的原理是什么?

在mybatis 中默认没有使用延迟加载

Mybatis仅支持association关联对象和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,几乎所有的包括Hibernate,支持延迟加载的原理都是一样的。


6.说一下 mybatis 的一级缓存和二级缓存?

一级缓存:一级缓存是SqlSession级别的缓存。在操作数据库时需要构造sqlSession对象,在对象中有一个数据结构用于存储缓存数据。不同的sqlSession之间的缓存数据区域是互相不影响的。也就是他只能作用在同一个sqlSession中,不同的sqlSession中的缓存是互相不能读取的。

二级缓存:二级缓存是mapper级别的缓存,多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。UserMapper有一个二级缓存区域(按namespace分),其它mapper也有自己的二级缓存区域(按namespace分)。每一个namespace的mapper都有一个二级缓存区域,两个mapper的namespace如果相同,这两个mapper执行sql查询到数据将存在相同的二级缓存区域中。对于查询多commit少且用户对查询结果实时性要求不高,此时采用mybatis二级缓存技术降低数据库访问量,提高访问速度。

二级缓存性能不佳会造成问题:

    1)对该表的操作与查询都在同一个namespace下,其他的namespace如果有操作,就会发生数据的脏读。

    2)对关联表的查询,关联的所有表的操作都必须在同一个namespace。

所以一般情况下 mybatis的二级缓存默认关闭不太使用


7.mybatis 和 hibernate 的区别有哪些?

相同点:屏蔽jdbc api的底层访问细节,使用我们不用与jdbc api打交道,就可以访问数据。jdbc api编程流程固定,还将sql语句与java代码混杂在了一起,经常需要拼凑sql语句,细节很繁琐。

mybatis的好处:屏蔽jdbc api的底层访问细节;将sql语句与java代码进行分离;提供了将结果集自动封装称为实体对象和对象的集合的功能,queryForList返回对象集合,用queryForObject返回单个对象;提供了自动将实体对象的属性传递给sql语句的参数。

Hibernate是一个全自动的orm映射工具,它可以自动生成sql语句,mybatis需要我们自己在xml配置文件中写sql语句,hibernate要比mybatis功能负责和强大很多。因为hibernate自动生成sql语句,我们无法控制该语句,我们就无法去写特定的高效率的sql。对于一些不太复杂的sql查询,hibernate可以很好帮我们完成,但是,对于特别复杂的查询,hibernate就很难适应了,这时候用mybatis就是不错的选择,因为mybatis还是由我们自己写sql语句。


8.mybatis 有哪些执行器(Executor)?

SimpleExecutor、ReuseExecutor、BatchExecutor。

SimpleExecutor:每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象。

ReuseExecutor:执行update或select,以sql作为key查找Statement对象,存在就使用,不存在就创建,用完后,不关闭Statement对象,而是放置于Map内,供下一次使用。简言之,就是重复使用Statement对象。

BatchExecutor:执行update(没有select,JDBC批处理不支持select),将所有sql都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个Statement对象,每个Statement对象都是addBatch()完毕后,等待逐一执行executeBatch()批处理。与JDBC批处理相同。

作用范围:Executor的这些特点,都严格限制在SqlSession生命周期范围内。


9. MyBatis实现一对一有几种方式?具体怎么操作的? MyBatis实现一对多有几种方式,怎么操作的?

一对一:

有联合查询和嵌套查询,联合查询是几个表联合查询,只查询一次, 通过在resultMap里面配置association节点配置一对一的类就可以完成;嵌套查询是先查一个表,根据这个表里面的结果的 外键id,去再另外一个表里面查询数据,也是通过association配置,但另外一个表的查询通过select属性配置。

一对多:

有联合查询和嵌套查询。联合查询是几个表联合查询,只查询一次,通过在resultMap里面的collection节点配置一对多的类就可以完成;嵌套查询是先查一个表,根据这个表里面的 结果的外键id,去再另外一个表里面查询数据,也是通过配置collection,但另外一个表的查询通过select节点配置。


10.mybatis 如何编写一个自定义插件?

1. 编写Interceptor的实现类 2. 使用@Intercepts注解完成插件签名 说明插件的拦截四大对象之一的哪一个对象的哪一个方法 3. 将写好的插件注册到全局配置文件中4大对象。

1.Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)          --执行sql

2.ParameterHandler (getParameterObject, setParameters)                     --获取、设置参数

3.ResultSetHandler (handleResultSets, handleOutputParameters)          --处理结果集

4.StatementHandler (prepare, parameterize, batch, update, query)          --记录sql


11.简单介绍下你对MyBatis的理解?MyBatis中如何使用事务?MyBatis如何做对象关联? 

1. MyBatis是一个数据持久层(ORM)框架。把实体类和SQL语句之间建立了映射关系,是一种半自动化的ORM实现。需要开发人员自己来写sql语句,程序更灵活,在一定程度上可以作为ORM的一种补充。数据库移植性差。便于统一管理与维护,降低了程序的耦合度

2. Mybatis对于事务的支持不太好。需要手动开启JDBC事务进行事务管理。在整个请求处理之前,创建事务工厂,基于同一个SqlSession对象获得事务对象,期间执行多次数据库更新操作,最后捕捉异常,进行事务回滚或关闭。

3. Mybatis的对象关联,分成:集合、关联

  一对多,多对多统称为集合。多对一,一对一统称为关联。

不管是集合还是关联,都有两种实现方式:

嵌套查询:分别编写两个查询sql,通过自定义resultMap中association或者collection标签的select引用,将查询嵌套起来

嵌套结果:编写联表查询sql,查询出需要的多表中的数据,分别通过不同的resultMap进行映射,并在主resultMap的association或者collection标签的resultMap中,将结果映射嵌套起来

嵌套查询可能会出现1+N次查询的问题,可以通过延迟加载来尽量减少性能的影响。嵌套结果会使查询数据过多,并且不能延迟加载。所以通常使用嵌套查询更多些。


12.JDBC编程有哪些不足之处,MyBatis是如何解决这些问题的?

① 数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。

解决:在SqlMapConfig.xml中配置数据链接池,使用连接池管理数据库链接。

② Sql语句写在代码中造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码。

解决:将Sql语句配置在XXXXmapper.xml文件中与java代码分离。

③ 向sql语句传参数麻烦,因为sql语句的where条件不一定,可能多也可能少,占位符需要和参数一一对应。

解决: Mybatis自动将java对象映射至sql语句。

④ 对结果集解析麻烦,sql变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成pojo对象解析比较方便。

解决:Mybatis自动将sql执行结果映射至java对象。


13.MyBatis编程步骤是什么样的?

① 创建SqlSessionFactory

②通过SqlSessionFactory创建SqlSession

③ 通过sqlsession执行数据库操作

④ 调用session.commit()提交事务

⑤ 调用session.close()关闭会话


14.使用MyBatis的mapper接口调用时有哪些要求?

①  Mapper接口方法名和mapper.xml中定义的每个sql的id相同

②  Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同

③  Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同

④  Mapper.xml文件中的namespace即是mapper接口的类路径。


16.SqlMapConfig.xml中配置有哪些内容?

SqlMapConfig.xml中配置的内容和顺序如下: 

properties(属性)

settings(配置)

typeAliases(类型别名)

typeHandlers(类型处理器)

objectFactory(对象工厂)

plugins(插件)

environments(环境集合属性对象)

environment(环境子属性对象)

transactionManager(事务管理)

dataSource(数据源)

mappers(映射器)


17.Mapper编写有哪几种方式?

①接口实现类继承SqlSessionDaoSupport

        使用此种方法需要编写mapper接口,mapper接口实现类、mapper.xml文件

    1、在sqlMapConfig.xml中配置mapper.xml的位置

            <mappers>

                      <mapper resource="mapper.xml文件的地址" />

                       <mapper resource="mapper.xml文件的地址" />

            </mappers>

    2、定义mapper接口

    3、实现类集成SqlSessionDaoSupport

            mapper方法中可以this.getSqlSession()进行数据增删改查。

    4、spring 配置

        <bean id=" " class="mapper接口的实现">

                <property name="sqlSessionFactory" ref="sqlSessionFactory"></property>

         </bean>

②使用org.mybatis.spring.mapper.MapperFactoryBean

1、在sqlMapConfig.xml中配置mapper.xml的位置

如果mapper.xml和mappre接口的名称相同且在同一个目录,这里可以不用配置

<mappers>

    <mapper resource="mapper.xml文件的地址" />

    <mapper resource="mapper.xml文件的地址" />

</mappers>

2、定义mapper接口

注意

1、mapper.xml中的namespace为mapper接口的地址

2、mapper接口中的方法名和mapper.xml中的定义的statement的id保持一致

3、 Spring中定义

<bean id="" class="org.mybatis.spring.mapper.MapperFactoryBean">

    <property name="mapperInterface"   value="mapper接口地址" />  

    <property name="sqlSessionFactory" ref="sqlSessionFactory" />  

</bean>

③使用mapper扫描器

1、mapper.xml文件编写,

注意:

mapper.xml中的namespace为mapper接口的地址

mapper接口中的方法名和mapper.xml中的定义的statement的id保持一致

如果将mapper.xml和mapper接口的名称保持一致则不用在sqlMapConfig.xml中进行配置 

2、定义mapper接口

注意mapper.xml的文件名和mapper的接口名称保持一致,且放在同一个目录

3、配置mapper扫描器

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">

    <property name="basePackage" value="mapper接口包地址"></property>

    <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/> 

</bean>

4、使用扫描器后从spring容器中获取mapper的实现对象

扫描器将接口通过代理方法生成实现对象,要spring容器中自动注册,名称为mapper 接口的名称。


18.Mybaits动态查询(动态SQL)

有时候我们并不想应用所有的条件,而只是想从多个选项中选择一个。如果直接写静态的SQL语句,可能会引起SQL语句的报错,比如在where条件语句后面多了个,拼接等等,这时候就需要采用动态sql标签来拼接动态的SQl语句执行查询。Mybatis提供了9种动态sql标签:trim | where | set | foreach | if | choose | when | otherwise | bind。

If条件:<if>元素被用来有条件地嵌入SQL片段,如果测试条件被赋值为true, 则相应地SQL片段将会被添加到SQL语句中。

choose,when 和 otherwise 条件:有点类似于Java中的switch选择结构,我们【需要只使用其中一种】查询类别。

Where 条件:所有的查询条件应该是可选的。在需要使用至少一种查询条件的情况下,我们应该使用WHERE子句。并且如果有多个条件,我们需要在条件中添加AND或OR。 MyBatis提供了<where>元素支持这种类型的动态SQL语句。

<trim>条件:<trim>元素和<where>元素类似,但是<trim>提供了在添加前缀/后缀或者移除前缀/后缀方面提供更大的灵活性。

foreach 循环:另外一个强大的动态SQL语句构造标签即是<foreach>。它可以迭代遍历一个数组或者列表,构造AND/OR条件或一个IN子句。

set 条件:<set>元素和<where>元素类似,如果其内部条件判断有任何内容返回时,他会插入SET SQL 片段。


19.如何获取自动生成的(主)键值?

insert 方法总是返回一个int值 ,这个值代表的是插入的行数。

如果采用自增长策略,自动生成的键值在 insert 方法执行完后可以被设置到传入的参数对象中。


20.在mapper中如何传递多个参数?

未完待续。。。。将不定时更新

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,175评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,674评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,151评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,597评论 1 269
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,505评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,969评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,455评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,118评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,227评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,213评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,214评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,928评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,512评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,616评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,848评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,228评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,772评论 2 339