Mybatis整理

Mybatis

定义

Mybatis是一个半ORM(对象关系映射)框架,它内部封装了JDBC,加载驱动、创建连接、创建statement等繁杂的过程,开发者开发时只需要关注如何编写SQL语句,可以严格控制sql执行性能,灵活度高。

作为一个半ORM框架,MyBatis 可以使用 XML 或注解来配置和映射原生信息,将 POJO映射成数据库中的记录,避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。

通过xml 文件或注解的方式将要执行的各种 statement 配置起来,并通过java对象和 statement中sql的动态参数进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射为java对象并返回。(从执行sql到返回result的过程)。

优缺点

优点
  • 基于SQL语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任何影响,SQL写在XML里,解除sql与程序代码的耦合,便于统一管理;提供XML标签,支持编写动态SQL语句,并可重用。
  • 与JDBC相比,减少了50%以上的代码量,消除了JDBC大量冗余的代码,不需要手动开关连接;
  • 很好的与各种数据库兼容(因为MyBatis使用JDBC来连接数据库,所以只要JDBC支持的数据库MyBatis都支持)。
  • 能够与Spring很好的集成;
  • 提供映射标签,支持对象与数据库的ORM字段关系映射;提供对象关系映射标签,支持对象关系组件维护。
缺点
  • SQL语句的编写工作量较大,尤其当字段多、关联表多时,对开发人员编写SQL语句的功底有一定要求。
  • SQL语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。

Hibernate 和 MyBatis 的区别

相同点

都是对jdbc的封装,都是持久层的框架,都用于dao层的开发。

不同点
  1. Mybatis 和 hibernate 不同,它不完全是一个 ORM 框架,因为 MyBatis 需要 程序员自己编写 Sql 语句。

  2. Mybatis 直接编写原生态 sql,可以严格控制 sql 执行性能,灵活度高,非常 适合对关系数据模型要求不高的软件开发,因为这类软件需求变化频繁,一但需 求变化要求迅速输出成果。但是灵活的前提是 mybatis 无法做到数据库无关性, 如果需要实现支持多种数据库的软件,则需要自定义多套 sql 映射文件,工作量大。

  3. Hibernate 对象/关系映射能力强,数据库无关性好,对于关系模型要求高的 软件,如果用 hibernate 开发可以节省很多代码,提高效率

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

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

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

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

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

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

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

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

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

MyBatis编程步骤是什么样的?

1、创建SqlSessionFactory

2、通过SqlSessionFactory创建SqlSession

3、 通过sqlsession执行数据库操作

4、 调用session.commit()提交事务

5、 调用session.close()关闭会话

#{}和${}的区别

#{}是占位符,预编译处理;${}是拼接符,字符串替换,没有预编译处理。

Mybatis在处理#{}时,#{}传入参数是以字符串传入,会将SQL中的#{}替换为?号,调用PreparedStatement的set方法来赋值。

变量替换后,#{} 对应的变量自动加上单引号 ‘’;变量替换后,${} 对应的变量不会加上单引号 ‘’

#{} 可以有效的防止SQL注入,提高系统安全性;${} 不能防止SQL 注入

#{} 的变量替换是在DBMS 中;${} 的变量替换是在 DBMS 外

通常一个Xml映射文件,都会写一个Dao接口与之对应,那么这个Dao接口的工作原理是什么?Dao接口里的方法、参数不同时,方法能重载吗?

Dao接口即Mapper接口。接口的全限名就是映射文件中的namespace的值;接口的方法名,就是映射文件中Mapper的Statement的id值;接口方法内的参数,就是传递给sql的参数。Mapper接口是没有实现类的,当调用接口方法时,接口全限名+方法名的拼接字符串作为key值,可唯一定位一个MapperStatement。

Dao接口里的方法,是不能重载的,因为是全限名+方法名的保存和寻找策略。如果重载可能会出现相同的id发生id冲突和错误。

Dao接口的工作原理是JDK动态代理,Mybatis运行时会使用JDK动态代理为Dao接口生成代理proxy对象,代理对象proxy会拦截接口方法,转而执行MappedStatement所代表的sql,然后将sql执行结果返回。

在Mapper中如何传递多个参数?

1、若Dao层函数有多个参数,那么其对应的xml中,#{0}代表接收的是Dao层中的第一个参数,#{1}代表Dao中的第二个参数,以此类推。

2、使用@Param注解:在Dao层的参数中前加@Param注解,注解内的参数名为传递到Mapper中的参数名。

3、多个参数封装成Map,以HashMap的形式传递到Mapper中。

Mybatis动态sql有什么用?执行原理是什么?有哪些动态sql?

