[size=large][align=center][b]爱上框架之hibernate框架[/b][/align][/size]
[size=medium][b]一、使用hibernate开发的步骤:[/b][/size]
1.创建工程
2.导入jar包
3.创建hibernate核心配置文件 hibernate.cfg.xml
路径:hibernate-release-5.2.10.Final\project\etc,放在src中。
[b][size=medium]二、hibernate对象的三种状态:[/size][/b]
1.瞬时对象 当对象被new出来时候,此对象为瞬时对象。超过作用域会被JVM垃圾回收器回收。
数据库中没有此对象对应的记录。
2.持久对象:数据库中存在数据与对象一一对应,但是此对象必须是与session相关联的
并且此session没有关闭。
3.脱管状态,数据库中存在此对象,但是此时session已经关闭了,但是此对象还存在。
此对象发生改变,hibernate检测不到。
[b][size=medium]三、hibernate的get和load方法的区别:[/size][/b]
1.对于get方法,hibernate会确认一下该id对应的数据是否存在,
首先在session缓存中查找,然后在二级缓存中查找,
还没有就查询数据库,数据库中没有就返回null。这个相对比较简单,也没有太大的争议。
主要要说明的一点就是在这个版本中get方法也会查找二级缓存!
2.load方法加载实体对象的时候,根据映射文件上类级别的lazy属性的配置(默认为true),
分情况讨论:
(1)若为true,则首先在Session缓存中查找,看看该id对应的对象是否存在,不存在则使用延迟加载,返回实体的代理类对象(该代理类为实体类的子类,由CGLIB动态生成)。等到具体使用该对象(除获取OID以外)的时候,再查询二级缓存和数据库,若仍没发现符合条件的记录,则会抛出一个ObjectNotFoundException。
(2)若为false,就跟get方法查找顺序一样,只是最终若没发现符合条件的记录,则会抛出一个ObjectNotFoundException。
[b][size=medium]四、save()方法和persist()方法的区别:[/size][/b]
1.save()方法不提交事务,都会插入数据到数据库,但是没有提交,数据会进行回滚。
2.persist()如果不添加事务,则根本不会提交数据到数据库中。
[b][size=medium]五、hibernate查询[/size][/b]
1.Get/load主键查询
2.对象导航查询
3.HQL查询, Hibernate Query language hibernate 提供的面向对象的查询语言。
注意点:此时的sql中的表必须要替换成为类,而表的列名必须要对应类的属性名。
注意:使用hql查询的时候 auto-import="true" 要设置true,如果是false,写hql的时候,要指定类的全名
4.Criteria 查询, 完全面向对象的查询(Query By Criteria ,QBC)
5.SQLQuery, 本地SQL查询
缺.点:不能跨数据库平台: 如果该了数据库,sql语句有肯能要改
使用场景: 对于复杂sql,hql实现不了的情况,可以使用本地sql查询。
例:分页查询:先查询总记录数,再分页查询。
[size=medium][b]六、hibernate C3P0连接池的配置:[/b][/size]
为什么不使用hibernate自带的连接池,而去使用C3P0连接池?
C3P0是一款流行的开源的数据库连接池,使用此连接池,可以提高对数据库的访问和使用的效率。
C3P0的配置,配置在hibernate.cfg.xml文件中
[size=medium][b]七、hibernate的主键生成策略:[/b][/size]
1.assigned:
特点:可以跨数据库,人为控制主键生成,。Hibernate不负责维护主键生成。
与Hibernate和底层数据库都无关,应尽量避免。
语法:
<id name="id" column="id">
<generator class="assigned" />
</id>
2.increment:
由Hibernate从数据库中取出主键的最大值(每个session只取1次),
以该值为基础,每次增量为1,在内存中生成主键,不依赖于底层的数据库。
<id name="id" column="id">
<generator class="increment" />
</id>
Hibernate调用org.hibernate.id.IncrementGenerator类里面的generate()方法,
使用select max(idColumnName) from tableName语句获取主键最大值。
特点:跨数据库,不适合多进程并发更新数据库,适合单一进程访问数据库,不能用于群集环境。
3.hilo:
特点:跨数据库,hilo算法生成的标志只能在一个数据库中保证唯一。
4.seqhilo
与hilo类似,通过hi/lo算法实现的主键生成机制,
只是将hilo中的数据表换成了序列sequence,
需要数据库中先创建sequence,适用于支持sequence的数据库,如Oracle。
<id name="id" column="id">
<generator class="seqhilo">
<param name="sequence">hibernate_seq</param>
<param name="max_lo">100</param>
</generator>
</id>
5.sequence
采用数据库提供的sequence机制生成主键,需要数据库支持sequence。
如oralce、DB、SAP DB、PostgerSQL、McKoi中的sequence。
MySQL这种不支持sequence的数据库则不行(可以使用identity)。
<generator class="sequence">
<param name="sequence">hibernate_id</param>
</generator>
hibernate_id 指定sequence的名称
特点:只能在支持序列的数据库中使用,如Oracle。
[size=medium][b]八、hibernate的关联关系[/b][/size]
在一对多与多对一的关联关系中,保存数据最好的通过多的一方来维护关系,这样可以减少update语句的生成,从而提高hibernate的执行效率!
配置一对多与多对一,这种叫“双向关联”
只配置一对多, 叫“单项一对多”
只配置多对一, 叫“单项多对一”
注意:配置了哪一方,哪一方才有维护关联关系的权限!
1、Inverse属性
是在维护关联关系的时候起作用的。
表示控制权是否转移。(在一的一方起作用)
Inverse , 控制反转。
Inverse = false 不反转; 当前方有控制权
True 控制反转; 当前方没有控制权
2、cascade 表示级联操作 【可以设置到一的一方或多的一方】
none 不级联操作, 默认值
save-update 级联保存或更新
delete 级联删除
save-update,delete 级联保存、更新、删除
all 同上。级联保存、更新、删除
[size=medium][b]九、hibernate延迟加载[/b][/size]
hibernate为了提高程序的效率,优化访问数据的数据,默认加载数据的时候设置了延迟加载。
延迟加载一般使用在one对多或者多对多的关系上面。
但是有时候延迟加载当我们关闭Session的时候会抛出异常,所以解决延迟加载有如下方法:
1.查询的方法当中即时打印数据。
2.使用hibernate.initlize(代理对象);初始化代理对象
3.在*.hbm.xml中配置延迟加载的数据 lasy=false false代表取消延迟加载。
[size=medium][b]十、Hibernate的缓存[/b][/size]
1、Hibernate的一级缓存(Session级别的缓存)
缓存容器Map:save(),get(),load()
第一个用户:Object ->Map容器中 key,value (class,id)
第二个用户:先去容器中去取(如果容器中存在,则直接提取,如果不存在,查询数据库,查询到数据存在容器中)
Session:clear();close();s.evict(Object);清除单个对象
缺点:声明周期短,数据存储在内容中,如果数据量过大,很容易导致内存溢出
2、二级缓存:SessionFactory:
1).在项目的src文件下面创建ehcache.xml
2).修改hibernate.cfg.xml,
在此配置文件中加上二级缓存的相关配置
3).配置需要查询的对象的映射文件*.hbm.xml
<!-- 缓存的策略
1.read-only 只读
2.read-write 允许读取或者更新数据 推荐使用
3.nonstrict-read-write 脏读,不严格的读写
4.transactional 支持事务,如果读取或者更新数据时报错,可以回滚。
-->
<cache usage="read-only"/>
用户查询数据的顺序:效率从高到低。
session(以及缓存)->cache(二级缓存)->db(数据库中去取)
二级缓存使用的注意事项:
1.一般适用于查询的数据,数据量处于中等。(10W下)
2.如果使用多个dao层的框架,hibernate在某些情况下不能检测到数据的一些更新状态时,则不推荐使用二级缓存
3.如果长期进行一些增删改的操作,也不推荐使用二级缓存。
MVC各层所对应框架
M - 模型层
dao -> hibernate,mybits,dbutils 基于orm的框架,推荐只使用一种
service -> spring ,springmvc
pojo
controll -> struts2,springmvc
view -> jsp
hibernate使用在dao层:
查询所有的方法:(对emp表进行查询,可实现根据雇员名称和薪水进行模糊查询)
四种查询结果的hql语句分解:
1.hql:from Emp where 1=1//查询所有雇员信息
2. hql:from Emp where 1=1 and ename like :ename//根据雇员名称模糊查询雇员信息
3.hql:from Emp where 1=1 and sal > :sal//根据雇员薪水模糊查询雇员信息
4.hql:from Emp where 1=1 and ename like :ename and sal > :sal//根据雇员名称和薪水模糊查询雇员信息
查询结果如下图所示:
[img]
[img]http://dl2.iteye.com/upload/attachment/0124/9821/4d60d7cb-cef2-3625-a239-69ea2d9bb9ff.png[/img]
[/img]
[size=medium][b]一、使用hibernate开发的步骤:[/b][/size]
1.创建工程
2.导入jar包
3.创建hibernate核心配置文件 hibernate.cfg.xml
路径:hibernate-release-5.2.10.Final\project\etc,放在src中。
[b][size=medium]二、hibernate对象的三种状态:[/size][/b]
1.瞬时对象 当对象被new出来时候,此对象为瞬时对象。超过作用域会被JVM垃圾回收器回收。
数据库中没有此对象对应的记录。
2.持久对象:数据库中存在数据与对象一一对应,但是此对象必须是与session相关联的
并且此session没有关闭。
3.脱管状态,数据库中存在此对象,但是此时session已经关闭了,但是此对象还存在。
此对象发生改变,hibernate检测不到。
[b][size=medium]三、hibernate的get和load方法的区别:[/size][/b]
1.对于get方法,hibernate会确认一下该id对应的数据是否存在,
首先在session缓存中查找,然后在二级缓存中查找,
还没有就查询数据库,数据库中没有就返回null。这个相对比较简单,也没有太大的争议。
主要要说明的一点就是在这个版本中get方法也会查找二级缓存!
2.load方法加载实体对象的时候,根据映射文件上类级别的lazy属性的配置(默认为true),
分情况讨论:
(1)若为true,则首先在Session缓存中查找,看看该id对应的对象是否存在,不存在则使用延迟加载,返回实体的代理类对象(该代理类为实体类的子类,由CGLIB动态生成)。等到具体使用该对象(除获取OID以外)的时候,再查询二级缓存和数据库,若仍没发现符合条件的记录,则会抛出一个ObjectNotFoundException。
(2)若为false,就跟get方法查找顺序一样,只是最终若没发现符合条件的记录,则会抛出一个ObjectNotFoundException。
[b][size=medium]四、save()方法和persist()方法的区别:[/size][/b]
1.save()方法不提交事务,都会插入数据到数据库,但是没有提交,数据会进行回滚。
2.persist()如果不添加事务,则根本不会提交数据到数据库中。
[b][size=medium]五、hibernate查询[/size][/b]
1.Get/load主键查询
Dept dept = (Dept) session.get(Dept.class, 10);
Dept dept = (Dept) session.load(Dept.class, 10); (支持懒加载)
2.对象导航查询
Dept dept = (Dept) session.get(Dept.class, 10);
System.out.println(dept.getDname());
System.out.println(dept.getEmps());
3.HQL查询, Hibernate Query language hibernate 提供的面向对象的查询语言。
注意点:此时的sql中的表必须要替换成为类,而表的列名必须要对应类的属性名。
注意:使用hql查询的时候 auto-import="true" 要设置true,如果是false,写hql的时候,要指定类的全名
Query q = session.createQuery("from Dept");
System.out.println(q.list());
4.Criteria 查询, 完全面向对象的查询(Query By Criteria ,QBC)
Criteria criteria = session.createCriteria(Emp.class);
criteria.add(Restrictions.eq("empNo", 12));
5.SQLQuery, 本地SQL查询
缺.点:不能跨数据库平台: 如果该了数据库,sql语句有肯能要改
使用场景: 对于复杂sql,hql实现不了的情况,可以使用本地sql查询。
SQLQuery q = session.createSQLQuery("select * from Dept where deptno = 20 ") System.out.println(q.list());
例:分页查询:先查询总记录数,再分页查询。
@Test
public void all() {
Session session = HibernateSessionFactory.getSession();
Transaction tr = session.beginTransaction();
Query q = session.createQuery("from Emp");
ScrollableResults scroll = q.scroll(); // 得到滚动的结果集
scroll.last(); // 滚动到最后一行
int totalCount = scroll.getRowNumber() + 1;// 得到滚到的记录数,即总记录数
// 设置分页参数
q.setFirstResult(0);
q.setMaxResults(5);
System.out.println(q.list()); // 查询
System.out.println("总记录数:" + totalCount);
tr.commit();
HibernateSessionFactory.closeSession();
}
[size=medium][b]六、hibernate C3P0连接池的配置:[/b][/size]
为什么不使用hibernate自带的连接池,而去使用C3P0连接池?
C3P0是一款流行的开源的数据库连接池,使用此连接池,可以提高对数据库的访问和使用的效率。
C3P0的配置,配置在hibernate.cfg.xml文件中
<!-- hibernate连接池的供应类 -->
<property name="connection.provider_class">
org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider
</property>
<!-- hibernate连接池的最小个数 -->
<property name="c3p0.min_size">3</property>
<!-- hibernate连接池中的最大个数 -->
<property name="c3p0.max_size">20</property>
<!-- 连接池中执行sql语句的最大个数,同时执行50条sql语句 -->
<property name="c3p0.max_statements">50</property>
<!-- 连接超时数,单位为毫秒 -->
<property name="c3p0.timeout">1800</property>
<!-- 连接自动增长的个数 -->
<property name="c3p0.acquire_increment">2</property>
[size=medium][b]七、hibernate的主键生成策略:[/b][/size]
1.assigned:
特点:可以跨数据库,人为控制主键生成,。Hibernate不负责维护主键生成。
与Hibernate和底层数据库都无关,应尽量避免。
语法:
<id name="id" column="id">
<generator class="assigned" />
</id>
2.increment:
由Hibernate从数据库中取出主键的最大值(每个session只取1次),
以该值为基础,每次增量为1,在内存中生成主键,不依赖于底层的数据库。
<id name="id" column="id">
<generator class="increment" />
</id>
Hibernate调用org.hibernate.id.IncrementGenerator类里面的generate()方法,
使用select max(idColumnName) from tableName语句获取主键最大值。
特点:跨数据库,不适合多进程并发更新数据库,适合单一进程访问数据库,不能用于群集环境。
3.hilo:
特点:跨数据库,hilo算法生成的标志只能在一个数据库中保证唯一。
4.seqhilo
与hilo类似,通过hi/lo算法实现的主键生成机制,
只是将hilo中的数据表换成了序列sequence,
需要数据库中先创建sequence,适用于支持sequence的数据库,如Oracle。
<id name="id" column="id">
<generator class="seqhilo">
<param name="sequence">hibernate_seq</param>
<param name="max_lo">100</param>
</generator>
</id>
5.sequence
采用数据库提供的sequence机制生成主键,需要数据库支持sequence。
如oralce、DB、SAP DB、PostgerSQL、McKoi中的sequence。
MySQL这种不支持sequence的数据库则不行(可以使用identity)。
<generator class="sequence">
<param name="sequence">hibernate_id</param>
</generator>
hibernate_id 指定sequence的名称
特点:只能在支持序列的数据库中使用,如Oracle。
[size=medium][b]八、hibernate的关联关系[/b][/size]
在一对多与多对一的关联关系中,保存数据最好的通过多的一方来维护关系,这样可以减少update语句的生成,从而提高hibernate的执行效率!
配置一对多与多对一,这种叫“双向关联”
只配置一对多, 叫“单项一对多”
只配置多对一, 叫“单项多对一”
注意:配置了哪一方,哪一方才有维护关联关系的权限!
1、Inverse属性
是在维护关联关系的时候起作用的。
表示控制权是否转移。(在一的一方起作用)
Inverse , 控制反转。
Inverse = false 不反转; 当前方有控制权
True 控制反转; 当前方没有控制权
2、cascade 表示级联操作 【可以设置到一的一方或多的一方】
none 不级联操作, 默认值
save-update 级联保存或更新
delete 级联删除
save-update,delete 级联保存、更新、删除
all 同上。级联保存、更新、删除
[size=medium][b]九、hibernate延迟加载[/b][/size]
hibernate为了提高程序的效率,优化访问数据的数据,默认加载数据的时候设置了延迟加载。
延迟加载一般使用在one对多或者多对多的关系上面。
但是有时候延迟加载当我们关闭Session的时候会抛出异常,所以解决延迟加载有如下方法:
1.查询的方法当中即时打印数据。
2.使用hibernate.initlize(代理对象);初始化代理对象
3.在*.hbm.xml中配置延迟加载的数据 lasy=false false代表取消延迟加载。
[size=medium][b]十、Hibernate的缓存[/b][/size]
1、Hibernate的一级缓存(Session级别的缓存)
缓存容器Map:save(),get(),load()
第一个用户:Object ->Map容器中 key,value (class,id)
第二个用户:先去容器中去取(如果容器中存在,则直接提取,如果不存在,查询数据库,查询到数据存在容器中)
Session:clear();close();s.evict(Object);清除单个对象
缺点:声明周期短,数据存储在内容中,如果数据量过大,很容易导致内存溢出
2、二级缓存:SessionFactory:
1).在项目的src文件下面创建ehcache.xml
2).修改hibernate.cfg.xml,
在此配置文件中加上二级缓存的相关配置
<!-- 二级缓存供应工厂 -->
<property name="cache.region.factory_class">
org.hibernate.cache.ehcache.EhCacheRegionFactory
</property>
<!-- 是否使用二级缓存,默认为true:使用。可设置为false不启用 -->
<property name="cache.use_second_level_cache">true</property>
<!-- 查询时应用缓存 -->
<property name="cache.use_query_cache">true</property>
3).配置需要查询的对象的映射文件*.hbm.xml
<!-- 缓存的策略
1.read-only 只读
2.read-write 允许读取或者更新数据 推荐使用
3.nonstrict-read-write 脏读,不严格的读写
4.transactional 支持事务,如果读取或者更新数据时报错,可以回滚。
-->
<cache usage="read-only"/>
用户查询数据的顺序:效率从高到低。
session(以及缓存)->cache(二级缓存)->db(数据库中去取)
二级缓存使用的注意事项:
1.一般适用于查询的数据,数据量处于中等。(10W下)
2.如果使用多个dao层的框架,hibernate在某些情况下不能检测到数据的一些更新状态时,则不推荐使用二级缓存
3.如果长期进行一些增删改的操作,也不推荐使用二级缓存。
MVC各层所对应框架
M - 模型层
dao -> hibernate,mybits,dbutils 基于orm的框架,推荐只使用一种
service -> spring ,springmvc
pojo
controll -> struts2,springmvc
view -> jsp
hibernate使用在dao层:
/**
* 封装对数据库中的表的操作 (新增 / 修改 / 删除 / 根据id查询)
*
*/
public class HibernateDao<T> {
public T find(Class<T> classz, Serializable id) {
Session session = HibernateSessionFactory.getSession();
T t = session.get(classz, id);
HibernateSessionFactory.closeSession();
return t;
}
public void add(T t) {
Session session = HibernateSessionFactory.getSession();
Transaction tx = session.beginTransaction();
session.save(t);
tx.commit();
HibernateSessionFactory.closeSession();
}
public void modify(T t) {
Session session = HibernateSessionFactory.getSession();
Transaction tx = session.beginTransaction();
session.update(t);
tx.commit();
HibernateSessionFactory.closeSession();
}
public void remove(T t) {
Session session = HibernateSessionFactory.getSession();
Transaction tx = session.beginTransaction();
session.delete(t);
tx.commit();
HibernateSessionFactory.closeSession();
}
}
查询所有的方法:(对emp表进行查询,可实现根据雇员名称和薪水进行模糊查询)
public class EmpDao extends HibernateDao<Emp> {
/**
* 多条件查询
* @param ename
* @param sal
* @return
*/
@SuppressWarnings("unchecked")
public List<Emp> find(String ename, Double sal) {
Session session = HibernateSessionFactory.getSession();
Transaction tr = session.beginTransaction();
String hql = "from Emp where 1=1 ";
if (ename != null && ename.trim().length() > 0) {
hql += " and ename like :ename ";
}
if (sal != null && sal > 0D) {
hql += " and sal > :sal ";
}
Query query = session.createQuery(hql);
if (ename != null && ename.trim().length() > 0) {
query.setString("ename", "%" + ename.toUpperCase() + "%");
}
if (sal != null && sal > 0D) {
query.setDouble("sal", sal);
}
ScrollableResults scroll = query.scroll();//得到滚动结果集
scroll.last(); //滚动到最后一条记录
int totalCont = scroll.getRowNumber()+1; //得到总记录数
query.setFirstResult(0); // 设置分页参数
query.setMaxResults(10);
List<Emp> emps = query.list();
//强制加载关联的数据、得到dept表中的数据
for(Emp emp:emps){
Hibernate.initialize(emp.getDept());
}
tr.commit();
HibernateSessionFactory.closeSession();
return emps;
}
}
四种查询结果的hql语句分解:
1.hql:from Emp where 1=1//查询所有雇员信息
2. hql:from Emp where 1=1 and ename like :ename//根据雇员名称模糊查询雇员信息
3.hql:from Emp where 1=1 and sal > :sal//根据雇员薪水模糊查询雇员信息
4.hql:from Emp where 1=1 and ename like :ename and sal > :sal//根据雇员名称和薪水模糊查询雇员信息
查询结果如下图所示:
[img]
[img]http://dl2.iteye.com/upload/attachment/0124/9821/4d60d7cb-cef2-3625-a239-69ea2d9bb9ff.png[/img]
[/img]