ssh面试

更新时间:2023-12-23 00:36:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

Hibernate工作原理及为什么要用? 原理:

1.读取并解析配置文件 2.读取并解析映射信息,创建SessionFactory 3.打开Sesssion 4.创建事务Transation 5.持久化操作 6.提交事务

7.关闭Session 8.关闭SesstionFactory

为什么要用:

1. 对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码。

2. Hibernate是一个基于JDBC的主流持久化框架,是一个优秀的ORM实现。他很大程度的简化DAO层的编码工作,使开发更对象化了。

3. hibernate使用Java反射机制,而不是字节码增强程序来实现透明性。支持透明持久化,因为hibernate操作的是纯粹的(pojo)java类,没有实现任何接口,没有侵入性。

4. hibernate的性能非常好,因为它是个轻量级框架。映射的灵活性很出色。它支持各种关系数据库,从一对一到多对多的各种复杂关系。

Hibernate是如何延迟加载?

1. Hibernate2延迟加载实现:a)实体对象 b)集合(Collection) 2. Hibernate3 提供了属性的延迟加载功能

3.get不支持延迟加载,load支持延迟加载。

当Hibernate在查询数据的时候,数据并没有存在与内存中,当程序真正对数据的操作时,对象才存在与内存中,就实现了延迟加载,他节省了服务器的内存开销,从而提高了服务器的性能。

hibernate延迟加载就是当使用session.load(User.class, 1)或者session.createQuery()查询对象或者属性的时候,这个对象或者属性并没有在内存中,只有当程序操作数据的时候,才会存在内存中,这样就实现延迟加载,节省了内存的开销,从而提高了服务器的性能。

Hibernate中怎样实现类之间的关系?(如:一对多、多对多的关系)

类与类之间的关系主要体现在表与表之间的关系进行操作,它们都市对对象进行操作,我们程序中把所有的表与类都映射在一起,它们通过配置文件中的many-to-one、one-to-many、many-to-many、

说下Hibernate的缓存机制

1. 一级缓存:内部缓存存在Hibernate中,属于session级的缓存也叫事务级的缓存,只缓存实体,生命周期和session一致。不能对其进行管理。不用显示的调用。

2. 二级缓存:sessionFactory缓存,也叫进程级的缓存,使用第3方插件实现的,也指缓存实体,生命周期和sessionFactory一致,可以进行管理。首先配置第3放插件,我们用的是EHCache,在hibernate.cfg.xml文件中加入,在映射中也要显示的调用。 a) 应用及缓存 b) 分布式缓存

条件:数据不会被第三方修改、数据大小在可接受范围、数据更新频率低、同一数据被系统频繁使用、非关键数据

c) 第三方缓存的实现

3.二级缓存之查询缓存: 对普通属性进行缓存。如果关联的表发生了修改,那么查询缓存的生命周期也结束了。在程序中必须手动启用查询缓存: query.setCacheable(true);

Hibernate的查询方式 3种。hql 条件查询() 原生sql Sql、Criteria,object comptosition Hql:

1、 属性查询 2、 参数查询、命名参数查询 3、 关联查询 4、 分页查询 5、 统计函数

如何优化Hibernate?

1.使用双向一对多关联,不使用单向一对多,尽量从多的一端维护。 如果将t_student(多)表里的classesid字段设置为非空,则无法保存。不在student这一端维护关系, 存储student时不会存学生对应的班级,在存储班级时需要发出多余的update语句来更新关系 2.灵活使用单向一对多关联 3.不用一对一,用多对一取代

4.配置对象缓存,不使用集合缓存 5.一对多集合使用Bag,多对多集合使用Set

6. 继承类使用显式多态 7. 表字段要少,表关联不要怕多,有二级缓存撑腰

谈谈你对Hibernate的理解。

1. 面向对象设计的软件内部运行过程可以理解成就是在不断创建各种新对象、建立对象之间的关系,调用 对象的方法来改变各个对象的状态和对象消亡的过程,不管程序运行的过程和操作怎么样,本质上都是要得到一个结果,程序上一个时刻和下一个时刻的运行结果的差异就表现在内存中的对象状态发生了变化。 2.为了在关机和内存空间不够的状况下,保持程序的运行状态,需要将内存中的对象状态保存到持久化设备和从持久化设备中恢复出对象的状态,通常都是保存到关系数据库来保存大量对象信息。从Java程序的运行功能上来讲,保存对象状态的功能相比系统运行的其他功能来说,应该是一个很不起眼的附属功能,java采用jdbc来实现这个功能,这个不起眼的功能却要编写大量的代码,而做的事情仅仅是保存对象和恢复对象,并且那些大量的jdbc代码并没有什么技术含量,基本上是采用一套例行公事的标准代码模板来编写,是一种苦活和重复性的工作。

