(1)、hibernate是封装了jdbc的一个面向关系映射(ORM)的数据库链接方式;而JDBC是一个关系型数据库链接方式;java
(2)、JDBC与hibernate链接数据库的方式大体相同,但hibernate将配置信息写在XML中;spring
(3)、hibernate用HQL查询,结果返回的是List<Object>,而JDBC用SQL查询,结果返回的是ResultSet,要经过bean方式封装到对象中;数据库
(4)、hibernate的 HQL语句有专门的Dao层,而JDBC没有,这样当数据库修改时,hibernate只须要修改Dao层便可,而JDBC修改的代码量就多不少;apache
(5)、当处理一样的SQL语句时,hibernate不会重复处理,而JDBC每一次都要进行处理,这样hibernate的效率就远远高于JDBC;编程
(6)、JDBC在性能上,灵活性比hibernate要好,当对多表或者复杂的数据库进行操做时,用JDBC好;缓存
(7)、“精心编写”的JDBC必定是性能最好的。再级联关系较多的时候,用hibernate应该比jdbc强,安全
(8)、用hibernate大大减小了代码量的编写;服务器
1.struts是控制页面跳转;struts是控制层和视图层,负责JSP页面的展现和交互。session
2.hibernate负责和数据库的链接与操做;hibernate 是持久化层,负责数据的存储和检索。并发
3.Spring 减 少耦合,功能完成的层次分的很清楚;Spring是业务逻辑层,负责具体业务逻辑的实现,核心是IOC 和面向AOP 编程,spring与struts和hibernate整合后,做为一个IoC容器,所以能够对struts和hibernate实施监控;能够作安全, 日志等一系列AOP的工做。
1 客户端初始化一个指向Servlet容器(例如Tomcat)的请求
2 这 个请求通过一系列的过滤器(Filter),FilterDispatcher被调用,FilterDispatcher询问ActionMapper来 决定这个请是否须要调用某个Action,ActionServlet类是关键的控制器部件,全部的Action都继承自 org.apache.struts.ation.Action类;
3 若是ActionMapper决定须要调用某个Action,FilterDispatcher把请求的处理交给Action执行,执行完毕, struts.xml中的配置找到对应的返回结果。
1) 在 Action实现类方面的对比:Struts 1要求Action类继承一个抽象基类; Struts 2 Action类能够实现一个Action接口,也能够实现其余接口,使可选和定制的服务成为可能。Struts 2提供一个ActionSupport基类去实现经常使用的接口。即便Action接口不是必须实现的,只有一个包含execute方法的POJO类均可以用 做Struts 2的Action。
2) 线程模式方面的对比:Struts 1 Action是单例模式而且必须是线程安全的,由于仅有Action的一个实例来处理全部的请求。单例策略限制了Struts 1 Action能作的事,而且要在开发时特别当心。Action资源必须是线程安全的或同步的;Struts 2 Action对象为每个请求产生一个实例,所以没有线程安全问题。
3) Servlet依赖方面的对比:Struts 1 Action依赖于Servlet API,由于Struts 1 Action的execute方法中有HttpServletRequest和HttpServletResponse方法。Struts 2 Action再也不依赖于Servlet API,从而容许Action脱离Web容器运行,从而下降了测试Action的难度。 固然,若是Action须要直接访问HttpServletRequest和HttpServletResponse参数,Struts 2 Action仍然能够访问它们。大部分时候Action都无需直接访问HttpServetRequest和HttpServletResponse,从 而给开发者更多灵活的选择。
4) 封装请求参数的对比:Struts 1使用ActionForm对象封装用户的请求参数,全部的ActionForm必须继承一个基类:ActionForm。普通的JavaBean不能用 做ActionForm,所以,开发者必须建立大量的ActionForm类封装用户请求参数。虽然Struts 1提供了动态ActionForm来简化ActionForm的开发,但依然须要在配置文件中定义ActionForm;Struts 2直接使用Action属性来封装用户请求属性,避免了开发者须要大量开发ActionForm类的烦琐, Struts 2提供了Model Driven模式,可让开发者使用单独的Model对象来封装用户请求参数,但该Model对象无需继承任何Struts 2基类,是一个POJO,从而下降了代码污染。
5) 表达式语言方面的对比:Struts 1整合了JSTL,所以可使用JSTL表达式语言。这种表达式语言有基本对象图遍历,但在对集合和索引属性的支持上则功能不强;Struts 2可使用JSTL,但它整合了一种更强大和灵活的表达式语言:OGNL,所以Struts 2下的表达式语言功能更增强大。
6) 类型转换的对比:Struts 1 ActionForm 属性一般都是String类型。Struts 1使用Commons-Beanutils进行类型转换,每一个类一个转换器,转换器是不可配置的;Struts 2使用OGNL进行类型转换,支持基本数据类型和经常使用对象之间的转换。
7) Action执行控制的对比:Struts 1支持每个模块对应一个请求处理,可是模块中的全部Action必须共享相同的生命周期。Struts 2支持经过拦截器堆栈(Interceptor Stacks)为每个Action建立不一样的生命周期。开发者能够根据须要建立相应堆栈,从而和不一样的Action一块儿使用。
建立action对象资源浪费不是特别大,只要在设计的时候注意不要把一些比较重的资源放到全局变量和构造方法里面就行了。另外容器里有很好的垃圾回收机制,只要有一个action实例不用,就会立刻回收处理。因此服务器是彻底抗的住的。
由于二级缓存维护的问题,hibernate查询数据后要进行持久化对象;好比查询每一行都进行ORMapping,速度是会比较慢的;
加快方法:使用延迟加载:lazy=true;或者建立索引加快查询速度;或者减小查询字段;
解决方法:若是底层数据库(如Oracle)支持存储过程,也能够经过存储过程来执行批量更新。存储过程直接在数据库中运行,速度更加快。
hibernate.cfg.xml文件主要配置session-factory的数据源配置,而自增加配置在hbm.xml文件里面的每一个表中id部分里面的generate上;
工做原理
前提:在hibernate.cfg.xml文件中配置数据库链接;其次写domain.hbm.xml配置文件;
(1)、启动服务器,读取配置信息,建立sessionFactory;
(2)、Configuration conf = new Configuration().configure("hibernate.cfg.xml"); //实例化configuration对象;
(3)、SessionFactory sessionFactory = conf.buildSessionFactory(); //建立一个SessionFactory对象;
(4)、Session session = sessionFactory.openSession(); //建立session对象,打开一个Session;
(5)、Transaction tx = session.beginTransaction().begin(); //开启事务;
(6)、添加要对数据库进行操做信息;
(7)、session.save(user);//保存信息;
(8)、tx.commit();//提交;
为何要用
1.对JDBC访问数据库的代码作了封装,大大简化了数据访问层繁琐的重复性代码。
2.Hibernate是一个基于JDBC的主流持久化框架,是一个优秀的ORM实现。他很大程度的简化DAO层的编码工做
3.hibernate使用Java反射机制,而不是字节码加强程序来实现透明性。
4.hibernate的性能很是好,由于它是个轻量级框架。映射的灵活性很出色。它支持各类关系数据库,从一对一到多对多的各类复杂关系。
当Hibernate在查询数据的时候,数据并无存在与内存中,当程序真正对数据的操做时,对象才存在与内存中,就实现了延迟加载,他节省了服务器的内存开销,从而提升了服务器的性能。
答:session/sessionFactory/configuration/transcation/query
HQL、SQL、Criteria;
第一种方式:Hibernate继承关系树的每一个具体类对应一个表:关系数据模型彻底不支持域模型中的继承关系和多态。
第二种方式:Hibernate继承关系树的根类对应一个表:对关系数据模型进行很是规设计,在数据库表中加入额外的区分子类型的字段。经过这种方式,可使关系数据模型支持继承关系和多态。
第三种方式:Hibernate继承关系树的每一个类对应一个表:在关系数据模型中用外键参照关系来表示继承关系。
答:主要解决数据持久化的问题
一级缓存:
Session 有一个内置的缓存,其中存放了被当前工做单元加载的对象。
每一个Session 都有本身独立的缓存,且只能被当前工做单元访问。
二级缓存:
SessionFactory的外置的可插拔的缓存插件。其中的数据可被多个Session共享访问。
SessionFactory的内置缓存:存放了映射元数据,预约义的Sql语句。
(1).临时状态 (transient)又叫暂态:刚用new建立,没被持久化,没在session缓存中;
特征:
1】不处于Session 缓存中
2】数据库中没有对象记录
Java如何进入临时状态
1】经过new语句刚建立一个对象时
2】当调用Session 的delete()方法,持久化状态à临时
(2).持久化状态(persisted):被持久化,加入到session缓存中;
特征:
1】处于Session 缓存中
2】持久化对象数据库中没有对象记录
3】Session 在特定时刻会保持两者同步
Java如何进入持久化状态
1】Session 的save() 临时à持久化状态
2】Session 的load(),get()方法返回的对象 临时à持久化状态
3】Session 的find()返回的list集合中存放的对象 临时à持久化状态
4】Session 的update(),saveOrUpdate() 游离à持久化
(3).游离状态(detached):被持久化,没在session缓存中;
特征:
1】再也不位于Session 缓存中
2】游离对象由持久化状态转变而来,数据库中可能还有对应记录。
Java如何进入 持久化状态à游离状态
1】Session 的close()方法
2】Session 的evict()方法,从缓存中删除一个对象。提升性能。少用。
一对多关系分为单向一对多关系和双向一对多关系。
单向一对多关系只能经过主控方对被动方进行级联更新。
双向一对多关系其实是“一对多”与“多对一”关联的组合,也就是说咱们必须在主控方配置单向一对多关系的基础上,在被控方配置与其对应的多对一关系。
双向一对多的关系除了避免约束违例和提升性能的好处以外,还带来另一个优势,因为创建了双向关联,咱们能够在关联双方中任意一方,访问关联的另外一方。
答:ORM是面向对象关系映射的意思;
应用:主要是开发人员就能够把对数据库的操做转化为对这些对象的操做;
(1)、悲观锁:在整个数据处理过程当中,数据处于锁定状态,外界没法修改;
实现:query.setLockMode( " user " ,LockMode.UPGRADE); // 加锁
(2)、乐观锁:更改数据库表后,将为数据表增长一个版本标识;大大提升并发效率;
实现:为TUser的class描述符添加optimistic-lock属性:
< hibernate - mapping >
< class
name = " org.hibernate.sample.TUser "
table = " t_user "
dynamic - update = " true "
dynamic - insert = " true "
optimistic - lock = " version "
>
……
</ class >
</ hibernate - mapping >
答:lazy,就是延时加载。
以最简单的parent和child为例子:一个parent能够有多个child,一个child只有一个parent。
当parent类的child属性的lazy为true,那么当select parent的时候,他的child不会立刻被select,一直延迟到他的child须要被读写的时候再去select。
当parent类的child属性的lazy为false,那么select parent的时候,他的child会立刻被select。
inverse,用于外键维护的控制。
当inverse为false,则在插入表数据以后,会再插入外键维护的记录。
当inverse为true,则在插入表数据的同时,插入外键维护的记录。
在非多对多的表关系中:
仍是以parent和child为例子。假设1个parent有3个child,那么:
当inverse为false,则先insert 1 条 parent,再insert 3 条 child,再insert 3 个child的parent ID,一共7次insert。
当inverse为true,则先insert 1 条 parent,再insert 3 条 child,固然这3次insert是同时完成插入parent ID的,因此一共4次insert。
总结:在非多对多的表关系中,inverse永远为ture。
在多对多的表关系中:
中间表的外键维护一般由一方进行维护。
因此2个多方,1个inverse为ture,1个inverse为false。中间表会由inverse为false的一方维护。
总结:选择数据比较多的一方维护中间表的效率会比较高。
cascade,表的级联。
若是你熟悉数据库,表级联能够设置在数据库上。
若是你选择设置在配置文件中,则相应的你的系统会更方便的在各个数据库之间进行移植。
级联具体状况就看业务需求了。关于级联,不明白的可查阅数据库基础理论。没什么好多说的。
fetch,就是加载子表信息所采用的方式,select或者join
如下是我我的对这个属性的理解:
xml配置文件中能够不配置,采用默认的。而他真正的做用在于:
1). 一般状况为了保证效率,lazy的配置都是true的。好比有个页面须要显示parent列表,只须要parent的name属性和create time属性,由于不涉及子表信息,lazy为false的配置将大大影响效率。这样,咱们就拥有了hibernate的高性能。
2). 特殊状况下,咱们又但愿lazy为false,即当编辑某一个parent的时候,马上得到parent的子表,乃至子表的信息(例如当咱们采用分层结构 时,当信息到视图层时,hibernate的session已经断开了,因此要在逻辑层完成全部信息的载入)。咱们就能够在HQL中写 left/right outer/inner join fetch实现此功能。这样,咱们又得到了临时的灵活性。
(1).减小访问数据库的频率。
(2).保证缓存中的对象与数据库中的相关记录保持同步。
(3).保证不出现访问对象图的死循环,以及由死循环引发的JVM堆栈溢出异常。清理缓存时,会顺序执行一些SQL语句。
拦截器与过滤器的区别:
拦截器是基于java的反射机制的,而过滤器是基于函数回调。
拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
拦截器只能对action请求起做用,而过滤器则能够对几乎全部的请求起做用。
拦截器能够访问action上下文、值栈里的对象,而过滤器不能访问。
在action的生命周期中,拦截器能够屡次被调用,而过滤器只能在容器初始化时被调用一次
执行顺序:过滤前 - 拦截前 - Action处理 - 拦截后 - 过滤后。我的认为过滤是一个横向的过程,首先把客户端提交的内容进行过滤(例如未登陆用户不能访问内部页面的处理);过滤经过后,拦截器将检查用户提交数据的验证,作一些前期的数据处理,接着把处理后的数据发给对应的Action;