Hibernate技术(一)--Hibernate初步

Hibernate初步

ORM:在编写程序时,处理数据采用面向对象的方式,而保存数据却以关系型数据库的方式,因此需要一种能在两者之间进行转换的机制。这种机制称为ORM,ORM保存了对象和关系型数据库表的映射信息

Hibernate框架搭建

Hibernate3JAR包引入:


antlr-2.7.6.jar


语言转换工具,实现HQL到SQL的转换


commons-collections-3.1.jar


dom4j-1.6.1.jar


读写XML文件


hibernate3.jar


核心类库


hibernate-jpa-2.0-api-1.0.0.Final.jar


对JPA规范的支持,事物处理


javassist-3.12.0.GA.jar


分析、编辑、创建java字节码的类库


jta-1.1.jar


mysql-connector-java-5.1.12-bin.jar


数据库驱动


slf4j-api-1.6.1.jar


 

Hibernate4 jar包引入:

文件配置

Hibernate.cfg.xml


<!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>

<!-- 数据库连接配置 -->

<!—数据库类型 -->

<property
name="hibernate.connection.driver_class">com.mysql.jdbc.Driver

</property>

<!—数据库URL -->

<propertyname="hibernate.connection.url">jdbc:mysql:///hib_demo

</property>

<!—用户名 -->

<property
name="hibernate.connection.username">root

</property>

<!—用户名密码 -->

<property
name="hibernate.connection.password">root

</property>

<!—配置Hibernate数据库类型  -->

<property
name="hibernate.dialect">org.hibernate.dialect.MySQLDialect

</property>

<!—显示SQL脚本语句 -->

<property
name="hibernate.show_sql">true

</property>

<!-- 加载所有映射 -->

<mapping
resource="映射文件目录"/>

</session-factory>

</hibernate-configuration>


sf = new Configuration()

.configure()

.addClass(Employee.class)

.buildSessionFactory()//(测试时候用)会自动加载映射文件:效果等同于    <mapping
resource="映射文件目录"/>

数据库连接参数配置

例如:

sql语言配置

#hibernate.dialectorg.hibernate.dialect.MySQLDialect

#hibernate.dialectorg.hibernate.dialect.MySQLInnoDBDialect

#hibernate.dialectorg.hibernate.dialect.MySQLMyISAMDialect

自动建表

Hibernate.properties

hibernate.hbm2ddl.auto create-drop 每次在创建sessionFactory时候执行创建表;

                                                        当调用sesisonFactory的close方法的时候,删除表!

hibernate.hbm2ddl.auto create   每次都重新建表;如果表已经存在就先删除再创建

hibernate.hbm2ddl.auto update  如果表不存在就创建;表存在就不创建;

hibernate.hbm2ddl.auto validate  (生成环境时候) 执行验证: 当映射文件的内容与数据                                                   库表结构不一样的时候就报错!

 

代码自动建表和文件配置自动建表区别

文件配置自动建表在加载配置文件时候才会建表,代码自动建表启动时候就会建表。

代码自动建表:

// 创建配置管理类对象

Configuration config = new Configuration();

// 加载主配置文件

config.configure();

// 创建工具类对象

SchemaExport export =
new SchemaExport(config);

// 建表

// 第一个参数:是否在控制台打印建表语句

// 第二个参数:是否执行脚本

export.create(true,
true);

 

对象的映射 (映射文件)

类名.hbm.xml             


<?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
package="cn.itcast.a_hello"  auto-import="trueHQL查询时不用指定包名/false得指定"
>

<class
name="实体类的名字"
table="数据库表名"
catalog="数据表的名字"
>

<!-- 主键 ,映射id属性必须有一个-->

<id
name="实体类属性"
type="属性的java类型"
column="指定对应数据库表的主键"
type=“字段类型”
>

<generator
class="主键生成器策略"/>

主键生成策略:

