Hibernate工作原理及为什么要用?
- 原理:
- 1. 读取并解析配置文件
- 2. 读取并解析映射信息,创建SessionFactory
- 3. 打开Sesssion
- 4. 创建事务Transation
- 5. 持久化操作
- 6. 提交事务
- 7. 关闭Session
- 8. 关闭SesstionFactory
- 为什么要用:hibernate的性能非常好,因为它是个轻量级框架。映射的灵活性很出色。它支持各种关系数据库,从一对一到多对多的各种复杂关系。对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码。Hibernate是一个基于JDBC的主流持久化框架,是一个优秀的ORM实现,他很大程度的简化DAO层的编码工作hibernate使用Java反射机制,而不是字节码增强程序来实现透明性
Hibernate是如何延迟加载?
- 1. Hibernate2延迟加载实现:a)实体对象 b)集合(Collection)
- 2. Hibernate3 提供了属性的延迟加载功能
- 当Hibernate在查询数据的时候,数据并没有存在与内存中,当程序真正对数据的操作时,对象才存在与内存中,就实现了延迟加载,他节省了服务器的内存开销,从而提高了服务器的性能。
Hibernate中怎样实现类之间的关系?(如:一对多、多对多的关系)
- 类与类之间的关系主要体现在表与表之间的关系进行操作,它们都市对对象进行操作,我们程序中把所有的表与类都映射在一起,它们通过配置文件中的many-to-one、one-to-many、many-to-many
- 说下Hibernate的缓存机制
- 内部缓存存在Hibernate中又叫一级缓存,属于应用事物级缓存二级缓存:
- a)应用及缓存
- b)分布式缓存
- 条件:数据不会被第三方修改、数据大小在可接受范围、数据更新频率低、同一数据被系统频繁使用、非关键数据
- c) 第三方缓存的实现
- Hibernate的查询方式
- Sql、Criteria,objectcomptosition
- Hql:属性查询 参数查询、命名参数查询 关联查询 分页查询 统计函数
如何优化Hibernate?
- 使用双向一对多关联,不使用单向一对多 灵活使用单向一对多关联 不用一对一,用多对一取代 配置对象缓存,不使用集合缓存 一对多集合使用Bag,多对多集合使用Set 继承类使用显式多态 表字段要少,表关联不要怕多,有二级缓存撑腰
spring工作机制及为什么要用
- 1.spring mvc请所有的请求都提交给DispatcherServlet,它会委托应用系统的其他模块负责负责对请求进行真正的处理工作。
- 2.DispatcherServlet查询一个或多个HandlerMapping,找到处理请求的Controller.
- 3.DispatcherServlet请请求提交到目标Controller
- 4.Controller进行业务逻辑处理后,会返回一个ModelAndView
- 5.Dispathcher查询一个或多个ViewResolver视图解析器,找到ModelAndView对象指定的视图对象
- 6.视图对象负责渲染返回给客户端。
- 为什么用:
- AOP 让开发人员可以创建非行为性的关注点,称为横切关注点,并将它们插入到应用程序代码中。使用 AOP 后,公共服务(比如日志、持久性、事务等)就可以分解成方面并应用到域对象上,同时不会增加域对象的对象模型的复杂性。
- IOC 允许创建一个可以构造对象的应用环境,然后向这些对象传递它们的协作对象。正如单词倒置所表明的,IOC 就像反过来的 JNDI。没有使用一堆抽象工厂、服务定位器、单元素(singleton)和直接构造(straight construction),每一个对象都是用其协作对象构造的。因此是由容器管理协作对象(collaborator)。
- Spring即使一个AOP框架,也是一IOC容器。 Spring 最好的地方是它有助于您替换对象。有了 Spring,只要用 JavaBean 属性和配置文件加入依赖性(协作对象)。然后可以很容易地在需要时替换具有类似接口的协作对象
在数据库中条件查询速度很慢的时候,如何优化
- 1.建索引
- 2.减少表之间的关联
- 3.优化sql,尽量让sql很快定位数据,不要让sql做全表查询,应该走索引,把数据量大的表排在前面
- 4.简化查询字段,没用的字段不要,已经对返回结果的控制,尽量返回少量数据
- 在hibernate中进行多表查询,每个表中各取几个字段,也就是说查询出来的结果集并没有一个实体类与之对应,如何解决这个问题
- 解决方案一,按照Object[]数据取出数据,然后自己组bean
- 解决方案二,对每个表的bean写构造函数,比如表一要查出field1,field2两个字段,那么有一个构造函数就是Bean(type1 filed1,type2 field2) ,然后在hql里面就可以直接生成这个bean了
hibernate的核心类是什么,它们的相互关系是什么?重要的方法是什么?
- Configuration
- SessionFactory
- Session如下方法
- Save
- Load
- Update
- Delete
Hibernate中数据表映射关系主要有什么类型
- one-to-many
- inverse:主控方,外键的关系有谁控制
- inverse=false 是主控方,外键是由它控制的
- inverse=true 是被控方,外键与它没关系
- 要想实现主控方的控制必须将被控方作为主控方的属性
- cascade:级联
- 主表增从表增
- 主表修从表修
- 主表删从表删
- lazy:延迟
- lazy=false:一下将所有的内容取出,不延时(常用)
- lazy=true:取出部分内容,其余内容动态去取
- 通过get可以取出对方的所有内容
jdbc、Hibernate、ibatis的区别
- jdbc:手动,手动写sql
- delete、insert、update要将对象的值一个一个取出传到sql中,不能直接传入一个对象 select:返回的是一个resultset,要从ResultSet中一行一行、一个字段一个字段的取出 然后封装到一个对象中,不直接返回一个对象。
- ibatis的特点:半自动化
- sql要手动写
- delete、insert、update:直接传入一个对象
- select:直接返回一个对象
- hibernate:全自动
- 不写sql,自动封装
- delete、insert、update:直接传入一个对象
- select:直接返回一个对象
Hibernate的三种状态
- 瞬时态(Transient)、持久态(Persistent)、脱管态(Detached)。处于持久态的对象也称为PO(Persistence Object),瞬时对象和脱管对象也称为VO(Value Object)。
- 瞬时态
- 由new命令开辟内存空间的java对象,
- eg. Person person = new Person(“amigo”, “女”);
- 如果没有变量对该对象进行引用,它将被java虚拟机回收。
- 瞬时对象在内存孤立存在,它是携带信息的载体,不和数据库的数据有任何关联关系,在Hibernate中,可通过session的save()或saveOrUpdate()方法将瞬时对象与数据库相关联,并将数据对应的插入数据库中,此时该瞬时对象转变成持久化对象。
- 持久态
- 处于该状态的对象在数据库中具有对应的记录,并拥有一个持久化标识。如果是用hibernate的delete()方法,对应的持久对象就变成瞬时对象,因数据库中的对应数据已被删除,该对象不再与数据库的记录关联。
- 当一个session执行close()或clear()、evict()之后,持久对象变成脱管对象,此时持久对象会变成脱管对象,此时该对象虽然具有数据库识别值,但它已不在HIbernate持久层的管理之下。
- 持久对象具有如下特点:
- 1. 和session实例关联;
- 2. 在数据库中有与之关联的记录。
- 脱管态
- 当与某持久对象关联的session被关闭后,该持久对象转变为脱管对象。当脱管对象被重新
- 关联到session上时,并再次转变成持久对象。
- 脱管对象拥有数据库的识别值,可通过update()、saveOrUpdate()等方法,转变成持久对象。 脱管对象具有如下特点:
- 1. 本质上与瞬时对象相同,在没有任何变量引用它时,JVM会在适当的时候将它回收;
- 2. 比瞬时对象多了一个数据库记录标识值。
谈谈Hibernate中inverse的作用
- inverse属性默认是false,就是说关系的两端都来维护关系。
- 比如Student和Teacher是多对多关系,用一个中间表TeacherStudent维护。Gp)i
- 如果Student这边inverse=”true”, 那么关系由另一端Teacher维护,就是说当插入Student时,不会操作TeacherStudent表(中间表)。只有Teacher插入或删除时才会触发对中间表的操作。所以两边都inverse=”true”是不对的,会导致任何操作都不触发对中间表的影响;当两边都 inverse=”false”或默认时,会导致在中间表中插入两次关系。3种:hql、QBC——Query By Criteria API、原生sql(通过createSQLQuery建立)
- 说说Hibernate中的update()和saveOrUpdate()的区别,session的load()和get()的区别。
- saveOrUpdate()方法可以实现update()的功能,但会多些步骤,具体如下:
- 如果对象在该session中已经被持久化,不进行操作;对象的标识符属性(identifier property)在数据库中不存在或者是个暂时的值,调用save()方法保存它;如果session中的另一个对象有相同的标识符抛出一个异常;以上皆不符合则调用update()更新之。
- Session.load/get方法均可以根据指定的实体类和id从数据库读取记录,并返回与之对应的实体对象。其区别在于:
- 如果未能发现符合条件的记录,get方法返回null,而load方法会抛出一个
- ObjectNotFoundException;load方法可返回实体的代理类实例,而get方法永远直接返回实体类;load方法可以充分利用内部缓存和二级缓存中的现有数据,而get方法则仅仅在内部缓存中进行数据查找,如没有发现对应数据,将越过二级缓存,直接调用SQL完成数据读取
Hibernate都支持哪些缓存策略,比较它们的优缺点
- Read-only: 这种策略适用于那些频繁读取却不会更新的数据,这是目前为止最简单和最有效的缓存策略
- Read/write:这种策略适用于需要被更新的数据,比read-only更耗费资源,在非JTA环境下,每个事务需要在session.close和session.disconnect()被调用
- Nonstrict read/write: 这种策略不保障两个同时进行的事务会修改同一块数据,这种策略适用于那些经常读取但是极少更新的数据
- Transactional: 这种策略是完全事务化得缓存策略,可以用在JTA环境下
如何查看Hibernate生成并执行的sql
- 在定义数据库和数据库属性的文件applicationConfig.xml里面,把hibernate.show_sql设置为true
- 这样生成的SQL就会在控制台出现了
- 注意:这样做会加重系统的负担,不利于性能调优
比较Hibernate的三种检索策略优缺点
- 1立即检索;
- 优点:对应用程序完全透明,不管对象处于持久化状态,还是游离状态,应用程序都可以方便的从一个对象导航到与它关联的对象;
- 缺点:1.select语句太多;2.可能会加载应用程序不需要访问的对象白白浪费许多内存空间;
- 2延迟检索:
- 优点:由应用程序决定需要加载哪些对象,可以避免可执行多余的select语句,以及避免加载应用程序不需要访问的对象。因此能提高检索性能,并且能节省内存空间;
- 缺点:应用程序如果希望访问游离状态代理类实例,必须保证他在持久化状态时已经被初始化;
- 3 迫切左外连接检索
- 优点:1对应用程序完全透明,不管对象处于持久化状态,还是游离状态,应用程序都可以方便地冲一个对象导航到与它关联的对象。2使用了外连接,select语句数目少;
- 缺点:1 可能会加载应用程序不需要访问的对象,白白浪费许多内存空间;2复杂的数据库表连接也会影响检索性能;
什么是Hibernate并发机制怎么处理并发问题
- a、Hibernate的Session对象是非线程安全的,对于单个请求,单个会话,单个的工作单元(即单个事务,单个线程),它通常只使用一次,
- 然后就丢弃。
- 如果一个Session 实例允许共享的话,那些支持并发运行的,例如Http request,session beans将会导致出现资源争用。
- 如果在Http Session中有hibernate的Session的话,就可能会出现同步访问Http Session。只要用户足够快的点击浏览器的“刷新”,就会导致两个并发运行的线程使用同一个Session。
- b、多个事务并发访问同一块资源,可能会引发第一类丢失更新,脏读,幻读,不可重复读,第二类丢失更新一系列的问题。
- 解决方案:设置事务隔离级别。
- Serializable:串行化。隔离级别最高
- Repeatable Read:可重复读
- Read Committed:已提交数据读
- Read Uncommitted:未提交数据读。隔离级别最差
- c、设置锁:乐观锁和悲观锁。
- 乐观锁:使用版本号或时间戳来检测更新丢失,在的映射中设置 optimistic-lock=”all”可以在没有版本或者时间戳属性映射的情况下实现 版本检查,此时Hibernate将比较一行记录的每个字段的状态 行级悲观锁:Hibernate总是使用数据库的锁定机制,从不在内存中锁定对象!只要为JDBC连接指定一下隔 离级别,然后让数据库去搞定一切就够了。
类LockMode 定义了Hibernate所需的不同的锁定级别
LockMode.UPGRADE,LockMode.UPGRADE_NOWAIT,LockMode.READ;