Fork me on GitHub

Hibernate

Hibernate(数据访问层)

概念:是数据访问层的框架,对JDBC进行了封装,是针对数据库访问提出的面向对象的解决方案(ORM);
使用Hibernate可以直接访问对象,将访问转换成SQL执行对象–>数据库
Hibernate:采用数据库与Entity映射,对JDBC封装程度较重,自动生成SQL,对于基本的操作,开发效率高
MyBatis:采用SQL与Entity映射,对JDBC封装程度较轻,自己写SQL,更具灵活性
Hibernate与MyBatis共同点:对JDBC进行了封装,采用ORM思想解决了Entity和数据库的映射问题
ORM思想:Object Relation Mapping对象关系映射(java对象和关系数据库直接的映射)
主配置文件:hibernate.cfg.xml;配置数据库连接参数,框架参数,映射关系文件;实体类,映射关系文件

Hibernate常用API

Configuration,SessionFactory,Session,Transaction,Query

Hibernate主键生成方式

sequence:是采用序列方式生成主键,适用于Oracle数据库;
identity:采用数据库自增长机制生成主键,适用于Oracle之外的其他数据库
native:根据当前配置的数据库方言,自动选择sequence或者identity
increment:Hibernate提供的一种生成主键方式,获取当前表中主键的最大值,然后加1作为新的主键(在并发量高时,可能会生成重复的主键)
assigned:Hibernate不负责生成主键,需要程序员自己处理主键的生成。
uuid/hilo:采用uuid或hilo算法生成一个主键值,这个主键值是一个不规则的长数字

创建Session工具类

1
2
3
4
Configuration conf=new Configuration().configure("/hibernate.cfg.xml");
SessionFactory = conf.buildSessionFactory();
session = SessionFactory.openSession();
session.save(e);

开启事务

1
Transaction ts = session.beginTransaction();

回滚事务

1
ts.rollback();

一级缓存

Hibernate创建每个Session对象时,都会给该Session分配一块独立的缓存区(一级缓存,Session级缓存),用于存放该Session查询出来的对象。
Session取数据时,会优先向缓存区取数据,没有才去数据库查询,降低数据库访问次数,提高代码效率。
一级缓存是Session独享,每个Session不能访问其他Session的缓存区,Session的save、update、delete操作会触发缓存更新。线程不安全

二级缓存

SessionFactory级别的缓存(全局),二级缓存的数据是Session间共享的。

延迟加载(提升内存资源利用率,降低对数据库访问次数)

在使用Hibernate方法查询数据时,返回的是一个空对象(只有id),只有在使用这个对象时,才会触发查询数据库,写入数据
使用延迟加载要避免Session提前关闭,要在视图层保持session的开启

关联映射

一对多关联

通过增/删/改/查一,自动增/删/改/查多

1
2
3
4
5
<!-- replies属性,本类与Reply的一对多-->
<set name="replies">
<key column="topicId"></key>
<one-to-many class="Reply"/>
</set>

多对一关联

1
2
<!-- topic属性,本类与Topic的多对一-->
<many-to-one name="topic" class="Topic" column="topicId"></many-to-one>

多对多关联

1
2
3
4
5
6
7
8
9
10
<!-- users属性,本类与User的多对多(Role类) -->
<set name="users" table="itcast_user_role">
<key column="roleId"></key>
<many-to-many class="User" column="userId"></many-to-many>
</set>
<!-- roles属性,本类与Role的多对多(User类) -->
<set name="roles" table="itcast_user_role" lazy="false">
<key column="userId"></key>
<many-to-many class="Role" column="roleId"></many-to-many>
</set>

一对一关联

1
<property name="name" />

继承关联

级联操作:通过关联映射,在对一方进行增删改查时,连带增删改关联的另一方数据。(cascade="save-update/delete/all")

实体查询

1
2
3
4
5
6
7
8
9
public void testQueryAllDept(){
String hql="from Employee";
//hql="from com.sh.Entity";
Query query=session.createQuery(hql);
List<Employee> list= query.list();
//...
}