increment  个是由Hibernate在内存中生成主键,每次增量为1,不依赖于底层的数据库,因此所有的数据库都可以使用

identity      采用数据库生成的主键,用于为long、short、int类型生成唯一标识, Oracle 不支持自增字段.

sequence   对象标识符由底层的序列生成机制产生,要求底层数据库支持序列

native         根据底层数据库的能力,从identity、sequence、hilo中选择一个,灵活性更强。

assigned  指定主键生成策略为手动指定主键的值

uuid.hex     使用一个128-bit的UUID算法生成字符串类型的标识符

uuid.string  hibernate会算出一个16位的值插入

foreign  即把别的表的主键作为当前表的主键;

</id>

<!-- 非主键,映射 -->

<property
name="实体类属性"
column="指定对应数据库表的主键"
></property>

<set name="集合属性名"
table="集合属性要映射到的表">

<key
column="指定集合表的外键字段"></key>

<element
column="address"
type="元素类型,一定要指定"></element>

</set>

<!-- list集合映射 list-index 
指定的是排序列的名称 (因为要保证list集合的有序) -->

<list name=".." table="..">

<key column=".."></key>

<list-index column=".."></list-index>

<element column=".." type="string"></element>

</list>

<!-- map集合的映射-->

<map name=".." table="..">

<key column=".."></key>

<map-key column=".." type=".." ></map-key>

<element column=".." type=".." ></element>

</map>

</class>


type   指定映射表的字段的类型,如果不指定会匹配属性的类型

java类型:    
必须写全名

hibernate类型: 
直接写类型,都是小写

<!-- 如果列名称为数据库关键字,需要用反引号或改列名。 -->

<property
name="desc"
column="`desc`"
type="java.lang.String"></property>

联合/复合主键

如果找不到合适的列作为主键,除了用id列以外,我们一般用联合主键,即多列的值作为一个主键,从而确保记录的唯一性。

<!-- 复合主键映射 -->

<composite-id name="keys">

<key-property name="userName" type="string"></key-property>

<key-property name="address" type="string"></key-property>

</composite-id>

运行流程

执行流程:

会话工厂类SessionFactory创建

Hibernate4.0以下版本创建


public
static void
main(String[] args)
throws Exception{

// 1. 加载默认的hibernate.cfg.xml的配置文件

Configuration config = new Configuration().configure();

// 2. 加载hbm文件  (Test.hbm.xml)

config.addClass(cn.itcast.hibernate.api.Test.class);

// 3. 根据配置生成表

SchemaExport schema = new SchemaExport(config);

schema.create(true,
true);

// 4. 构建SessionFactory对象

SessionFactory factory = config.buildSessionFactory();

Session session = factory.openSession();        
// 5. 建立连接

Transaction tran = session.beginTransaction();
// 6. 开启事务

Test t = new Test();

t.setName("test hibbernate");

session.save(t);

tran.commit();        // 7.
提交事务

session.close();        // 8.
关闭会话

}

Session 类的方法:

取得持久化对象的方法: get() load()

持久化对象都得保存,更新和删除:save(),update(),saveOrUpdate(),delete()

开启事务: beginTransaction().

管理Session 的方法:isOpen(),flush(), clear(), evict(),close()等

Transaction 类的方法:

commit():提交相关联的session实例

rollback():撤销事务操作

wasCommitted():检查事务是否提交

Hibernate4.0以后版本创建(安全线程)


public
class
HibernateSessionFactory