Mybatis动态sql是一种可以根据不同的参数条件来动态拼接sql语句的功能。它可以让开发者在xml文件里以标签的形式编写动态sql。更灵活地控制sql的执行,避免写出冗余或不合法的sql语句。Mybatis提供了9种动态sql标签,分别是:

  • if:根据表达式的值判断是否拼接某个sql片段。
  • choose:类似于Java中的switch语句,从多个when子句中选择一个满足条件的执行,如果都不满足,就执行otherwise子句。
  • trim:用于修改sql语句的前缀或后缀,可以添加或移除某些字符。
  • where:用于生成where子句,只有当至少有一个子元素返回sql片段时才插入where,并且会自动去除多余的and或or。
  • set:用于生成set子句,用于动态更新语句,只有当至少有一个子元素返回sql片段时才插入set,并且会自动去除多余的逗号。
  • foreach:用于遍历集合或数组,生成in条件或批量插入语句。
  • bind:用于创建OGNL表达式以外的变量,可以在后面的sql语句中引用。
  • when:配合choose使用,表示一个分支条件。
  • otherwise:配合choose使用,表示默认分支条件。

Mybatis动态sql的执行原理是基于OGNL表达式和XML解析技术。Mybatis会从sql参数对象中计算OGNL表达式的值,并根据值的结果动态拼接sql语句。然后,Mybatis会使用XML解析器解析XML映射文件中的动态sql标签,并生成对应的sql节点。最后,Mybatis会将sql节点转换为可执行的PreparedStatement对象,并执行数据库操作。

xml映射文件中,不同的xml映射文件id是否可以重复?

不同的xml映射文件,如果配置了namespace,那么id可以重复;如果没有配置namespace,那么id不能重复;

原因是namespace+id是作为Map的key使用的,如果没有namespace,就剩下id,那么id重复会导致数据互相覆盖。有了namespace,自然id就可以重复,namespace不同,namespace+id自然也不同。

Mybatis实现一对一有几种方式?具体是怎么操作的?

有联合查询和嵌套查询两种方式。

联合查询是几个表联合查询,通过在resultMap里面配置association节点配置一对一的类就可以完成;

嵌套查询是先查一个表,根据这个表里面的结果的外键id,再去另外一个表里面查询数据,也是通过association配置,但另外一个表的查询是通过select配置的。

Mybatis实现一对多有几种方式?具体是怎么操作的?

有联合查询和嵌套查询两种方式。

联合查询是几个表联合查询,只查询一次,通过在resultMap里面的collection节点配置一对多的类就可以完成;

嵌套查询是先查一个表,根据这个表里面的结果的外键id,再去另外一个表里面查询数据,也是通过collection,但另外一个表的查询是通过select配置的。

Mybatis一级,二级缓存

根据web搜索结果,Mybatis的一级缓存和二级缓存的区别如下:

  • 一级缓存是SqlSession级别的缓存,缓存的数据只在SqlSession内有效,当SqlSession关闭或者执行增删改操作时,缓存会被清空。一级缓存默认是开启的,可以通过设置localCacheScope为STATEMENT来关闭。
  • 二级缓存是mapper级别的缓存,同一个namespace下的所有操作语句,都影响着同一个Cache,即二级缓存被多个SqlSession共享。二级缓存默认是关闭的,需要在mapper.xml中配置标签来开启。
  • 一级缓存和二级缓存的查询顺序是:二级缓存 -> 一级缓存 -> 数据库。当开启二级缓存后,会使用CachingExecutor装饰Executor,先在CachingExecutor中进行二级缓存的查询,再进入一级缓存的查询流程。
  • 一级缓存和二级缓存都可以提高查询效率,避免频繁访问数据库。但是也要注意缓存数据的更新和失效问题,避免出现脏读或者不一致的情况。

使用MyBatis的Mapper接口调用时有哪些要求?

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

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

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

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

hotspot比jit

zing虚拟机

https://blog.csdn.net/21aspnet/article/details/88667880

原生代码(Native Code)是电脑的CPU可直接解读的数据,也就是机器码(machine code)。原生代码是计算机可以直接执行,并且执行速度最快的代码。字节码(Bytecode)是一种中间码,它比机器码更抽象,需要直译器转译后才能成为机器码的中间代码。字节码通常不像源码一样可以让人阅读,而是编码后的数值常量、引用、指令等构成的序列。字节码是解释器能够理解的代码,但是对于CPU来说,它是无法直接执行的。所以,字节码还需要被解释器转换成机器码才能被CPU执行。

原生代码比字节码效率高的原因是,原生代码不需要经过任何转换就可以被CPU直接执行,而字节码需要经过解释器的转换才能变成机器码,这个过程会消耗一定的时间和资源。另外,原生代码是针对特定平台和硬件优化过的,而字节码是与特定机器码无关的,所以原生代码可能会利用一些平台或硬件特有的优势来提高性能。

select
user_id,
count(*) daysCount
from
(
select distinct
user_id,
sales_date,
dense_rank() over (
partition by
user_id
order by
sales_date
) rn
from
sales_tb
) a
group by
user_id,
DATE_ADD (sales_date, INTERVAL - rn day)
having
daysCount >= 2
order by
user_id

你可能感兴趣的:(mybatis,oracle,tomcat)