Hibernate学习总结(非常详细的总结,希望对初学者有帮助)
来源:互联网 发布:thinkphp js跳转页面 编辑:程序博客网 时间:2024/05/17 00:10
Hibernate学习总结
花了几天的时间把Hibernate学习了一下,在这里做一个总结,也算是对学习内容的一个梳理,如果能帮助到看这篇文章的童鞋,那自然是最好不过了。
用java语言去操作数据库,javaAPI自带的有JDBC,但是,JDBC无法直接面向对象,弊端是:
1.开发效率低2.代码冗余3.重复性工作多Hibernate对JDBC进行了非常轻量级的对象封装,使我们能够用面向对象的思维去操作数据库。
一、Hibernate核心接口和类
Hibernate的核心接口一共有6个,分别为:Session、SessionFactory、Transaction、Query、Criteria和Configuration。
Session接口: 用来执行执行被持久化对象的CRUD(增删改查)操作.
SessionFactory接口: SessionFactory接口负责初始化HibernateSessionFactory是重量级的,所以一个项目通常只需要一个SessionFactory了,然后由SessionFactory创建Session对象。
Transaction接口:用来处理事务的接口。
Configuration类:Configuration对象用来配置和引导Hibernate,一个Hibernat
e应用使用一个Configuration实例来指定主 配置文件的位置,然后创建会话工厂。
二、Hibernate使用前的准备
使用Hibernate前需要搭建项目框架编写hibernate配置文件、实体映射文件。
1)hibernate配置文件默认文件名为“hibernate.cfg.xml”。配置如下
<?xml version='1.0' encoding='utf-8'?><!DOCTYPE hibernate-configuration PUBLIC"-//Hibernate/Hibernate Configuration DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"><hibernate-configuration><session-factory><!-- 数据库连接URL --><property name="connection.url">jdbc:oracle:thin:@localhost:1521:XE</property><!-- 数据库用户名 --><property name="connection.username">oa</property><!-- 数据库密码 --><property name="connection.password">oa123</property><!-- 数据库JDBC驱动类名 --><property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property><!-- 数据库方言 --><property name="dialect">org.hibernate.dialect.Oracle10gDialect</property><!-- ddl语句自动建表 --><property name="hbm2ddl.auto">none</property><!-- 是否输出Hibernate生成的SQL语句,开发阶段一般需要开启 --><property name="show_sql">true</property><!-- 是否对输出SQL进行格式化 --><property name="format_sql">true</property><!-- 连接池配置 --><property name="hibernate.connection.provider_class">org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider</property><!-- 这是C3P0随时准备好的最少的JDBC连接数量 --><property name="hibernate.c3p0.min_size">5</property><!-- 连接池中JDBC连接的最大数量 --><property name="hibernate.c3p0.max_size">20</property><!-- 超时周期,在它之后,闲置连接将从池中移除 --><property name="hibernate.c3p0.timeout">300</property><!-- 最多高速缓存100个预编译语句,该属性是使Hibernate获得较好性能的要素。 --><property name="hibernate.c3p0.max_statements">100</property><!-- 连接被自动验证前,以秒为单位的闲置时间 --><property name="hibernate.c3p0.idle_test_period">3000</property><!-- 注册ORM实体类映射文件--><mapping resource="实体类映射文件路径" />…</session-factory></hibernate-configuration>注:数据库不同连接信息也不同,这里使用的是Oracle10g。mapping resource可以在下面写多条。2)编写实体映射文件。
<1>创建实体类实体类(也称持久化类)是一个带有一些属性的JavaBean类,实体类对属性的存取方法(getter and setter method)使用了标准JavaBean命名约定,同时把类属性的访问级别设成私有的。为了通过反射机制来实例化类的对象,我们需要提供一个无参的构造器,所有的实体类都要求有无参的构造器,因为Hibernate需要使用Java反射机制来为你创建对象。
最后要为实体类实现Java.io.Serializable 接口,以便Hibernate能更好的缓存实体对象。 通过实体映射文件,Hibernate知道怎样去加载和存储实体类的对象,知道应该访问数据库里面的哪个表及应该使用表里面的哪些字段。
实例如下:
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><hibernate-mapping><class name="org.ijob.bean.Seeker" table="ijob_seeker"><!-- 主键映射 --><id name="id" type="string"><column name="id" length="32"></column><generator class="uuid" /></id> <!—属性映射 --><property name="email" type="string"><column name="email" length="100"></column></property><property name="password" type="string"><column name="password" length="20"></column></property><property name="name" type="string"><column name="name" length="10"></column></property><!—此处省略系列属性映射 --></class></hibernate-mapping>注:也可以不用写类型和长度,<property name="name" column name="name"></property>,映射文件名后缀hbm.xml;<2>主键生成策略,为了不用在向数据库输入数据的时候每次都要给主键一个ID,可以让系统自动生成,这样可以避免人为输入的重复。如下:
<generator class="sequence" ><param name="sequence">sequence_name</param><!--sequence对象的名字 --></generator>这样配置之后,每次往数据库中插入新对象,都调用数据库的“sequence_name”所指定的sequence对象来产生其标识符。uuid:每次新增对象时,用一个128-bit的UUID算法生成长度为32的字符串类型的标识符。当然这也可选的,不配置也可以。
映射文件配置好以后,将映射文件的路径信息添加到hibernate.cfg.xml中。
<mapping resource=“***/***/***.hbm.xml"/>
注意问题:映射文件在配置的时候要注意Hibernate关联映射,对于实体之间的关系为通过一个对象持有另一个对象的实例,但是在映射文件中是怎么样来表示的呢?
1.单向多对一关联,many的一端应持有one的一端的对象(引用)代码示例
2.单向一对多关联,one的一端应持有many端的对象集合。
解释:多本书对应一种书籍类型,体现多对一。
一本书应该有很多的借阅记录,体现一对多。
<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><hibernate-mapping><!-- 类和表 --><class name="entity.Book" table = "books"><!-- 属性和主键 --><id name="isbn" column="book_id"><!-- 主键生成策略 --><generator class="sequence"><param name="sequence">lib_seq</param><!--sequence对象的名字 --></generator></id><!-- 属性和字段 --><property name="name" column="name" length="20"></property><property name="price" column="price" ></property><property name="author" column="author" length="20"></property><property name="count" column="count"></property><property name="press" column="press" length="20"></property><!-- 多本书一种类型 --><many-to-one name="type" class="entity.Type" > <column name="type_id" ></column></many-to-one> <!-- 一本书可以有多条记录,书的映射文件,先看书对应 --><set name="records"><key column="book_id"></key><one-to-many class="entity.Record"/></set></class></hibernate-mapping>三、数据库操作
这些准备工作都做完以后就可以对数据库进行操作了。流程为
获取配置信息>>创建SessionFactory>>打开Session>>开始一个事物>>持久化操作>>提交事物>>关闭Session
事例代码:
// 1、获取配置Configuration cfg = new Configuration().configure();ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(cfg.getProperties()).buildServiceRegistry();// 2、创建SessionFactorySessionFactory factory = cfg.buildSessionFactory(serviceRegistry);// 3、获取sessionSession session = factory.openSession();Transaction tx = session.getTransaction();try {// 4、开启事务tx.begin();Seeker seeker = new Seeker();seeker.setEmail("abc@163.com");seeker.setPassword("abc");// 5、保存seeker对象session.save(seeker);// 6、提交事务session.getTransaction().commit();} catch (Exception e) {tx.rollback();e.printStackTrace();} finally {// 7、关闭sessionsession.close();}}注:session.close()写在finally里,以确保这个方法可以被执行。session可操作的对象为,持久态的对象,session中的三种状态为瞬时状态,持久状态,游离状态,我们直接new一个对象为还没有被持久化,而且不处于Session的缓存中为瞬时态,我们可以通过save,update使瞬时太转为持久态,如果我们delete这个对象,则又放回瞬时态,session关闭后持久态转为游离态,不过可以通过get重新使游离态变为持久态。
每次我们操作数据都要写前面的一些获取session的信息,我们可以将相同的代码封装,建立一个工具类HibernateUtils,
这样通过方法一句就可以获得这个Session的实例。
难点
Hibernate默认的加载数据的方法为延迟加载,也就是对于一些属性里面有关联对象或者集合的类,当你去查询获得这个类的属性的时候,这些关联的对象或者集合不会直接返回给你。示例:
public void test() {Session session = HibernateUtils.currentSession();Type type = (Type) session.get(Type.class, 1);System.out.println(type.getName());System.out.println("=========================");HibernateUtils.closecurrentSession();Set<Book> books = type.getBooks();System.out.println(books);}我们先不看其他的东西,有一个书籍类型的类,这个类里面包含了书的集合(一个书籍类型包含很多书);我们用session方法或者这个ID为1的书籍类型,然后关闭Session,从打印结果可以看出,关闭Session之前,我们可以直接获得Type类的属性(除关联对象或者集合),打印输出。关闭后,我们不能获得,Book类的集合。这就是延迟加载,不会立刻返回所有数据给你。如果直接返回所有数据,可能一个表里面关联其他对象和集合,这样都一次加载完,有些可能我们不需要的数据也都给返回了,造成内存的浪费,效率也不高。
解决Session关闭在调用对象方法的办法
1.在一个线程内只有一个Session,在我们把这个调用链路全部走完最后关闭Session,这样我们可以任意调用数据。参考文章http://blog.csdn.net/zhengwei223/article/details/9376299;这个最好写在工具类HibernateUtils,示例代码
import org.hibernate.HibernateException;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.cfg.Configuration;import org.hibernate.service.ServiceRegistry;import org.hibernate.service.ServiceRegistryBuilder;public class HibernateUtils {public static final SessionFactory SESSION_FACTORY; // 静态变量public static final ThreadLocal<Session> HIBERNATE_SESSION_LOCAL = new ThreadLocal<Session>(); //线程的变量static {// 静态初始化块try {Configuration cfg = new Configuration().configure();// Hibernate4提供的新方式ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(cfg.getProperties()).buildServiceRegistry();SESSION_FACTORY = cfg.buildSessionFactory(serviceRegistry);} catch (Throwable ex) {throw new ExceptionInInitializerError(ex);}} /** * 创建一个session制造器 * @return 返回一个SessionFactory * */ public static SessionFactory getSessionFactory() {return SESSION_FACTORY;}/** * 关闭该session工厂 * */public static void shutdown() {getSessionFactory().close();}/** * * @return返回一个线程的session * */ public static Session currentSession() throws HibernateException { Session s = HIBERNATE_SESSION_LOCAL.get(); if(s == null) { s = SESSION_FACTORY.openSession(); HIBERNATE_SESSION_LOCAL.set(s); } return s; } /** * 关闭一个线程的session * */ public static void closecurrentSession() throws HibernateException { Session s = HIBERNATE_SESSION_LOCAL.get(); if(s != null) { s.close(); } HIBERNATE_SESSION_LOCAL.set(null); } }注:SessionFactory是重量级的,创建很费资源,在一个线程中只需要一个就够了。而且是共享的。2.第一次获得该对象的时候用get而不用load,因get不支持懒加载,在get该对象的同时会想数据库发出sql语句,取出该对象的相应信息放入缓存中,下次即使session已经关闭,因缓存中有相应的数据,查找该对象时会首先从缓存中查询,直接拿来用就ok了。
3.在映射文件中lazy设为false,这样在load该对象的同时就会发sql语句取出该对象放到缓存中,以后再用可以直接从缓存中取。但是这种方法一般不推荐使用。
四、Hibernate的缓存机制
一级缓存:session级的缓存也叫事务级的缓存,只缓存实体,生命周期和session一致。不能对其进行管理。在Session的save()、update()、saveOrUpdate()、get()或load(),如果在Session缓存中还不存在相应的对象,Hibernate就会把该对象加入到第一级缓存中。
二级缓存:sessionFactory缓存,也叫进程级的缓存,也值缓存实体,生命周期和sessionFactory一致,可以进行管理。
- Hibernate学习总结(非常详细的总结,希望对初学者有帮助)
- Servlet总结,希望对初学者有所帮助
- FlexViewer学习资料,希望对初学者有帮助(转)
- FlexViewer学习资料,希望对初学者有帮助(转)
- 我的五年总结,希望对大家有帮助
- JAVA初学者之旅(希望对JAVA初学者学习有帮助)
- FlexViewer学习资料,希望对初学者有帮助
- FlexViewer学习资料,希望对初学者有帮助
- 分享下一步步学习java的内容,希望对初学者有帮助,1.java的认识
- 浅谈单片机调试方法(希望对初学者有帮助)
- Hibernate 学习笔记(对关键知识点的系统化总结,亲,百分百对你有帮助哦!)
- 关于ASP的(VBScript)类,只希望给初学者看一看,希望对你们有帮助
- 自己攒的一些总结,希望对新学的有帮助
- 总结4点对学习Linux有帮助的建议
- 总结4点对学习Linux有帮助的建议
- 关于RDLC报表的一些总结,希望对正在学习使用它的朋友有所帮助
- 通过H5的新标签canvas做出一个时钟的全过程,希望对初学者有帮助
- 简单的整理了一下分页,希望对初学者有帮助
- UVA 579 (13.07.20)
- Hibernate学习总结(1)
- jquery 遍历数组与数组详细说明
- xCAT裸机部署 ( by quqi99 )
- Java telnet连接的实现
- Hibernate学习总结(非常详细的总结,希望对初学者有帮助)
- 【deep learning学习笔记】注释yusugomori的DA代码 --- dA.h
- Hibernate学习总结
- 初学orCAD原理图
- C++文件操作
- 转载:cocos2d-x下硬件音量按键控制游戏音量的实现
- Windows7平台下安装和配置MySQL
- UVA 1426 - Discrete Square Roots
- Oracle 12C静默安装与配置