{

//指定Hibernate配置文件路径

private
static
String CONFIG_FILE_LOCATION =
"/hibernate.cfg.xml";

//创建ThreadLocal对象

private
static final
ThreadLocal<Session> sessionThreadLocal =
new ThreadLocal<Session>();

//创建Configuration对象

private
static
Configuration configuration = new Configuration();

//定义SessionFactory对象

private
static
SessionFactory sessionFactory;

//定义configFile属性并赋值

private
static
String configFile = CONFIG_FILE_LOCATION;

static

{

try

{

//读取配置文件hibernate.cfg.xml

configuration.configure();

//生成一个注册机对象

ServiceRegistry serviceRegistry=new ServiceRegistryBuilder().

applySettings(configuration.getProperties()).buildServiceRegistry();


//
生成注册机对象(hibernate5之后注册机对象如下创建)

ServiceRegistry serviceRegistry =newStandardServiceRegistryBuilder()

.configure("org/hibernate/example/hibernate.cfg.xml").build();

//使用注册机对象serviceRegistry创建sessionFactory

sessionFactory = configuration.buildSessionFactory(serviceRegistry);

}

catch (HibernateException e)

{

e.printStackTrace();

}

}

//创建无参的HibernateSessionFactory构造方法

private HibernateSessionFactory(){

}

//获得SessionFactory对象

public
static
SessionFactory getSessionFactory()

{

return sessionFactory;

}

//重建SessionFactory

public
static void
rebuildSessionFactory()

{

synchronized (sessionFactory)

{

try

{

configuration.configure(configFile);

ServiceRegistry serviceRegistry=new ServiceRegistryBuilder().

applySettings(configuration.getProperties()).buildServiceRegistry();

//使用注册机对象serviceRegistry创建sessionFactory

sessionFactory = configuration.buildSessionFactory(serviceRegistry);

}

catch (HibernateException e)

{

e.printStackTrace();

}

}

}

//获得Session对象

public
static
Session getSession()

{

//获得ThreadLocal对象管理的Session对象

Session session = (Session) sessionThreadLocal.get();

try

{

//判断Session对象是否已经存在或是否打开

if (session ==
null || !session.isOpen())

{

//如果Session对象为空或未打开,再判断sessionFactory对象是否为空

if (sessionFactory ==
null)

{

//如果sessionFactory为空,则创建SessionFactory

rebuildSessionFactory();

}

//如果sessionFactory不为空,则打开Session

session = (sessionFactory !=
null) ? sessionFactory.openSession() :
null;

sessionThreadLocal.set(session);

}

}

catch (HibernateException e)

{

e.printStackTrace();

}

return session;

}

//关闭Session对象

public
static void
closeSession()

{

Session session = (Session) sessionThreadLocal.get();

sessionThreadLocal.set(null);

try

{

if (session !=
null && session.isOpen())

{

session.close();

}

}

catch (HibernateException e)

{

e.printStackTrace();

}

}

//configFile属性的set方法

public
static void
setConfigFile(String configFile)

{

HibernateSessionFactory.configFile = configFile;

sessionFactory = null;

}

//configuration属性的get方法

public
static
Configuration getConfiguration()

{

return configuration;

}

}


Session创建原理

由于SessionFactory是线程安全的,因而同一个SessionFactory实例可以被多个线程共

享,即多个并发线程可以同时访问一个SessionFactory并获得Session实例。但由于Sessior

不是线程安全的,如果多个并发线程同时操作同一个Session对象,就可能出现一个线程在

进行数据库操作,而另一个线程将Session对象关闭的情况,从而出现异常。如何才能保证

线程安全呢?这就要求SessionFactory能够针对不同的线程创建不同的Session对象,即需

要对Session进行有效的管理,Hibernate中使用ThreadLocal对象来维护和管理Session实例

ThreadLocal是指线程局部变量(Tread Local Variable),线程局部变量高效地为每个使用

它的线程提供单独的线程局部变量的副本。每个线程只能修改与自己相联系的副本,而不

会影响到其他进程的副本。为了实现为每个线程维护一个变量的副本, ThreadLocal类提供

了一个Map结构,其key值用来保存线程的ID, value值用来保存一个Session实例的副本。

这样,多个线程并发操作时,是在与自己绑定的Session实例副本上进行的,从而避免多个

线程在同一个Session实例上操作时可能导致的数据异常。

