撩课-Java每天5道面试题第16天
111.什么是乐观锁(Optimistic Locking)?
悲观锁,正如其名,
它指的是对数据被外界
包括本系统当前的其他事务,
以及来自外部系统的事务处理
修改持保守态度,
因此,在整个数据处理过程中,
将数据处于锁定状态。
悲观锁的实现,
往往依靠数据库提供的锁机制
也只有数据库层提供的锁机制才能真正保证数据访问的排他性,
否则,即使在本系统中实现了加锁机制,
也无法保证外部系统不会修改数据
乐观锁( Optimistic Locking )
相对悲观锁而言,
乐观锁假设认为数据
一般情况下不会造成冲突,
所以在数据进行提交更新的时候,
才会正式对数据的冲突与否进行检测,
如果发现冲突了,
则让返回用户错误的信息,
让用户决定如何去做
112.描述下Hibernate当中事务?
一、事务的并发问题 在实际应用中, 数据库是要被I多个用户共同访问的, 在多个事务同时使用相同的数据时, 可能会发生并发的问题, 具体为: 脏读: 一个事务读取到 另一个事务未提交的数据。 不可重复读: 一个事务对同一行数据 重复读取两次, 但是得到了不同的结果。 虚读: 一个事务连续两次在数据库进行同样条件的查询, 但是第二次查询结果包含了 第一次查询中未出现的数据。 (注意与不可重复读的区别) 更新丢失: 两个事物同时更新一行数据, 后提交(或撤销)的事务将前面事务 提交的数据都覆盖了。 第一类丢失更新: 是由于后面事务撤销将前面事务 修改的数据覆盖了 第二类丢失更新: 是由于后面事务更新将前面事务 修改的数据覆盖了 1、读未提交(1级,可防止更新丢失): 当一个事务进行写(更新)数据, 则另外一个事务不允许同时进行写(更新)数据, 但允许其他事务进行读数据, 即使是未提交的 (但这个不能防止脏读) 更新丢失是因为一个事务开始进行写事务, 另一个事务也可以进行写事务导致的。 2、读已提交(2级,可防止更新丢失、脏读): 读取数据的事务允许其他事务继续读取该数据, 但是未提交的写事务将会禁止其他事务访问改行。 脏读是由于读到未提及的数据 3、可重复读(4级,可防止不可重复读、脏读): 读取数据的事务禁止写事务, 写事务将禁止其他任何事务。 不可重复读是一个事务 对一行数据重复读取两次, 但是得到不同的结果; 脏读是读到未提交的数据 4、序列化(8级,防止一切并发问题): 提供严格的事务隔离。 事务只能一个接着一个执行, 不能并发执行 简单总结: 事务并发问题: (1)脏读 (2)不可重复读 (3)虚读 (4)更新丢失 事务隔离级别: (1)读未提交 (2)读已提交 (3)可重复读 (4)序列化 在hibernate.cfg.xml的标签配置: 使用本地事务还是全局事务,参数是: hibernate.current_session_context_class 值:thread(本地事务)、jta(全局事务) 设置事务隔离级别,参数是: hibernate.connection.isolation 当多个事务同时访问数据库中的相同数据时, 如果没有采取必要的隔离措施, 那么可以采用悲观锁或者是乐观锁对其进行控制。 悲观锁: 悲观地认为总是会有其他事务回来操作同一数据 因此在这个数据处理过程中, 将会把数据处于锁定状态。 比如读取数据时: User user = (User)session.get(User.class, "111111", LockMode.UPGRADE) 乐观锁: 认为事务同时操作同一个数据的情况很少发生, 所以乐观锁不做数据库层次的锁定, 而是基于数据版本标识 实现应用程序级别上的锁定机制。 原理:数据版本标识, 是指通过为数据表增加一个“version”字段, 实现在读取数据时, 将版本号一同独处, 之后更新次数据时, 将此版本号加一; 在提交数据时, 将现有的版本号 与数据表对应的记录的版本号进行对比, 如果提交数据的版本号大于数据表中的版本号, 则允许更新数据, 否则禁止更新数据。
113.Hibernate 中的缓存分为几层。
hibernate的缓存包括 Session的缓存和SessionFactory的缓存, 其中SessionFactory的缓存又可以分为两类: 内置缓存和外置缓存。 Session的缓存是内置的, 不能被卸载, 也被称为Hibernate的第一级缓存。 SessionFactory的内置缓存 和Session的缓存在实现方式上比较相似, 前者是SessionFactory对象的一些集合属性包含的数据, 后者是指Session的一些集合属性包含的数据。 SessionFactory的内置缓存中存放了 映射元数据和预定义SQL语句, 映射元数据是映射文件中数据的拷贝, 而预定义SQL语句是 在Hibernate初始化阶段根据 映射元数据推导出来, SessionFactory的内置缓存是只读的, 应用程序不能修改缓存中的映射元数据 和预定义SQL语句, 因此SessionFactory不需要进行内置缓存与映射文件的同步。 SessionFactory的外置缓存是一个可配置的插件。 在默认情况下,SessionFactory不会启用这个插件。 外置缓存的数据是数据库数据的拷贝, 外置缓存的介质可以是内存或者硬盘。 SessionFactory的外置缓存 也被称为Hibernate的第二级缓存
114.Entity Beans 的状态有哪些
瞬时(transient):
数据库中没有数据与之对应,
超过作用域会被JVM垃圾回收器回收,
一般是new出来且与session没有关联的对象。
持久(persistent):
数据库中有数据与之对应,
当前与session有关联,
并且相关联的session没有关闭,
事务没有提交;
持久对象状态发生改变,
在事务提交时会影响到数据库(hibernate能检测到)。
脱管(detached):
数据库中有数据与之对应,
但当前没有session与之关联;
托管对象状态发生改变,
hibernate不能检测到。
115.谈谈Hibernate中inverse的作用
Hibernate中的inverse 在表关系映射中经常应用 inverse的值有两种,“true”和“false”。 inverse="false"是默认的值 inverse的作用: 在hibernate中是通过inverse的设置 来决定是有谁来维护表和表之间的关系的。 我们说inverse设立不当会导致性能低下, 其实是说inverse设立不当, 会产生多余重复的SQL语句 甚至致使JDBC exception的throw。 这是我们在建立实体类关系时 必须需要关注的地方。 一般来说,inverse=true是推荐使用, 双向关联中双方都设置 inverse=false的话, 必会导致双方都重复更新同一个关系。 但是如果双方都设立inverse=true的话, 双方都不维护关系的更新, 这也是 不行的, 好在一对多中的一端: many-to-one默认是inverse=false, 避免了这种错误的产生。 但是多对多就没有这个默认设置了, 所以很 多人经常在多对多的两端都使用inverse=true, 结果导致连接表的数据根本没有记录, 就是因为他们双分都没有责任维护关系。 所以说,双向关联中最 好的设置 是一端为inverse=true, 一端为inverse=false。 一般inverse=false会放在多的一端, 那么有人提问了, many-to-many两边都是多的, inverse到底放在哪儿? 其实hibernate建立多对多关系 也是将他们分离成两个一对多关系, 中间连接一个连接表。 所以通用存在一对多的关系, 也可以这样说: 一对多是多对多的基本组成部分。