现在的位置: 首页 > 综合 > 正文

Hibernate基础知识

2013年05月18日 ⁄ 综合 ⁄ 共 8207字 ⁄ 字号 评论关闭

一.HibernateSession的缓存

要使得一个pojo对象一直处在生命周期中,就必须保证至少有一个变量引用它,或将它放在一个java 的集合中,即集合中存放的就是这个对象的引用。Session接口中的实现类就是一系列的java集合,这就构成了Session的缓存,所以Session可以保存pojo对象。

Session缓存的作用:

1.减少访问数据库的频率

2.保证缓存中的对象与数据库中的相关纪录保持同步。Session并不会立即执行相关的SQL语句,它能够把几条相关的SQL语句合并为一条SQL语句,以便减少访问数据库的次数。

Session清理缓存的时机:

默然情况下,当显示调用了Sessionflush()方法的时候;当调用Transactioncommit()方法的时候会先清理缓存,然后再向数据库提交事务;当调用查询方法的时候,如果缓存中没有要查找的对象,会清理缓存,然后去数据库中查找,保证查找的对象是和数据库同步的对象。

可以通过SessionsetFlushMode设置清理模式,FlushMode.AUTO; FlushMode.ALWAYS; FlushMode.COMMIT; FlushMode.MANUAL;

二.Hibernatepojo的三种状态以及转换关系:

临时状态(transient):刚刚new出来的,还没有被持久化,不处在Session的缓冲区中。(临时对象)

持久化状态(persistent):已经被持久化,加入到Session的缓存中,正在被Session所管理。(持久化对象)

游离状态(detached):已经被持久化,但不处于Session的缓存中。(游离对象)


load()方法:返回的是一个pojo类的子类对象(代理对象),该子类是由cglib.jar产生的。load()会使用延迟加载。(延迟加载:只有真正用到类的属性的时候才去数据库中去加载对象。)所以load()方法不会返回一个null,要真正得到一个对象应该调用get()方法。

get()方法:不会产生动态的子类,他会先在缓存里面找该对象,如果没有则马上到数据库中找,然后返回一个pojo对象,如果没有找到就返回null,所以get()没有延迟加载。

save()方法:用来持久化一个临时对象。

//新增

Person person = new Person();

person.setName("new person");

person.setAge(20);

session.save(person);

hibernate将执行insert语句

update()方法:使一个游离对象加入Session缓存中,使它转变为一个持久化对象。当清理缓存的时候执行一条update语句。

//修改

Person person = (Person)session.load(Person.class,2);

person.setName("new test");

hibernate将先装载Person然后执行update语句,如果再次运行则不会再执行update语句

Person person = (Person)session.load(Person.class,2);

person.setName("new test1");

person.setName("new test2");

person.setName("new test1");

只会执行一次update语句

当执行session.flush()的时候执行更新语句,如果不显示执行flush语句,在执行commit的时候会调用session.flush()方法更新语句才能真正被执行。

当开始一个新的session

Person person = new Person();

session.save(person);这个时候session会先把该person对象存入数据库(执行insert语句)并将会管理这个Person对象。如果一个对象曾经被一个session管理过,但是该session已经被关闭,重新开一个session管理该对象时要更新该对象就要执行session.update()方法.

session = sessionFactory.openSession();

person.setName("ttt");

session.update(person);

saveOrUpdate()方法:如果传入对象是一个临时对象就调用save()方法;如果传入对象是一个游离对象就调用update()方法;如果传入对象是一个持久化对象,就直接返回。该方法是通过判断id来决定是save还是用update

session.contains(person);用于判断session中是否有一个Person对象.

session = sessionFactory.openSession();

person.setName("ttt");

session.saveOrUpdate(person);

delete()方法:从数据库中删除与pojo对象对应的纪录。如果要删除的是一个持久化对象,Session就将执行一条delete语句;如果传入的是一个游离对象,则先使游离对象被Session关联,使它变成一个持久化对象,然后将执行一条delete语句。注意:只有在清理缓存或调用Sessionclose方法的时候,delete语句才能真正被执行。

//删除

Person person = (Person)session.load(Person.class,2);

session.delete(person);

hibernate将先装载Person然后执行delete语句

三.主键生成方式