在 HibemateSessionFactory 类的 getSession()方法中,首先调用 ThreadLocal 类的 get()方法获得当前线程的Session对象,然后判断是否已存在该Session对象。如果该对象不存在或者该对象未打幵,再判断SessionFactory对象是否为空,如果SessionFactory对象不存在,先调用rebuildSessionFactory方法创建SessionFactory。如果存在则调用sessionFactory的openSession()方法创建Sessionsession对象。创建完成后还要调用threadLocal的set()方法为该线程保存session对象

持久化对象的状态

瞬时对象(Transient Objects)    

使用new操作符初始化的对象不是立刻就持久化的,他们的状态是瞬时的。

(1) 不处于Session的缓存中,也可以说,不被任何一个Session实例关联。

(2) 在数据库中没有对应的记录。

持久化对象(Persist Objects)

持久实例是任何具有数据库标识的实例。它有持久化管理器Session统一管理,持久实例是在事务中进行操作的———他们的状态在事务结束时同数据库进行同步。

(1) 位于一个Session实例的缓存中,也可以说,持久化对象总是被一个Session实例关联。

(2) 持久化对象和数据库中的相关记录对应。

(3) Session在清理缓存时,会根据持久化对象的属性变化,来同步更新数据库。

离线对象(Detached Objects)

     Session关闭之后,持久化对象就变为离线对象。离线表示这个对象不能再与数据库保持同步,他们不再受Hibernate管理。

(1) 不再位于Session的缓存中,也可以说,游离对象不被Session关联。

(2) 游离对象是由持久化对象转变过来的,因此在数据库中可能还存在与它对应的记录(前提条件是没有其他程序删除了这条记录)。

能够使hibernate的对象由瞬时态或托管态转变为持久态:

?      save()方法:将对象由瞬时态转变为持久态。

?      load()或get()方法:获得的对象的状态处于持久态。

?      find()方法:获得的List集合中的对象状态处于持久态。

?      update()、saveOrUpdate()和lock()方法:可将托管态对象转变为持久态。

能够使Hibernate的对象由持久态转变为托管态的方法:

?      close()方法:调用后,Session的缓存会被清空,缓存中所有持久态对象状态都转变为托管态。处于托管状态的对象称为游离对象,当游离对象不再被引用时,将被Java虚拟机垃圾回收机制清除。

?      evict()方法:可将Session缓存中一个指定的持久态对象删除,使其转变为托管态对象。当缓存中保存了大量处于持久态的对象时,为了节省内存空间,可以调用evict()方法删除一些持久态对象。

知识点

A.     Hibernate的运行过程如下:

1、应用程序先调用Configuration类,该类读取Hibernate配置文件及映射文件中的信息,

2、并用这些信息生成一个SessionFactory对象,

3、然后从SessionFactory对象生成一个Session对象,

4、并用Session对象生成Transaction对象;

A、可通过Session对象的get(),load(),save(),update(),delete()

和saveOrUpdate()等方法对PO进行加载、保存、更新、删除、

等操作;

B、在查询的情况下,可通过Session对象生成一个Query对象,然后

利用Query对象执行查询操作;如果没有异常,Transaction对象将

提交这些操作到数据库中

B.      session的get()和load()有什么区别?

get()如果没有找到持久化类返回null,有可能导致空指针异常。

load()如果没有找到持久化类直接抛出异常。

get()是直接加载数据,load()是延迟加载,当使用被加载数据的时候才发送SQL。

简而言之:Hibernate对于load()认为数据库一定存在,因此可以放心的使用代理进行延迟加载,如果使用中发现了问题,那么只能抛出异常。而对于get方法一定要获取真实的数据,否则返回null。

DataType dataType1 = (DataType) session.load(DataType.class,new Long(1));

DataType dataType2 = (DataType) session.load(DataType.class,new Long(1));

System.out.println(dataType1);   // 延迟加载,需要使用才发送SQL语句

System.out.println(dataType2);   // 从一级缓存中获取持久化对象

