Hibernate基础知识

一.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>永远不负责维护关系.
  
  
 
 
  
  
 
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值