hibernate 介绍
hibernate是一个开源框架,它是对象关联关系映射的框架,它对 JDBC 做了轻量级的封装,而我们 Java 程序员可以使用面向对象的思想来操纵数据库。
Hibernate核心接口
Hibernate核心接口
1.session:负责被持久化对象CRUD操作
2.sessionFactory:负责初始化hibernate,创建session对象
3. Configuration :负责配置并启动hibernate,创建SessionFactory
4.Transaction:负责事物相关的操作
5. Query 和Criteria接口:负责执行各种数据库查询
详解:
1.Session接口:Session 接口负责执行被持久化对象的CRUD操作。 但需要注意的是 Session 对象是非线程安全的。
2.SessionFactory接口:SessionFactroy接口负责初始化Hibernate。它充当数据存储源的代理,并负责创建Sessio对象。
这里用到了工厂模式。 需要注意的是 SessionFactory 并不是轻量级的, 因为一般情况下, 一个项目通常只需要一个 SessionFactory 就够,
当需要操作多个数据库时,可以为每个数据库指定一个 SessionFactory。
3.Configuration 接口:Configuration 接口负责配置并启动 Hibernate,创建SessionFactory对象。
在Hibernate的启动的过程中, Configuration 类的实例首先定位映射文档位置、读取配置, 然后创建 SessionFactory 对象。
4.Transaction 接口:Transaction 接口负责事务相关的操作。它是可选的,开发人员也可以设计编写自己的底层事务处理代码。
5.Query 和 Criteria 接口:Query 和 Criteria 接口负责执行各种数据库查询。它可以使用 HQL
Hibernate工作原理及作用
1.读取并解析hibernate.cfg.xml配置文件:通过Configuration config = new Configuration().configure();
2.读取并解析映射信息:由hibernate.cfg.xml中的<mapping resource=”com/xx/User.hbm.xml”/>
3.创建SessionFactory:通过SessionFactory sf = config.buildSessionFactory();
4.打开Sesssion:Session session = sf.openSession();
5.创建并启动事务Transation:Transaction tx = session.beginTransaction();
6.操作数据,持久化操作:增删改查
7.提交事务tx.commit();
8.关闭Session
9.关闭SesstionFactory
怎样构建SessionFactory
Hibernate配置文件分为两种格式,一种是xml格式的配置文件,另一种是Java属性文件格式的配置文件
1.创建一个Configuration对象,并通过该对象的configura()方法加载Hibernate配置文件,代码如下。
Configuration config = new Configuration().configure();
configura()方法:用于告诉Hibernate加载hibernate.cfg.xml文件。Configuration在实例化时默认加载classpath中的hibernate.cfg.xml,当然也可以加载名称不是hibernate.cfg.xml的配置文件,例如wghhibernate.cfg.xml,可以通过以下代码实现。
Configuration config = new Configuration().configure(“wghhibernate.cfg.xml”);
2.完成配置文件和映射文件的加载后,将得到一个包括所有Hibernate运行期参数的Configuration实例,通过Configuration实例的buildSessionFactory()方法可以构建一个惟一的SessionFactory,代码如下:
SessionFactory sessionFactory = config.buildSessionFactory();
构建SessionFactory要放在静态代码块中,因为它只在该类被加载时执行一次。
3.从Java属性文件读取配置信息构建SessionFactory的具体步骤如下: [难]
1.创建一个Configuration对象,此时Hibernate会默认加载classpath中的配置文件hibernate.properties,代码如下。
Configuration config = new Configuration();
2.由于在配置文件中缺少相应的配置映射文件的信息,所以此处需要通过编码方式加载,这可以通过Configuration对象的addClass()方法实现, config.addClass(BranchForm.class);
addClass()方法用于加载实体类。
3.完成配置文件和映射文件的加载后,将得到一个包括所有Hibernate运行期参数的Configuration实例,通过Configuration实例的buildSessionFactory()方法可以构建一个惟一的SessionFactory,代码如下。
SessionFactory sessionFactory = config.buildSessionFactory();
为什么要用hibernate:
1. 对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码。
2. Hibernate是一个基于JDBC的主流持久化框架,是一个优秀的ORM实现。他很大程度的简化DAO层的编码工作
3. hibernate使用Java反射机制,而不是字节码增强程序来实现透明性。
4. hibernate的性能非常好,因为它是个轻量级框架。映射的灵活性很出色。它支持各种关系数据库,从一对一到多对多的各种复杂关系。
Hibernate比JDBC的优点
1. 能使用JDBC的地方都能使用Hibernate
2. 对JDBC轻量封装,面向对象地操作数据库
3. 对不同的数据库比JDBC移植性好
4. 具有缓存机制(一级缓存和 二级缓存 )
5. 提供方便的HQL查询语言
配置文件
配置hibernate.cfg..xml:包含数据库URL,数据库用户名,密码,数据库,JDBC驱动
配置.hbm.xml:Hibernate根据.hbm.xml配置文件生成对应的SQL语句。
配置多表查询
一对多关联:在User.hbm.xml中配置<many-to-one=”dept”column=”deptid”class=”Dept” not-null=”true”/>
一对多:在多的一方的.hbm.xml使用<many-to-one>,在一方使用<one-to-many>
查询方式
1.HQL:面向对象: from User as user where user.age>20
2.QBC条件查询方式:Query by Criteria。主要有Criteria接口,Criterion接口,Expression类组成
Criteria criteria=session.createCriteria(User.class);
Criterition criterion =Expression.like(“username”,”%tome%”);
certeria.add(criterion);
List userList=query.list();
3.本地SQl查询:当应用程序需要数据库底层的数据库方言来执行特殊的SQL时
SQLQuery query=session.createSQLQuery(“select * from tb …”);
query.setParameter(“username”,”%tom%”);
List userList=query.list();
Hibernate如何延迟加载
1.当Hibernate在查询数据的时候,数据并没有存在与内存中,当程序真正对数据的操作时,对象才存在与内存中,就实现了延迟加载,他节省了服务器的内存开销,从而提高了服务器的性能。
在读取一个对象时,跟它相关联的对象有时也会执行。在实体的映射配置文件中的<class lazy=”true”>
对于Hibernate get方法,Hibernate会确认一下该id对应的数据是否存在,首先在session缓存中查找,然后在二级缓存中查找,还没有就查询数据库,数据库中没有就返回null。
2. Hibernate load方法加载实体对象的时候,根据映射文件上类级别的lazy属性的配置(默认为true),分情况讨论:
(1)若为true,则首先在Session缓存中查找,看看该id对应的对象是否存在,不存在则使用延迟加载,返回实体的代理类对象(该代理类为实体类的子类,由CGLIB动态生成)。等到具体使用该对象的时候,再查询二级缓存和数据库,若仍没发现符合条件的记录,则会抛出一个ObjectNotFoundException。
(2)若为false,就跟Hibernateget方法查找顺序一样,只是最终若没发现符合条件的记录,则会抛出一个ObjectNotFoundException。
get和load有两个重要区别:
1.如果未能发现符合条件的记录,Hibernate get方法返回null,而load方法会抛出一个ObjectNotFoundException。
load方法可返回没有加载实体数据的代理类实例,而get方法永远返回有实体数据的对象。
总之对于get和load的根本区别,一句话,hibernate对于 load方法认为该数据在数据库中一定存在,可以放心的使用代理来延迟加载,如果在使用过程中发现了问题,只能抛异常;而对于get方法,hibernate一定要获取到真实的数据,否则返回null。
2.get()方法在内部缓存中没有打到相对应的数据时装直接执行SQL语句进行查询
load()方法查询数据时会先找Hibernate的内部缓存和二级缓存中的现有数据,
Hibernate如何实现类与类之间的关系(一对多,多对多)
类与类之间的关系主要体现在表与表之间的关系进行操作,它们都是对对象进行操作,我们程序中把所有的表与类都映射在一起,它们通过配置文件中的many-to-one、one-to-many、many-to-many进行映射
Hibernate的缓存机制
Hibernate经常访问物理磁盘数据,为了降低访问频次,使用缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据加快访问速度。
Hibernate缓存包括两大类:Hibernate一级缓存和Hibernate二级缓存。
1.Hibernate一级缓存又称为“Session的缓存”,由Hibernate管理。由于Session对象的生命周期通常对应一个数据库事务,因此它的缓存是事务范围的缓存。在第一级缓存中,持久化类的每个实例都具有唯一的OID。
2.Hibernate二级缓存又称为“SessionFactory的缓存”,由于SessionFactory对象的生命周期和应用程序的整个过程对应,因此Hibernate二级缓存是进程范围或者集群范围的缓存,有可能出现并发问题,因此需要采用适当的并发访问策略,该策略为被缓存的数据提供了事务隔离级别。第二级缓存是可选的,进可以行配置和更改, 并且可以动态加载和卸载。在默认情况下,SessionFactory不会启用这个插件。
Hibernate 中提供了两级 Cache, 配置二级缓存的主要步骤
1.第一级缓存:启用缓存的方式只要应用程序通过 Session 接口来执行保存、 更新、 删除、 加载和查询数据库数据的操作,Hibernate 就会启用第一级缓存,当应用程序调用 Session 的 save()、 update()、 savaeOrUpdate()、 get()或 load(), 以及调用查询接口的 list()、 iterate()或 filter()方法时, 如果在 Session 缓存中还不存在相应的对象, Hibernate 就会把该对象加入到第一级缓存中。
2. 二级缓存的管理:
1.条件查询的时候,总是发出一条select * from table_name where.. )这样的 SQL 语句查询数据库,一次获得所有的数据对象。
2.把获得的所有数据对象根据 ID放入到第二级缓存中。
3.当Hibernate根据ID访问数据对象的时候,首先从Session 一级缓存中查;查不到,如果配置了二级缓存,那么从二级缓存中查;
查不到,再查询数据库,把结果按照ID放入到缓存。
4.删除、 更新、 增加数据的时候, 同时更新缓存。
3.Hibernate的二级缓存策略,是针对于ID查询的缓存策略,对于条件查询则毫无作用。 为此, Hibernate提供了针对条件查询的Query Cache。
什么样的数据适合存放到第二级缓存中?
1 很少被修改的数据
2 不会被并发访问的数据
如果类的实例被经常读但很少被修改, 就可以考虑使用第二级缓存。 只有为某个类或集合配置了第二级缓存, Hibernate 在运行时才会把它的实例加入到第二级缓存中。
Hibernate的查询方式
Sql、Criteria,Hql:
1、 属性查询
2、 参数查询、命名参数查询
3、 关联查询
4、 分页查询
5、 统计函数
如何优化Hibernate
1.使用双向一对多关联,不使用单向一对多
2.灵活使用单向一对多关联
3.不用一对一,用多对一取代
4.配置对象缓存,不使用集合缓存
5.一对多集合使用Bag,多对多集合使用Set
6. 继承类使用显式多态
7. 表字段要少,表关联不要怕多,有二级缓存撑腰
什么是 Hibernate 的并发机制? 怎么去处理并发问题
a、 Hibernate的Session对象是非线程安全的,对于单个请求,单个会话,单个线程,它通常只使用一次, 然后就丢弃。
如果一个Session实例允许共享的话,那些支持并发运行的,例如 Http request,session beans 将会导致出现资源争用。
如果在 HttpSession中有hibernate的Session的话,就可能会出现同步访问 Http Session。
只要用户足够快的点击浏览器的“刷新” , 就会导致两个并发运行的线程使用同一个Session。
b、 多个事务并发访问同一块资源,可能会引发第一类丢失更新,脏读,幻读 不可重复读,第二类丢失更新一系列的问题。
解决方案: 设置事务隔离级别。
Serializable: 串行化。 隔离级别最高
Repeatable Read: 可重复读
Read Committed: 已提交数据读
Read Uncommitted:未提交数据读。 隔离级别最差
设置锁: 乐观锁 和悲观锁。
为了解决这些并发带来的问题。 我们需要引入并发控制机制。
乐观锁: 乐观锁假设认为数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测。在<class>的映射中设置 optimistic-lock=”all”。使用数据库版本和时间戳机制。
悲观锁: 假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作。Hibernate 总是使用数据库的锁定机制, 从不在内存中锁定对象!只要为JDBC 连接指定一下隔离级别,然后让数据库去搞定一切就够了。
类LockMode 定义了 Hibernate 所需的不同的锁定级别:
LockMode.UPGRADE,LockMode.UPGRADE_NOWAIT,LockMode.READ;
Hibernate 与 jdbc 的联系
Hibernate是一个持久层的ORM的框架jdbc的轻量级封装,运用了面向对象的思想,将Java中的实体类与数据库的关系表建立一个映射.就可以操作Java中对象,从而操作数据库。HQL语句也是面向对象的,它的查询语句不是查询数据库而是查询类。
Hibernate 自带的分页机制是什么
hibernate 自带的分页机制:获得Session对象后,从Session中获得Query对象。
用Query.setFirstResult():设置要显示的第一行数据, Query.setMaxResults():设置要显示的最后一行数据。
不使用 hibernate 自带的分页,可采用sql语句分页。
5:为每页显示的记录,2 为当前页: select * top 5 from table where tabId not in (select tabId top (2-1)*5 from table);
update( )和 saveOrUpdate( )的区别
update()和 saveOrUpdate()是用来对跨Session的PO进行状态管理的。
update:更新操作,没有主键时会抛异常。也就是说, 如果此对象在数据库中不存在的话,就不能使用 update()方法。update()方法操作的对象必须是持久化了的对象。
saveOrUpdate:保存和更新,没有主键就执行插入操作。
Hibernate 的三种状态之间如何转换
1.Hibernate三种状态之一:瞬时状态(Transient):,在一个对象刚被创建的时候,比如People people = new People(),它没有持久化,并没有处于Session的缓存中,这种状态的对象叫就是临时对象;
2.Hibernate三种状态之二:持久化状态(Persistent):已经执行了session的save()方法,已经持久化,加入到了Session缓存中,并且在数据库中具有对应的记录,并拥有一个持久化标识。处于此状态的对象叫持久对象。
此时如果使用hibernate的delete()方法,对应的持久对象就变成上面的瞬时对象,因为数据库中的对应数据已被删除,该对象不再与数据库的记录关联。
当一个session执行close()或clear()、evict()之后,持久对象变成下面要讲的脱管对象,此时持久对象会变成脱管对象,此时该对象虽然具有数据库识别值,但它已不在Hibernate持久层的管理之下,也就是它在session缓存中的记录已经被删除了。
3.Hibernate三种状态之三:脱管状态(Detached):持久化对象脱离了Session的对象。如当session关闭时,Session缓存被清空的对象。特点:已经持久化,但不在Session缓存中。处于此状态的对象叫游离对象;因关闭session而变成游离态的可以通过lock、save、update变成持久态 。
session对象的evict()和clear()的区别、refresh()和flush()的区别。
1.flush() flush只会操作持久化状态的对象,或者说只会操作一级缓存中的对象。flush只是执行了sql语句,但没有执行commit方法。对于临时对象和游离对象不做任何操作。
2.refresh() 和flush类似,只不过是方向相反。flush是把session缓存中的对象往数据库中更新,而refresh是把数据库中的对象往session缓存中更新。
3.evict() 该方法是从一级缓存中把持久化对象移除。
4.clear() 清理session中的所有缓存。
Hibernate 主键介绍
1.Assigned方式由程序生成主键值,并且要在session.save()之前指定否则会抛出异常特点:主键的生成值完全由用户决定,与底层数据库无关。
2.Hilo 使用高低位算法生成主键,高低位算法使用一个高位值和一个低位值, 然后把算法得到的两个值拼接起来作为数据库中的唯一主键。
3.Increment方式对主键值采取自动增长的方式生成新的主键值,但要求底层数据库的支持 Sequence 。
4.Identity 当时根据底层数据库,来支持自动增长,不同的数据库用不同的主键增长方式。
特点:与底层数据库有关,要求数据库支持Identity,如 MySQl 中是auto_increment, SQL Server 中是 Identity, 支持的数据库有 MySql、 SQL Server、 DB2、 Sybase 和 HypersonicSQL。 Identity无需 Hibernate 和用户的干涉, 使用较为方便, 但不便于在不同的数据库之间移植程序。
5.Sequence需要底层数据库支持 Sequence 方式
6.Native主键生成方式会根据不同的底层数据库自动选择 Identity、 Sequence、 Hilo 主键生成方式
7.UUID使用 128 位 UUID 算法生成主键, 能够保证网络环境下的主键唯一性, 也就能够保证在不同数据库及不同服务器下主键的唯一性。
事务控制:
1. 获取Session:session = sessionFactory.openSession();
2. 开始事务:Transacation ts=session.beginTransacation();
3. 数据库操作
4. 提交事务:ts.commit();
5. 事务回滚:ts.rollback();
6. 关闭session:session.close()
Hibernate 的抓取策略
抓取策略是指当应用程序需要利用关联关系进行对象获取的时候。
Hibernate中映射文件<hibernate-mapping> inverse属性和cascade属性的区别
1.inverse属性只存在于集合标记的元素中集合元素包括<set/>,<map/>,<list/>,<array/>,<bag/>
Inverse属性的作用是是否将对集合对象的修改反射到数据库中 inverse=”false”时修改反射到数据库中 inverse=”true” 时修改不反射到数据库中
2.Cascade属性的作用是描述关联对象进行操作时的级联特性,因此只有涉及到关系的元素才有cascade属性
如果希望Hibernate级联保存集合中的对象,<set>元素有一个cascade属性应该取save-update
Spring 是什么? 根据你的理解详细谈谈你的见解
*Spring框架是对三大框架的整合,可以将简单的组件配置、组合成为复杂的应用。
有对三层的每层解决方案:* web层:Spring MVC.* 持久层:JDBC Template * 业务层:Spring的Bean管理.
Spring是一个集合框架,是用来管理类的框架,利用一些编程思想,比如AOP和IOC,来管理它们之间的互相调用和依赖关系。
针对接口编程而不是针对类编程可以实现解耦;通过DAO层和关系映射更好的和hibernate进行整合;还提供了MVC框架,更好的和Struts整合。
总的来说,spring是一个集成了许多第三方框架的大杂烩,其核心技术是IOC(控制反转,也称依赖注入)和AOP(面向切面编程)。
Spring的七个模块
Spring core,Spring AOP,Spring ORM,Spring WEB,Spring MVC,Spring DAO,Spring Context
(1) spring AOP –面象切面编程
(2)spring DAO –数据访问对象
(3)spring ORM –对象关系影射
(4)spring Contect — 上下文配置,向Spring框架提供上下文信息
(5)spring WEB – -WEB上下文模块
(6)\spring WEB-MVC –实现了MVC
(7)spring CORE –核心容器提供Spring框架基本功能
Spring核心接口和类
1. BeanFactory:getBean,getType等。定义了IOC容器的基本功能,负责读取bean配置文档,管理bean加载实例化和生命周期。
2. XmlBeanFactory类:继承DefaultListableBeanFactory。一个与XMl相关的BeanFactory实现类
ClassPathResource res =newClassPathResource(“cintainer.xml”);
XMLBeanFactory factory = new XmlFactory(res);
3. ApplicationContext类:高级形态的IOC容器。支持国际化,支持监听机制
4. Resource接口:访问文件资源。常用ClassPathResource,FileSystemResource,ServletContextResource
5. ThrowsAdvice接口:标记接口
Spring的优点:
1. Spring的Ioc机制降低了代码的耦合性
2. 独立于各种应用服务器,可以实现一次编写,到处运行。
3. 开发人员可以自行使用Spring部分模块
XML配置文件
<?xml version=”1.0” encoding=”UTF-8”?>
<beans xmlns=””
xmlns:xsi=””
xsi:shcemaLoaction=”
”>
<beans id = “” class=””>
<bean></bean>
</beans>
数据源配置 :
<bean id =”dataSource” class=”org.springframework.jdbc.datasource.DriverManagerDataSource”>
<property name=”driverClassName”>
<value>com.mysql.jdbc.Driver</value>
</property>
url,username,password
</bean>
事务配置
1. 传播策略:propagation
2. 隔离性:isolation
3. 超时时间:timeout
4. 只读:readOnly