System.out.println(dataType1 == dataType2);

session.getTransaction().commit();

C.     lazy 值

true   使用懒加载

false   关闭懒加载

extra   (在集合数据懒加载时候提升效率)

在真正使用数据的时候才向数据库发送查询的sql;

如果调用集合的size()/isEmpty()方法,只是统计,不真正查询数据!

D.    Query对象在获取表的所有的数据的时候,使用list()和 iterator()有什么  

区别?

ü  编写代码的方式不同list()和iterator()

ü  底层发送的SQL语句不同

ü  list()直接一次性获取到所有持久化类的对象,iterator()先获取的是所有的数据的id值。当真正的遍历使用数据的时候再发送select语句。因此该方法一定要处于session会话中。

ü  list发送的查询语句只有1条。Iterator发送多条查询语句,因此iterator的效率低下。懒汉式(iterator)   饿汉式(list)

Hibernate  Api

|-- Configuration       配置管理类对象

config.configure();    加载主配置文件的方法(hibernate.cfg.xml)

默认加载src/hibernate.cfg.xml

config.configure(“cn/config/hibernate.cfg.xml”);加载指定路径下指定名称的主配                                                                                      置文件

config.buildSessionFactory();      创建session的工厂对象

|-- SessionFactory     session的工厂(或者说代表了这个hibernate.cfg.xml配置文件)

sf.openSession();   创建一个sesison对象

sf.getCurrentSession();  创建session或取出session对象

|--Session      session对象维护了一个连接(Connection), 代表了与数据库连接的会话。Hibernate最重要的对象: 只用使用hibernate与数据库操作,都用到这个对象

session.beginTransaction(); 开启一个事务; hibernate要求所有的与数据库的操作必须有事务的环境,否则报错!

更新:

session.save(obj);   保存一个对象

session.update(emp);  更新一个对象

session.saveOrUpdate(emp); 保存或者更新的方法:

à没有设置主键,执行保存;

à有设置主键,执行更新操作;

à如果设置主键不存在报错!


使用Session对象的save方法,虽然可以完成对象的持久化操作,但有时候会出现问题,如一个对象己经被持久化了,此时如果再次调用saveO方法,将会出现异常。

使用saveOrUpdateO方法可以很好地解决这一问题,因为它会自动判断该对象是否已经持久化,如果已经持久化,将执行更新操作,否则执行添加操作。如果标识(主键)的生成策略是自增型的,则使用Session对象的save()和saveOrUpdate〇方法是完全相同的。

提示: Session的save方法必须在事务环境中完成,并需使用commit方法提交事务,记录才能成功添加到数据表中。

主键查询:

session.get(Employee.class, 1);    主键查询

session.load(Employee.class, 1);   主键查询 (支持懒加载)

时间: 2024-10-10 10:17:10

Hibernate技术(一)--Hibernate初步的相关文章

Spring整合ORM技术 -- 集成Hibernate

1.Spring整合ORM方案的好处: 方便基础设施的搭建.不同的ORM技术都有一套自己的方案以初始化框架.搭建基础设施等.在搭建基础设施中,数据源是不可或缺的资源,不同的ORM框架的实现方式各不相同.Spring针对不同的ORM框架,采用相同的方式配置数据源,并为不同的ORM框架提供相同的FactoryBean,用以初始化ORM框架的基础设施,可以把它们当成普通Bean对待. 异常封装.Spring能够转化各种ORM框架抛出的异常,将ORM框架专有的或检查型异常转换为SpringDAO异常体系

hibernate中缓存的初步认识

为什么实用缓存 目的是为了减少应用程序对物理数据源访问的次数,从而提高应用程序的运行性能. hibernate如果使用了缓存,在查询数据时,首先到缓存中去查找,如果找到就直接使用,找不到的时候就会从物理数据源中检索,所以,把频繁使用的数据加载到缓存区后,就可以大大减少应用程序对物理数据源的访问,使得程序的运行性能明显的提升. 查询时使用缓存的实现过程为:首先查询一级缓存中是否具有需要的数据,如果没有,查询二级缓存,如果二级缓存中也没有,此时再执行查询数据库的工作.要注意的是:此3种方式的查询速度

