91,什么是 ORM?
对象关系映射(Object-Relational Mapping,简称 ORM)是一种为了解决程序的面向对象模型与数据库的关系模型互不匹配问题的技术;
简单的说,ORM 是通过使用描述对象和数据库之间映射的元数据(在 Java 中可以用 XML 或者是注解),将程序中的对象自动持久化到关系数据库中或者将关系数据库表中的行转换成 Java 对象,其本质上就是将数据从一种形式转换到另外一种形式。
92,Hibernate 中 SessionFactory 是线程安全的吗?Session 是线程安全的吗(两个线程能够共享同一个 Session 吗)?
SessionFactory 对应 Hibernate 的一个数据存储的概念,它是线程安全的,可以被多个线程并发访问。SessionFactory 一般只会在启动的时候构建。对于应用程序,最好将 SessionFactory 通过单例模式进行封装以便于访问。
Session 是一个轻量级非线程安全的对象(线程间不能共享 session),它表示与数据库进行交互的一个工作单元。Session 是由 SessionFactory 创建的,在任务完成之后它会被关闭。Session 是持久层服务对外提供的主要接口。
Session 会延迟获取数据库连接(也就是在需要的时候才会获取)。为了避免创建太多的 session,可以使用 ThreadLocal 将 session 和当前线程绑定在一起,这样可以让同一个线程获得的总是同一个 session。Hibernate 3 中 SessionFactory 的 getCurrentSession() 方法就可以做到。
93,Session 的 save()、update()、merge()、lock()、saveOrUpdate() 和 persist() 方法分别是做什么的?有什么区别?
Hibernate 的对象有三种状态:瞬时态(transient)、持久态(persistent)和游离态(detached)。
瞬时态的实例可以通过调用 save()、persist() 或者 saveOrUpdate() 方法变成持久态;
游离态的实例可以通过调用 update()、saveOrUpdate()、lock() 或者 replicate() 变成持久态。save() 和 persist() 将会引发 SQL 的 INSERT 语句,而 update() 或 merge() 会引发 UPDATE 语句。
save() 和 update() 的区别在于一个是将瞬时态对象变成持久态,一个是将游离态对象变为持久态。merge() 方法可以完成 save() 和 update() 方法的功能,它的意图是将新的状态合并到已有的持久化对象上或创建新的持久化对象。
对于 persist() 方法,按照官方文档的说明:
1、persist() 方法把一个瞬时态的实例持久化,但是并不保证标识符被立刻填入到持久化实例中,标识符的填入可能被推迟到 flush 的时间;
2、persist() 方法保证当它在一个事务外部被调用的时候并不触发一个 INSERT 语句,当需要封装一个长会话流程的时候,persist() 方法是很有必要的;
3、save() 方法不保证第 2 条,它要返回标识符,所以它会立即执行 INSERT 语句,不管是在事务内部还是外部。至于 lock() 方法和 update() 方法的区别,update() 方法是把一个已经更改过的脱管状态的对象变成持久状态;lock() 方法是把一个没有更改过的脱管状态的对象变成持久状态。
94,阐述 Session 加载实体对象的过程。
1、Session 在调用数据库查询功能之前,首先会在一级缓存中通过实体类型和主键进行查找,如果一级缓存查找命中且数据状态合法,则直接返回;
2、如果一级缓存没有命中,接下来 Session 会在当前 NonExists 记录(相当于一个查询黑名单,如果出现重复的无效查询可以迅速做出判断,从而提升性能)中进行查找,如果 NonExists 中存在同样的查询条件,则返回 null;
3、如果一级缓存查询失败查询二级缓存,如果二级缓存命中直接返回;
4、如果之前的查询都未命中,则发出 SQL 语句,如果查询未发现对应记录则将此次查询添加到 Session 的 NonExists 中加以记录,并返回 null;
5、根据映射配置和 SQL 语句得到 ResultSet,并创建对应的实体对象;
6、将对象纳入 Session(一级缓存)的管理;
7、如果有对应的拦截器,则执行拦截器的 onLoad 方法;
8、如果开启并设置了要使用二级缓存,则将数据对象纳入二级缓存;
9、返回数据对象。
95,MyBatis 中使用 #和 $ 书写占位符有什么区别?
#将传入的数据都当成一个字符串,会对传入的数据自动加上引号;
$ 将传入的数据直接显示生成在 SQL 中。
注意:使用 $ 占位符可能会导致 SQL 注射攻击,能用 #的地方就不要使用 $,写 order by 子句的时候应该用 $ 而不是 #。
96,解释一下 MyBatis 中命名空间(namespace)的作用。
在大型项目中,可能存在大量的 SQL 语句,这时候为每个 SQL 语句起一个唯一的标识(ID)就变得并不容易了。为了解决这个问题,在 MyBatis 中,可以为每个映射文件起一个唯一的命名空间,这样定义在这个映射文件中的每个 SQL 语句就成了定义在这个命名空间中的一个 ID。只要我们能够保证每个命名空间中这个 ID 是唯一的,即使在不同映射文件中的语句 ID 相同,也不会再产生冲突了。
97、MyBatis 中的动态 SQL 是什么意思?
对于一些复杂的查询,我们可能会指定多个查询条件,但是这些条件可能存在也可能不存在,如果不使用持久层框架我们可能需要自己拼装 SQL 语句,不过 MyBatis 提供了动态 SQL 的功能来解决这个问题。MyBatis 中用于实现动态 SQL 的元素主要有:
- if - choose / when / otherwise - trim - where - set - foreach
用法举例:
- id="foo" parameterType="Blog" resultType="Blog">
- select * from t_blog where 1 = 1
- test="title != null">
- and title = #{title}
- test="content != null">
- and content = #{content}
- test="owner != null">
- and owner = #{owner}
1、JDBC:数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。
MyBatis:在 SqlMapConfig.xml 中配置数据链接池,使用连接池管理数据库链接。
2、JDBC:Sql 语句写在代码中造成代码不易维护,实际应用 sql 变化的可能较大,sql 变动需要改变 java 代码。
MyBatis:将 Sql 语句配置在 XXXXmapper.xml 文件中与 java 代码分离。
3、JDBC:向 sql 语句传参数麻烦,因为 sql 语句的 where 条件不一定,可能多也可能少,占位符需要和参数一一对应。
MyBatis: Mybatis 自动将 java 对象映射至 sql 语句。
4,JDBC:对结果集解析麻烦,sql 变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成 pojo 对象解析比较方便。
MyBatis:Mybatis 自动将 sql 执行结果映射至 java 对象。
1、Mybatis 和 hibernate 不同,它不完全是一个 ORM 框架,因为 MyBatis 需要程序员自己编写 Sql 语句,不过 mybatis 可以通过 XML 或注解方式灵活配置要运行的 sql 语句,并将 java 对象和 sql 语句映射生成最终执行的 sql,最后将 sql 执行的结果再映射生成 java 对象。
2、Mybatis 学习门槛低,简单易学,程序员直接编写原生态 sql,可严格控制 sql 执行性能,灵活度高,非常适合对关系数据模型要求不高的软件开发,例如互联网软件、企业运营类软件等,因为这类软件需求变化频繁,一但需求变化要求成果输出迅速。但是灵活的前提是 mybatis 无法做到数据库无关性,如果需要实现支持多种数据库的软件则需要自定义多套 sql 映射文件,工作量大。 3、Hibernate 对象 / 关系映射能力强,数据库无关性好,对于关系模型要求高的软件(例如需求固定的定制化软件)如果用 hibernate 开发可以节省很多代码,提高效率。但是 Hibernate 的缺点是学习门槛高,要精通门槛更高,而且怎么设计 O/R 映射,在性能和对象模型之间如何权衡,以及怎样用好 Hibernate 需要具有很强的经验和能力才行。
总之,按照用户的需求在有限的资源环境下只要能做出维护性、扩展性良好的软件架构都是好架构,所以框架只有适合才是最好。
(这里也可以结合自己的理解说,别说的收不住)
Mybatis 首先去缓存中查询结果集,如果没有则查询数据库,如果有则从缓存取出返回结果集就不走数据库。Mybatis 内部存储缓存使用一个 HashMap,key 为 hashCode+sqlId+Sql 语句。value 为从查询出来映射生成的 java 对象
Mybatis 的二级缓存即查询缓存,它的作用域是一个 mapper 的 namespace,即在同一个 namespace 中查询 sql 可以从缓存中获取数据。二级缓存是可以跨 SqlSession 的。
转自 http://www.cnblogs.com/peke/p/7887626.html
来源: http://www.bubuko.com/infodetail-2428604.html