有条件的 实体查询 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public void testQueryAllDept(){
String hql="from Deptas model where mode.deptName like '%部%' ";
//hql="from com.sh.Entity";
Query query=session.createQuery(hql);
List<Employee> list= query.list();
//...
}
public void testQueryDeptByGt(){
String hql="from Dept model where model.createDate> '2012-03-10'";
Query query=session.createQuery(hql);
List<Employee> list= query.list();
}
// delete 删除
public void testDelDeptByHql(){
Transaction tr=session.beginTransaction();
String hql="delete Dept as model where model.deptId=6";
Query query=session.createQuery(hql);
query.executeUpdate();
tr.commit();
}

属性查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public void testQueryDeptName(){
String hql="select model.deptName from Dept as model";
Query query=session.createQuery(hql);
List<String> deptNameList=query.list();
//...
}
public void testQueryDeptName(){
String hql="select model.deptName,model.createDate from Dept as model";
Query query=session.createQuery(hql);
List<Object[]> prsList=query.list();
for(){
}
//...
}
//采用对象进行 保存 查询的字段(要添加 对应字段的构造方法)
public void testQueryDeptName(){
String hql="select new Dapt(model.deptName,model.createDate) from Dept as model";
Query query=session.createQuery(hql);
List<Dept> deptList=query.list();
for(Dept d:deptList){
d.setDeptName("test");
session.saveOrUpdate(dept);
}
//...
}
//如果采用对象 保存上面查询出来的对象 如果对其进行更新的操作 是不会成功的
public void testSaveDept(){
Transction tr=session.beginTransactino();
String hql="select new Dept(model.deptName,model.createDate) from Dept as model";
Query query=session.createQuery();
List<Dept> deptList=query.list();
for(Dept dept:deptList){
System.out.println(dept.deptName);
dept.setDetpName("test");
session.saveOrUpdate(dept);
}
tr.commit();
// 最后 根本就没有更新 而是 在数据库中 插入 新的记录
}

查询单个对象

1
2
3
4
5
6
7
public void testQueryUn(){
String hql="select model.deptName from Dept as model where model.deptId=2";
Query query=session.createQuery(hql);
query.setMaxResults(1);
String deptName=(String)query.uniqueResult();
System.out.println(deptNamae);
}

绑定参数

  • 使用 “:”加参数名 绑定参数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public void testQueryByParamsName(){
    //使用 ":参数名" 来传递参数
    String hql="from Dept as model where
    odel.deptName=:deptName and model.createDate=:createDate";
    Query query=session.createQuery(hql);
    query.setString("deptName","test");
    query.setString("ceateDate","2000-02-10");
    List<Dept> deptList=query.list();
    for(){}
    //...
    }
  • 使用 “?” 按照位置来绑定参数

1
2
3
4
5
6
7
8
9
public void testQueryByParamsID(){
String hql="from Dept as model where model.deptName=? and model.createDate=?";
Query query=session.createQuery(hql);
query.setString(0,"test");
query.setString(1,"2000-02-02");
List<Dept> list=query.list();
for(){}
//..
}
  • 采用setEntity() 将参数和一个持久化对象进行绑定
1
2
3
4
5
6
7
8
9
public void testQueryByDept(){
Dept dept=(Dept)Session.get(Dept.clas,new Integer(2));
String hql="select Employee as model where model.dept=?"
Query query=session.createQuery(hql);
query.setEntity(0,dept);
List<Employee> empList=query.list();
for(){}
//..
}

用Query是不能insert的;
使用HQL语句来完成插入操作是不能实现的,不管你使用insert into….values…还是insert into…..select…..都不行
原因:因为Hibernate的HQL语言是用于面向对象实现查询功能的,然而在插入操作中是不会牵涉任何查询动作的,所以HQL不能用于insert语句的插入操作,而select、update、delete语句都可以有可能的查询实现,比如:
select语句时标准的查询,这个就不用再说了
update语句:update 对象名 set…..where……
delete语句:delete from 对象名 where …..
看到了没有,update与delete牵涉到where的查询筛选过程,这个过程是需要采用HQL来实现的,然而insert永远牵涉不到查询筛选过程,所以Hibernate没有对插入做insert实现。
update语句:
既然都用了hibernate支持类,就别拼hql语句了,直接set属性值,再调用getHibernateTemplate().update(obj)就行了~

「真诚赞赏,手留余香」