Java基础103 Hibernate技术连接MySQL数据和Oracle数据库的配置方法

1.Hibernate技术连接MySQL数据 User.hbm.xml 配置文件 <?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"> <hibernat

Hibernate技术文档

hibernate数据持久化组件 对象持久化,把数据保存在永久的存储介质中(数据库) OR/M(object relationmapping)对象关系映射. POJO类,就是标准的Java Bean. Hibernate就是一个可以自动的根据xml完成对象关系映射,并持久化到数据库的开源组件. Hibernate的底层也是有JDBC实现的. hibernate是通过xml文件的配置,对数据库的底层的方言,以及数据库连接所需的信息,以及连接数据库的驱动.hibernate的系统配置文件的名字一般叫

【hibernate进阶】hibernate基本映射

        对象-关系映射(Object/Relation Mapping,简称ORM),是随着面向对象的软件开发方法发展而产生的,是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术,本质上就是将数据从一种形式转换到另外一种形式.hibernate作为一个ORM框架的代表,在实现ORM中,就是靠hibernate的基本映射来实现的. 常用的hibernate的几种映射:基本映射和关系映射.这篇博客主要介绍hibernate的基本映射. Hibernate在实现ORM功能的时候主要用

hibernate.properties和hibernate.cfg.xml

hibernate.properties和hibernate.cfg.xml 博客分类: 框架技术 HibernateXMLSQLOracleJDBC hibernate配置文件可以有两种方式:官方推荐的XML配置文件和属性配置文件.我们大都采用XML方式的配置,因为结构良好,配置灵活,可读性强.而且可以在XML中直接配置映射文件而属性文件则不行.但是我们可能忽略的一个问题是:hibernate首先查找的配置文件却是属性配置文件hibernate.properties.     看看下面这张图,

Hibernate 入门 04 - Hibernate中Java对象的三种状态

目录:(后续不断更新...) Hibernate 入门 01 - 框架技术 (介绍Hibernate框架的发展由来) Hibernate 入门 02 - Hibernate介绍及其环境搭建 Hibernate 入门 03 - 使用Hibernate完成持久化操作 Hibernate 入门 04 - Hibernate中Java对象的三种状态 ▁▃▅ Hibernate中Java对象的三种状态▅▃▁ 1. Java对象的三种状态 当应用通过调用Hibernate API与框架发生交互时,需要从持久

Hibernate 入门 02 - Hibernate介绍及其环境搭建

昨晚喝多了,下午刚清醒,继续搞Hibernate.走起. 觉得还行的话,记得点赞哈,给我这个渣渣点学习的动力.有错误的话也请指出,省的我在错误上走了不归路.呵呵. 目录: 数据持久化概念 Hiberante框架及ORM2.1. Hibernate框架2.2. 什么是ORM2.3. Hibernate框架的优缺点及其适用场合 2.4.1 Hibernate框架的优点 2.4.2 Hibernate框架的缺点2.4. Hibernate环境搭建2.5. 技能训练2.6. 练习 1.数据持久化概念 数

org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not

遇到这个问题之前,我去百度和谷歌去搜索了一下,发现各种说法,但是针对我的项目而言,也就是公司的项目而言,这个问题的根源并非是网上所说的那样. 最后是通过自己的想法做测试得到了解决. 1.首先说说我的配置吧!我的配置是通过spring自带的注解来实现 声明式事物管理的.如果我们没去了解spring的声明式事物管理的话,或许我们是得不出什么结论的. 如果你配置过声明式事物管理,你就知道spring是怎么帮你管理的. 2.spring声明式事物管理是在service层管理的,关于到sessionFac