3.通过数据库保存java程序运行时产生的对象和恢复对象,其实就是实现了java对象与关系数据库记录的映射关系,称为ORM(即Object Relation Mapping),人们可以通过封装JDBC代码来实现了这种功能,封装出来的产品称之为ORM框架,Hibernate就是其中的一种流行ORM框架。使用Hibernate框架,不用写JDBC代码,仅仅是调用一个save方法,就可以将对象保存到关系数据库中,仅仅是调用一个get方法,就可以从数据库中加载出一个对象。

4.使用Hibernate的基本流程是:配置Configuration对象、产生SessionFactory、创建session对象,启动事务,完成CRUD操作,提交事务,关闭session。

5.使用Hibernate时,先要配置hibernate.cfg.xml文件,其中配置数据库连接信息和方言等,还要为每个实体配置相应的hbm.xml文件,hibernate.cfg.xml文件中需要登记每个hbm.xml文件。 6.在应用Hibernate时,重点要了解Session的缓存原理,级联,延迟加载和hql查询。 AOP的作用。

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完成数据读取。

load()方法认为该数据一定存在,可以放心的使用代理来延时加载 ,如果使用过程中发现了问题,就抛出异常; get()方法一定要获取到真实的数据,否则返回null

简述 Hibernate 和 JDBC 的优缺点? 如何书写一个 one to many 配置文件.

写Hibernate的一对多和多对一双向关联的orm配置?

hibernate的inverse属性的作用?

iBatis与Hibernate有什么不同?

相同点:屏蔽jdbc api的底层访问细节,使用我们不用与jdbc api打交道,就可以访问数据。

jdbc api编程流程固定,还将sql语句与java代码混杂在了一起,经常需要拼凑sql语句,细节很繁琐。 ibatis的好处:屏蔽jdbc api的底层访问细节;将sql语句与java代码进行分离;提供了将结果集自动封装称为实体对象和对象的集合的功能,queryForList返回对象集合,用queryForObject返回单个对象;提供了自动将实体对象的属性传递给sql语句的参数。

Hibernate是一个全自动的orm映射工具,它可以自动生成sql语句,ibatis需要我们自己在xml配置文件中写sql语句,hibernate要比ibatis功能负责和强大很多。因为hibernate自动生成sql语句,我们无法控制该语句,我们就无法去写特定的高效率的sql。对于一些不太复杂的sql查询,hibernate可以很好帮我们完成,但是,对于特别复杂的查询,hibernate就很难适应了,这时候用ibatis就是不错的选择,因为ibatis还是由我们自己写sql语句。

hibernate进行多表查询每个表中各取几个字段,也就是说查询出来的结果集没有一个实体类与之对应如何解决;

解决方案一,按照Object[]数据取出数据,然后自己组bean

解决方案二,对每个表的bean写构造函数,比如表一要查出field1,field2两个字段,那么有一个构造函数就是Bean(type1 filed1,type2

field2) ,然后在hql里面就可以直接生成这个bean了。

介绍一下Hibernate的二级缓存

按照以下思路来回答:(1)首先说清楚什么是缓存,(2)再说有了hibernate的Session就是一级缓存,即有了一级缓存,为什么还要有二级缓存,(3)最后再说如何配置Hibernate的二级缓存。

(1)缓存就是把以前从数据库中查询出来和使用过的对象保存在内存中(一个数据结构中),这个数据结构通常是或类似Hashmap,当以后要使用某个对象时,先查询缓存中是否有这个对象,如果有则使用缓存中的对象,如果没有则去查询数据库,并将查询出来的对象保存在缓存中,以便下次使用。下面是缓存的伪代码:

引出hibernate的第二级缓存,用下面的伪代码分析了Cache的实现原理 Dao{ } Dao{ }

(2)Hibernate的Session就是一种缓存,我们通常将之称为Hibernate的一级缓存,当想使用session

Cache cache = null setCache(Cache cache){ }

User getUser(int id){ }

if(cache!=null){ }

return session.get(id);

User user = cache.get(id); if(user ==null){ }