sequence:在Oracle,DB2,PostgreSQL, SAP DB, McKoi中使用序列(sequence)。返回的标识符是long, short或者 int类型的。

执行sql语句:create sequence my_key;

<id name="id">

<generator class="sequence">

<param name="sequence">my_key</param>

</generator>

</id>

increment:用于为long, short或者int类型生成 唯一标识。只有在没有其他进程往同一张表中插入数据时才能使用。 在集群下不要使用。

<id name="id">

<generator class="increment"></generator>

</id>

identity:由底层数据库来负责生成标示符,它要求底层数据库把主键定义为自动增长字段类型。如:在mysql中应把主键定义为:auto_increment类型;在SQL Server中应把主键定义为identity类型。

<id name="id">

<generator class=" identity "/>

</id>

native:根据底层数据库的能力选择identity, sequence 或者hilo中的一个。适合跨数据库平台开发。

<id name="id">

<generator class=" native "/>

</id>

Hilo:使用一个高/低位算法高效的生成long, short 或者 int类型的标识符。给定一个表和字段(默认分别是 hibernate_unique_key next_hi)作为高位值的来源。 /低位算法生成的标识符只在一个特定的数据库中是唯一的。

执行sql语句:

create table hi_value (

next_value number(6,0)

);

insert into hi_value values(0);

<id name="id">

<generator class=" hilo">

<param name="table">hi_value</param>

<param name="column">next_value</param>

<param name="max_lo">100</param>

</generator>

</id>

uuid:用一个128-bitUUID算法生成字符串类型的标识符 这在一个网络中是唯一的(使用了IP地址)。UUID被编码为一个3216进制数字的字符串。

package net.xiaopi.pojo;

import java.io.Serializable;

public class UUIDObject implements Serializable {

private static final long serialVersionUID = -7800543060715584111L;

private String id;

public String getId() {

return id;

}

public void setId (String id) {

this.id = id;

}

}

执行sql语句:

create table hi_UUIDObject (

id char(32) primary key

);

<class name="UUIDObject">

<id name="id">

<generator class="uuid"></generator>

</id>

</class>

l 跨平台

l UUID

l Hilo

l 依赖数据库

l Squence

l Identity

l Native

l 其他方式

l Assignedincrement

l foreign

四.关联关系映射

1.单向many-to-one关联

<class name="Person">

 <id name="id" column="personId">

 <generator class="native"/>

 </id>

 <many-to-one name="address" 

column="addressId"

 not-null="true"/>

</class>

<class name="Address">

 <id name="id" column="addressId">

 <generator class="native"/>

 </id>

</class>

Sql语句:

 create table Person ( personId bigint not null primary key, addressId bigint not null )

 create table Address ( addressId bigint not null primary key )

 

 2.双向many-to-one/one-to-many关联

 <class name="Person">

 <id name="id" column="personId">

 <generator class="native"/>

 </id>

 <many-to-one name="address" 

column="addressId"

 not-null="true"/>

</class>

<class name="Address">

 <id name="id" column="addressId">

 <generator class="native"/>

 </id>

 <set name="people" inverse="true">

 <key column="addressId"/>

 <one-to-many class="Person"/>

 </set>

</class>

Sql语句:

 create table Person ( personId bigint not null primary key, addressId bigint not null )

 create table Address ( addressId bigint not null primary key )

 加载"主"(即有从的主键,如Person为主,Address为从)不会立即加载"从",而是延迟加载

 建立关联最好建立双向关联.

 注意建立pojo的时候set属性应该马上new一个集合对象.

 inverse:是否放弃维护关系.没有放弃维护关系,会执行一条update语句

比如:address 中的inverse=true;

cascade=All:看管理的集合对象是否持久化,没有持久化就持久化.

级联是级联持久化.没有负责维护关系.

cascade="save-update":级联持久化状态

 如果"主"被持久化,他所管理的集合里面的"从"也会被持久化.

cascade="all",对父对象进行save/update/delete操作就会导致子对象也进行save/update/delete操作

delete-orphan:删除“孤儿”模式,此时不被任何一个父对象引用的子对象会被删除.

cascade="all-delete-orphan"

级联(cascade)通常在 <one-to-one><one-to-many>关系中比较有用

