Hibernate系统知识
Hibernate
//----------------------------------------------------------------------------------
第一篇:hibernate入门
//----------------------------------------------------------------------------------
1. 应用程序的分层体系结构
表示层
|
业务层
Object |
| 持久层 (Hibernate JPA)
Mapping |
| |
Relation 数据层
2.Hibernate是最流行的ORM(Object-Relation Mapping:对象/关系映射)框架之一,也是最早实现JPA的规范框架之一,它被jboss收购后,目前作为jboss的一个开源框架,
其中,涉及JPA的子项目有三个:Hibernate Core,Hibernate 框架的核心实现;Hibernate Annotations,支持jdk 5.0 的注释;
Hibernate EntityManager支持JPA的实现
概念:
ORM全称为Object-Relation Mapping,对象/关系映射:就是利用描述对象和关系数据库之间映射的源数据,自动的把Java应用程序中的对象持久化到关系数据库的表
ORM框架的作用:帮助我们利用面向对象的思想开发基于关系型数据库的应用程序:
*1*将对象数据保存到关系数据库的表中
*2*将关系数据库表中数据读入到对象中
ORM的优势:
提高生产率:减少了重复性的持久性相关的代码,减少开发时间。
可维护性:重构方便,提高可维护性。
更好性能:ORM为性能优化问题考虑得比你更多。
厂商独立性:不依赖数据库,你的应用更具有可移植性。
3.配置Hibernate框架:
3.1架包的使用:
核心包:Hibernate-core-3.x.x.jar
产生查询分析器:antlr-2.7.6.jar
po字节码的动态生成:javassist-3,9.0.jar
规范包:jta-1.1.jar
解析xml配置文件和xml映射文件:dom4j-1.6.1.jar
日志服务通用库:slf4j-api-1.5.8jar
日志服务实现库:log4j.jar
slf4j和log4j之间的转换: slf4j-log4j12-1.5.8.jar
3.2 ## a. 添加hibernate配置文件hibernate.cfg.xml,(根据工程实例进行编写)
常用配置:
数据库连接参数配置
数据库方言配置
数据库连接池配置
指定对象关系映射文件
缓存属性配置
其它配置:如是否输出SQL到控制台等。
b. 添加日志服务配置文件log4j.properties
c. 设计持久化实体类:只要是一个POJO(Plain Ordinary Java Objects就是简单javaBean,为了避免和EJB混淆所造成的简称)即可
必须具备的条件:c1.为所有属性声明getter和setter方法。
c2.
有一个默认的构造方法。
c3.
提供一个作为对象标识符(OID)的属性。
c4.
如果属性的类型是集合,则必须定义成接口类型。如:List、Set、Map。
c5.
持久化类如果要支持序列化,则需要实现Serializable接口
d.创建对象-关系映射文件 User.hbm.xml
要在Hibernate配置文件中指明映射文件的位置<mapping resource="com/qiujy/domain/User.hbm.xml" />
主键生成器最常用的两种:native:根据底层数据库对自动生成标识符的支持能力来选择identity,sequence或hilo.适用于代理主键。主键类型要是long、int或short。
uuid:Hibernate采用128位的UUID算法来生成标识符。UUID算法能够在网络环境中生成唯一的一个32位16进制数字的字符串。适用于代理主键。String类型的数据
e.使用Hibernate API 进行持久化操作
操作过程
根据hibernate的默认配置文件构建一个(全局的)SessoinFactory实例
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
获取Session实例
Session session = sessionFactory.openSession();
开启事务
session.beginTransaction();
利用Session实例进行持久化操作
session.save(Object obj);
提交事务
session.getTransaction().commit();
关闭Session
session.close();
f.Session类主要用来执行实体的持久化操作。
Session中的方法几乎都声明抛出org.hibernate.HibernateException非受检异常。
新增:session.save(account);
修改:session.update(account);
删除:session.delete(account);
根据ID来查询:
session.get(Account.class, id);
session.load(Account.class, id);
根据指定参数来查询:
Query query = session.createQuery("from Account where loginname=:loginname");
query.setString("loginname", account.getLoginName());
List list = query.list();
g.Hibernate核心类和接口
Configuration类:加载Hibernate配置,创建SessionFactory对象,Configuration接口负责管理Hibernate的配置信息并且根启动Hibernate:
SessionFactory接口:初始化Hibernate,充当数据库源的代理,充当session对象
特点:
线程安全,即同一个SessionFactory实例可以被应用的多个线程共享。
它是重量级的,因为它需要一个很大的缓存,用来存放预定义的SQL语句以及映射元数据等。所以,如果应用程序只访问一个数据库,则只需要创建一个SessionFactory实例。
Session接口:也被称为持久化管理器提供了和持久化相关的操作(CRUD Create Retrieve查询 ),负责查询,删除,修改,添加对象
Transaction接口:管理事务
Query和Criteria接口:执行数据库查询
Query包装了一个HQL(Hibernate Query Language)查询语句。
Criteria 接口完全封装了基于字符串形式的查询语句,比Query更加面向对象,Cirteria接口擅长于执行动态查询。
调用代码:
List list = session.createQuery("from User").list();
List list = session.createCriteria(Student.class)
.add(Restrictions.like("name", "张%"))
.add(Restrictions.like("grade", "二%"))
.addOrder(Order.desc("id"))
.list();
注意:使用Hibernate进行操作时(增、删、改)必须显示的调用Transaction(默认:autoCommit=false)。
4.Hibernate 的工作流程:
开始
|
Configuration con=new Configuration().configure();
启动Hiberante
|
构建Configuration实例
|
Configuration实例加载hiberation.cfg.xml文件至内存
|
加载映射文件*。hbm.xml文件
|
Configuration实例根据hibernate.cfg.xml文件加载映射文件(*。hbm.xml)至内存
|
Configuration实例构建一个sessionFactory实例
SessionFactry sesssionFactory=con.buildSessionFactory();
|
SesssionFactory创建session实例
Session session=sessionFactory.openSession();
|
由Session实例创建Transaction的一个实例,开启事务
|
通过session的各种接口提供的各种方法操作数据库
|
提交或回滚事务
|
关闭session
|
结束
5。session缓存(一级缓存)
原理:当应用程序调用Session的crud方法时,如果session缓存中还不存在相应的对象,Hibernate就会把该对象加入到第一级缓存中
当清理缓存时,Hibernate会根据缓存中对象的状态变化来同步更新数据库
作用:a。减少数据库的访问频率,(持久化上下文调整缓存)
b. 保证缓存中的对象与数据库中的对应数据同步(自动脏检查)
位于缓存中的对象称为持久化对象,当缓存中持久化对象发生变化时,Session并不会执行相关的sql语句,这使得session
能够把几条相关的sql语句合并成一条sql语句,减少数据库的访问次数,提高效率
清理缓存的时间点:当应用程序调用Transction的commit()方法时,
commit()方法会清理缓存,然后再向数据库提交事务
当应用程序中显示调用session的flush()方法时。
还可以通过Session的setFushMode(FlushMode fm)方法来设定清理缓存的时间点。主要有四种模式:
FlushMode.ALWAYS:Session在执行查询前,总是先清理缓存。
FlushMode.AUTO:Session的查询方法,commit方法,flush方法都会清理缓存.(默认方式)
FlushMode.COMMIT:Session的commit方法,flush方法会清理缓存.
FlushMode.MANUAL:Session的flush方法会清理缓存.
6。持久化生命周期:
6.0 Hibernate中的实体对象状态:瞬时状态(Transient没有纳入session的管理),持久化状态(Persistent 纳入session的管理)
托管状态(detached不处于session的管理中,曾经与某个持久化上下文发生过关联,上下文已经关闭了)
移除状态:(removed,如果在工作单元中要删除,他就处于移除状态)
6.1 save()方法使一个瞬时状态的对象转变为持久化状态的对象
get()和load()方法,加载一个持久化对象
异同点:
2. 缓存中不存在给定OID对应的持久状态对象:
get方法:执行SQL从数据库获取。
load方法:返回一个代理对象。(延迟加载,懒加载)
3. 如果数据库不存在给定OID对应的记录:
get方法:返回null
load方法:抛出ObjectNotFoundException异常
6.4. delete()方法可以使一个持久化对象变成瞬时,从数据库中移除它的持久化状态。
如果传入的参数是持久化对象,Session就计划执行一个delete语句
如果传入的参数是脱管对象,先将脱管对象与Session关联使之变为持久化对象,再计划执行一个delete语句。
此时对象处于移除状态。
Session在清理缓存的时候才执行delete语句。
6.5 如果想要保存对脱管对象所做的修改,必须重附或合并它。
update()方法可以使一个脱管对象重附到新的session中,成为持久化对象。
计划执行一个update语句:只有当Session清理缓存时,才会执行update语句,此时才把此持久化对象的当前属性值组装到update语句中。程序中多次修改了持久化对象的属性值,在Session清理缓存时也只会执行一次update语句。
6.6 方法签名:
public Object merge(Object object) throws HibernateException;
将给定实例的状态复制到具有相同标识符的持久化实例上,并返回这个持久化实例。
第二篇 Hiberante基本查询
1。Hibernate查询方式:
Query是Hibernate专门用来执行HQL语句的查询接口
使用方式:Query query = session.createQuery("HQL语句");
a.Hiberante查询语言(Hibernate query language):是面向对象的查询,具备继承,多态和关联的特性
HQL基本用法
a1. 投影查询 Query query = session.createQuery("from User");
a2. where条件子句 a21.占位符的使用
Query query = session.createQuery("from User where name=?");
request.setString(0,"www");
a22.第二种方式:(:key)
Query query = session.createQuery("from User where name=:name");
query.setParameter("name","hello");
a23.第三种方式:(多个:key)
Map<string,Object> m=new HashMap<String,Object>();
m.put("占位符","占位符的值");
query.setProperties(m);
a3.调用标准函数
a4. 参数绑定
a5. distinct过滤重复值 “SELECT destinct s.age FROM Student AS s"
a6. 聚集函数 "SELECT count(s) FROM Student AS s"
a7. order by子句 FROM Student AS s ORDER BY s.id DESC
a8. group by子句 SELECT s.grade, COUNT(*) FROM Student AS s GROUP BY s.grade
a9. having子句 SELECT s.grade FROM Student AS s GROUP BY s.grade HAVING COUNT(s.id) > 20
a10. 分页查询
setFirstResult(int firstResult):设置检索返回的首个对象的位置。默认的起始位置是0。
setMaxResult(int maxResults): 设置每次检索返回的最大对象数
Query query = session.createQuery("FROM Student");
List list = query.setFirstResult(9).setMaxResult(10).list();
a11. 批量更新和删除
String hql = "DELETE Student AS s WHERE s.name LIKE :likeName";
Query query = session.createQuery(hql);
query.setString(“likeName”, “%三%”);
int count = query.executeUpdate(); // 返回受此操作影响的记录数量
注意:
where和having的区别在于作用对象不同:where作用于类的属性
having作用于分组后的组
b.标准化条件查询(criteria queries):比sql语句更面向对象的查询语句
QBC(Queries by criteria)主要由四部分组成:
Criteria接口:一个查询条件存放容器。
通过Session的createCriteria(Class persistentClass)来获取实例。
Criterion接口:代表一个查询条件。
Restrictions类:提供了一系列用于产生具体查询条件实例的静态方法。
作为hibernte2中Expression的替代
具体的查询条件通过Criteria的add()方法添加到Criteria实例中。
Order类:提供对查询结果进行排序的静态方法。
通过Criteria的addOrder()方法来添加。
Projection接口:代表投影查询。
Projections类:提供了一系列产生具体Projection实例的静态方法。
通过Criteria的setProjection()方法来添加。
举例://通过session创建一个Criteria实例
Criteria criteria = session.createCriteria(Student.class);
//设定查询条件
Criterion criterion1 = Restrictions.like("name", "张%");
Criterion criterion2 = Restrictions.like("grade", "初三%");
//把查询条件加入到Criteria中
criteria.add(criterion1);
criteria.add(criterion2);
criteria.addOrder(Order.desc("id"));
//执行查询语句,返回结果
List list = criteria.list();
a和b两种语言的区别:
hql适用于静态查询和业务比较复杂的查询;在
qbc适用于动态查询:只有在程序运行时才能明确要查询的字段
c.高级查询:
子查询:
String hql = "from Account a where (select count(o) from a.orders o)";
List<Account> list = session.createQuery(hql).list();
连接查询:
抓取连接
d.原生sql查询(native sql Queries):直接使用sql语言或特定数据库的查询
对原生SQL查询的控制是通过SQLQuery接口进行的
通过执行Session.createSQLQuery()获取这个接口。
例子:
//创建一个SQLQuery接口实现类的实例(传入的是SQL语句),然后执行查询
List<Account> list = session.createSQLQuery(
"SELECT * FROM ACCOUNT WHERE id > :id limit 3")
. addEntity(Account.class) //加入要返回的实体
.setLong("id", 1) //给命名参数传值
.list(); //执行查询
e.调用存储过程:(没有使用过的)
存储过程/函数必须返回一个结果集,作为Hibernate能够使用的第一个外部参数。
DROP PROCEDURE IF EXISTS findAccounts;
CREATE PROCEDURE findAccounts(IN idValue bigint(20))
begin
select * from account where id > idValue;
end;
在Hibernate通过命名查询来映射存储过程:
</hibernate-mapping>
...
<sql-query name="findAccounts">
<return alias="acc" class="com.qiujy.domain.Account">
<!-- 如果实体类的属性名和表的字段名相同,以下可省略 -->
<return-property name="id" column="id"/>
<return-property name="userName" column="userName"/>
</return>
<!-- 调用存储过程 -->
{call findAccounts(:idVal)}
</sql-query>
</hibernate-mapping>
第三篇:集合映射
*集合映射
set:元素存放没有顺序且不可以重复
bag:
list:元素有序且可以重复
Map:键值对应
排序集合和:在<set>和<map>元素上添加sort属性,指定排序规则
<set name="hobbies" table="student_hobby" sort="natural">
<!-- key子元素:指定集合属性对应的表的外键列 -->
<key column="student_id" />
<!-- element子元素:映射集合内的元素 -->
<element type="string" column="hobby_name" not-null="true" />
</set>
有序集合:有序集合是指在从数据库获取数据时就使用SQL语句的order by语句排好序,然后再封装到集合中存放。
<set name="hobbies" table="student_hobby" order-by="hobby_name desc">
<!-- key子元素:指定集合属性对应的表的外键列 -->
<key column="student_id" />
<!-- element子元素:映射集合内的元素 -->
<element type="string" column="hobby_name" not-null="true" />
</set>
集合映射的简单原则:
大部分情况下用<set>。
实体类中的某个属性用了List类别,可以使用<bag>来映射。
很少情况下会使用到<list>和<map>
*关联关系映射 (详细请查看工程中的readme.txt,或者根据实例来理解)
多对一(many-to-one)
一对一(one-to-one)
一对多(one-to-many)
多对多(many-to-many)
*高级关系映射
继承关系映射
组件映射
复合主键映射<PIXTEL_MMI_EBOOK_2005>11 </PIXTEL_MMI_EBOOK_2005>
浙公网安备 33010602011771号