return user;

user = session.get(id); cache.put(id,user);

this.cache = cache hashmap map = new map(); User getUser(integer id){ }

User user = map.get(id) if(user == null){ }

return user;

user = session.get(id); map.put(id,user);

从数据库中查询出一个对象时,Session也是先从自己内部查看是否存在这个对象,存在则直接返回,不存在才去访问数据库,并将查询的结果保存在自己内部。由于Session代表一次会话过程,一个Session与一个数据库连接相关连,所以Session最好不要长时间保持打开,通常仅用于一个事务当中,在事务结束时就应关闭。并且Session是线程不安全的,被多个线程共享时容易出现问题。通常只有那种全局意义上的缓存才是真正的缓存应用,才有较大的缓存价值,因此,Hibernate的Session这一级缓存的缓存作用并不明显,应用价值不大。Hibernate的二级缓存就是要为Hibernate配置一种全局缓存,让多个线程和多个事务都可以共享这个缓存。我们希望的是一个人使用过,其他人也可以使用,session没有这种效果。

(3)二级缓存是独立于Hibernate的软件部件,属于第三方的产品,多个厂商和组织都提供有缓存产品,例如,EHCache和OSCache等等。在Hibernate中使用二级缓存,首先就要在hibernate.cfg.xml配置文件中配置使用哪个厂家的缓存产品,接着需要配置该缓存产品自己的配置文件,最后要配置Hibernate中的哪些实体对象要纳入到二级缓存的管理中。明白了二级缓存原理和有了这个思路后,很容易配置起Hibernate的二级缓存。扩展知识:一个SessionFactory可以关联一个二级缓存,也即一个二级缓存只能负责缓存一个数据库中的数据,当使用Hibernate 的二级缓存后,注意不要有其他的应用或SessionFactory来更改当前数据库中的数据,这样缓存的数据就会与数据库中的实际数据不一致。

Hibernate的执行流程

1> 通过Configuration().configure();读取并解析hibernate.cfg.xml配置文件

2> 由hibernate.cfg.xml中的 通过config.buildSessionFactory();//创建SessionFactory 4> sessionFactory.openSession();//打开Sesssion 5> session.beginTransaction();//创建事务Transation 6> persistent operate持久化操作

7> session.getTransaction().commit();//提交事务 8> 关闭Session 9> 关闭SesstionFactory

Hibernate对象的三种状态

Persitent状态的对象不能引用Transient对象,不然会抛出TransientObjectException异常 Transient(瞬时)状态的特征:

* 在数据库中没有与之匹配的数据 * 没有纳入session的管理,可通过session的save()或 saveOrUpdate()方法将瞬时对象与数据库 相关联,并将数据对应的插入数据库中,此时该瞬时对象转变成持久化对象。 Persistent(持久)状态的特征: * persistent状态的对象在数据库中有与之匹配的数据 * 纳入了session的管理 * 在清理缓存(脏数据检查)的时候,会和数据库同步 Detached(游离)状态的特征: * 在数据库中有与之匹配的数据 * 没有纳入session的管理,当与某持久对象关联的session被关闭后,该持久对象转变为游离对象。 当游离对象被重新关联到session上时,并再次转变成持久对象。游离对象和比瞬时对象相比,多了 一个数据库记录标识值,其它没什么不同。

Hibernate的映射方式 一对一: Person和IdCard。添加Person的时候,不会出现TransientObjectException异常,因为一对一主键关联映射中,默认了cascade属性。 主键单向: 在Person端 idCard

主键双向: 在IdCard端也加入 外键单向,外键双向 一对多:单向,双向

单向: 在多的一端加入一个外键指向一的一端,它维护的关系是一指向多 标签的定义示例(在一的一端):

加载时: 加载一的一端时,会把多的一端的数据也都加载上(相当于执行两次查找操作) 双向: 在一的一端的集合上使用,在对方表中加入一个外键指向一的一端

在多一端采用

标签指定的外键字段必须和指定的外键字段一致,否则引用字段的错误。

一对多的关系一般采用双向的,在一的一端设置inverse属性,把关联关系交给多的一端,避免发出多余的update。

inverse:主控方,外键的关系有谁控制

inverse=false 是主控方,外键是由它控制的 inverse=true 是被控方,外键与它没关系

要想实现主控方的控制必须将被控方作为主控方的属性 cascade:级联, 主表增从表增,主表修从表修,主表删从表删 多对一:会在多的一端加入一个外键,指向一的一端 多对多:单向,双向