3.基于外键关联的单向one-to-many关联

<class name="Person">

 <id name="id" column="personId">

 <generator class="native"/>

 </id>

 <set name="addresses">

 <key column="personId" 

not-null="true"/>

 <one-to-many class="Address"/>

 </set>

</class>

<class name="Address">

 <id name="id" column="addressId">

 <generator class="native"/>

 </id>

</class>

 SQL语句:

create table Person ( personId bigint not null primary key )

create table Address ( addressId bigint not null primary key, personId bigint not null )

 基于外键关联的一对多关联是一种很少见的情况,并不推荐使用,对于这种关联关系最好使用连接表。

 4单向many-to-many关联

 <class name="Person">

 <id name="id" column="personId">

 <generator class="native"/>

 </id>

 <set name="addresses" table="PersonAddress">

 <key column="personId"/>

 <many-to-many column="addressId"

 class="Address"/>

 </set>

</class>

<class name="Address">

 <id name="id" column="addressId">

 <generator class="native"/>

 </id>

</class>

SQL语句:

create table Person ( personId bigint not null primary key )

create table PersonAddress ( personId bigint not null, addressId bigint not null, primary key (personId, addressId) )

create table Address ( addressId bigint not null primary key )

 

 5.双向many-to-many关联

<class name="Person">

 <id name="id" column="personId">

 <generator class="native"/>

 </id>

 <set name="addresses" table="PersonAddress">

 <key column="personId"/>

 <many-to-many column="addressId"

 class="Address"/>

 </set>

</class>

<class name="Address">

 <id name="id" column="addressId">

 <generator class="native"/>

 </id>

 <set name="people" inverse="true" table="PersonAddress">

 <key column="addressId"/>

 <many-to-many column="personId"

 class="Person"/>

 </set>

</class>

SQL语句:

create table Person ( personId bigint not null primary key )

create table PersonAddress ( personId bigint not null, addressId bigint not null, primary key (personId, addressId) )

create table Address ( addressId bigint not null primary key )

 

 作新增操作时,必须有一方放弃维护关系:inverse="true" ,否则数据库中会多增加一条相同的纪录. cascade="save-update"

 6.单向one-to-one关联

 a.基于外键关联的双向一对一关联

<class name="Person">

 <id name="id" column="personId">

 <generator class="native"/>

 </id>

 <many-to-one name="address" 

column="addressId" 

unique="true"

 not-null="true"/>

</class>

<class name="Address">

 <id name="id" column="addressId">

 <generator class="native"/>

 </id>

 <one-to-one name="person" 

property-ref="address"/>

</class>

SQL语句:

create table Person ( personId bigint not null primary key, addressId bigint not null unique )

create table Address ( addressId bigint not null primary key )

 外键一对一:

 主:

 <one-to-one name="..." property-ref="">

 

 从:

 <many-to-one name="" column="" unique="true" not-null="true"> 

 加载“主”会立即加载”从“,没有使用延迟加载

 加载“从”不会立即加载“主”,使用延迟加载

 加载的时候,总是加载主 

 

 可以更新,

 

 删除时

 在“主”写cascade="delete",去将从级联删除,

 但在实际的工程中,有没有delete 得从业务角度考虑

 

 b.基于主键关联的一对一关联,要使用特定的id生成器。

<class name="Person">

 <id name="id" column="personId">

 <generator class="native"/>

 </id>

 <one-to-one name="address"/>

</class>

<class name="Address">

 <id name="id" column="personId">

 <generator class="foreign">

 <param name="property">person</param>

 </generator>

 </id>

 <one-to-one name="person" 

constrained="true"/>

</class>

SQL语句:

create table Person ( personId bigint not null primary key )

create table Address ( personId bigint not null primary key )

 

 主键一对一:

 加载"主"会立即加载"从",没有使用延迟加载.

 加载"从"不会立即加载"主",使用延迟加载.

 加载的时候,总是加载主就OK了.

 增加时,先增加"主"还时先增加"从"都没有关系.

 如果单增加"从",会自动增加"主".

 如果单增加"主",不会自动增加"从",除非有cascade="save-update".

 这样的特性都是因为主键生成方式的原因.

 <one-to-one>永远不负责维护关系.

抱歉!评论已关闭.