hibernate的核心类是什么,它们的相互关系是什么?重要的方法是什么?

Configuration 接口:配置Hibernate,根据其启动hibernate,创建SessionFactory 对象;

SessionFactory 接口:初始化Hibernate,充当数据存储源的代理,创建session 对象,sessionFactory 是线程安全的,意味着它的同一个实例可以被应用的多个线程共享,是重量级、二级缓存;

Session 接口:负责保存、更新、删除、加载和查询对象,是线程不安全的,避免多个线程共享同一个session,是轻量级、一级缓存;

Session如下方法: save,load,update,delete,

Query q=CreateQuery(“from Customer where customerName=:customerName”) beginTransaction, close, transaction, commit Transaction 接口:管理事务;

Query 和Criteria 接口:执行数据库的查询。

Hibernate的查询方式, HQL与SQL 执行SQL查询的步骤如下:

(1)获取Hibernate Session对象;

(2)编写SQL语句;String sqlString = “select {s.*} from student s where s.name like ‘xxx’”; (3)以SQL语句作为参数,调用Session的createSQLQuery方法创建查询对象; (4)如果SQL语句包含参数,调用Query的setXxx方法为参数赋值;

List l = session.createSQLQuery(sqlString) .addEntity(“s”,Student.class) .list(); (5)调用SQLQuery对象的addEntity或addScalar方法将选出的结果与实体或标量值关联; (6)调用Query的list方法返回查询的结果集。 Criteria,object comptosition

Hql: * 属性查询* 参数查询、命名参数查询* 关联查询* 分页查询* 统计函数 实体查询例子:

String hql=”from User user ”;

List list=session.CreateQuery(hql).list(); HQL面向对象,而SQL操纵关系数据库

HQL仅用于查询数据,不支持insert,update和delete语句

Hibernate的主键生成机制

1) assigned主键由外部程序负责生成,无需Hibernate参与。 2) increment

主键按数值顺序递增。此方式的实现机制为在当前应用实例中维持一个变量,以保存着当前的最大值,之后每次需要生成主键的时候将此值加1作为主键。这种方式可能产生的问题是: 如果当前有多个实例访问同一个数据库,那么由于各个实例各自维护主键状态,不同实例可能生成同样的主键,从而造成主键重复异常。因此,如果同一数据库有多个实例访问,此方式必须避免使用。

3) identity采用数据库提供的主键生成机制。如DB2、SQL Server、MySQL中的主键生成机制。 4) sequence采用数据库提供的sequence 机制生成主键。如Oralce 中的Sequence。

5) native由Hibernate根据底层数据库自行判断采用identity、hilo、sequence其中一种作为主键生成方式。

6) uuid.hex由Hibernate基128位唯一值产生算法生成16 进制数值(编码后以长度32 的字符串表示)

作为主键。

7) uuid.string uuid.hex类似,只是生成的主键未进行编码(长度16)。 8) foreign 使用外部表的字段作为主键。

在数据库中条件查询速度很慢的时候,如何优化? 1)建索引2)减少表之间的关联

3)优化sql,尽量让sql很快定位数据,不要让sql做全表查询,应该走索引,把数据量大的表排在前面 4)简化查询字段,没用的字段不要,已经对返回结果的控制,尽量返回少量数据

Hibernate 事务处理机制

Hibernate是对JDBC的轻量级对象封装,Hibernate本身是不具备Transaction 处理功能的,Hibernate的 Transaction实际上是底层的JDBC Transaction的封装,或者是JTA Transaction的封装

作为主键。

7) uuid.string uuid.hex类似,只是生成的主键未进行编码(长度16)。 8) foreign 使用外部表的字段作为主键。

在数据库中条件查询速度很慢的时候,如何优化? 1)建索引2)减少表之间的关联

3)优化sql,尽量让sql很快定位数据,不要让sql做全表查询,应该走索引,把数据量大的表排在前面 4)简化查询字段,没用的字段不要,已经对返回结果的控制,尽量返回少量数据

Hibernate 事务处理机制

Hibernate是对JDBC的轻量级对象封装,Hibernate本身是不具备Transaction 处理功能的,Hibernate的 Transaction实际上是底层的JDBC Transaction的封装,或者是JTA Transaction的封装

本文来源:https://www.bwwdw.com/article/zjg5.html

Top