一、简介

Hibernate是一个开放源代码的对象关系映射框架,是连接java应用程序和数据库的中间件,对JDBC api 进行了轻量级的对象封装,负责Java对象的持久化,在分层软件构架中属于持久层,封装了所有数据访问细节,可以用对象编程思维解决数据库操纵问题,使业务逻辑层可以专注于业务逻辑的实现,是一种ORM(Object Relational Mapping对象-关系映射)工具,能够建立面向对象的域模型和关系模型映射。


hibernate官网下载地址:

http://hibernate.org/orm/


各类数据库驱动下载地址:

链接:http://pan.baidu.com/s/1pL5sX6r 密码:5jx8


二、hibernate.cfg.xml配置文件

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC           
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"           
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<!-- dtd可以在Hibernate3.1.3软件包中的src\org\hibernate目录中找到此文件-->

<!--声明Hibernate配置文件的开始-->       
<hibernate-configuration>  

<!--SessionFactory是Hibernate中的一个类,这个类主要负责保存HIbernate的配置信息,以及对Session的操作-->       
<session-factory>

<!--配置数据库的驱动程序-->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>      

<!--设置数据库的连接-->            
<property name="hibernate.connection.url">jdbc:mysql://localhost/hibernate </property>   

<!--连接数据库是用户名-->    
<property name="hibernate.connection.username">root</property>      

<!--连接数据库是密码--> 
<property name="hibernate.connection.password">123456</property>                

<!--数据库连接池的大小-->
<property name="hibernate.connection.pool.size">20</property>              

<!--是否在后台显示Hibernate用到的SQL语句,开发时设置为true,项目部署后可以设置为false,提高运行效率-->
<property name="hibernate.show_sql">true</property>        

<!--jdbc.fetch_size是指Hibernate每次从数据库中取出并放到JDBC的Statement中的记录条数。
Fetch Size设的越大,读数据库的次数越少,速度越快,Fetch Size越小,读数据库的次数越多,速度越慢-->       
<property name="jdbc.fetch_size">50</property>        

<!--jdbc.batch_size是指Hibernate批量插入,删除和更新时每次操作的记录数。
Batch Size越大,批量操作的向数据库发送Sql的次数越少,速度就越快,同样耗用内存就越大-->
<property name="jdbc.batch_size">23</property>

<!--jdbc.use_scrollable_resultset是否允许Hibernate用JDBC的可滚动的结果集。
对分页的结果集。对分页时的设置非常有帮助-->
<property name="jdbc.use_scrollable_resultset">false </property>   

<!--connection.useUnicode连接数据库时是否使用Unicode编码-->
<property name="Connection.useUnicode">true</property>      

<!--connection.characterEncoding连接数据库时数据的传输字符集编码方式-->   
<property name="connection.characterEncoding">UTF-8</property>                  

<!--hibernate.dialect 只是Hibernate使用的数据库方言,不同数据库用不同方言。-->      
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>

<!--指定映射文件"com.ziry.UserInfo"-->                 
<mapping resource="com/ziry/UserInfo.hbm.xml" />
<mapping class="com.ziry.UserInfoe"/>
</session-factory>   

</hibernate-configuration>


三、hibernate映射文件

<?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="指定一个包前缀" 
auto-import="指定在查询语言中使用非全限定的类名,默认为true,如果项目中有两个同名的持久化类,最好配置为false"
default-cascade="默认的级联风格,默认为none"
default-lazy="指定了未明确注明lazy属性的Java属性和集合类,默认为true"
 -->
<hibernate-mapping>

<!-- 
<class>:使用class元素定义一个持久化类。
name="持久化类(或者接口)的Java全限定名"
table="对应数据库表名"
mutable="默认为true,设置为false时则不可以被应用程序更新或删除"
dynamic-insert="默认为false,指定用于INSERT的SQL将会在执行时动态生成,并且只包含那些非空值字段"
dynamic-update="默认为false,指定用于UPDATE的SQL将会在运行时动态生成,并且只更新那些改变过的字段"
select-before-update="默认为false,在修改之前先做一次查询,与用户的值进行对比,有变化都会真正更新"
optimistic-lock="默认为version(检查version/timestamp字段),取值:all(检查全部字段)、dirty(只检查修改过的字段)、 none(不使用乐观锁定),此参数主要用来处理并发,每条值都有固定且唯一的版本,版本为最新时才能执行操作"
 -->
<class 
	name="cn.javass.user.vo.UserModel" 
	table="tbl_user" 
	dynamic-insert="true" 
	dynamic-update="true" 
	optimistic-lock="version"
>
    	
<!-- 
<id>:定义了该属性到数据库表主键字段的映射。
name="userId":标识属性的名字;
column="userId":表主键字段的名字,如果不填写与name一样;
 -->
<id name="userId">
  <!-- generator:指定主键由什么生成,推荐使用uuid,assigned指用户手工填入。-->
  <generator class="uuid"/>
</id>
	
<!-- 
<version/>:使用版本控制来处理并发,要开启optimistic-lock="version"和dynamic-update="true"。
name="version":持久化类的属性名,column="version":指定持有版本号的字段名;
-->
<version name="version" column="version"/>
	
<!-- 
       <property>:为类定义一个持久化的javaBean风格的属性。
	name(对应的java类的属性名称)、
	column(对应的表中的字段不填和name一样)、
	type(属性的类型,java.lang.String)、
	not-null(设置该属性是否为空,为true时表示非空,默认为false)、
	length(字段的长度限制)
	update:表明用于UPDATE的SQL语句中是否包含这个被映射的字段,默认为true
	insert:表明用于INSERT的SQL语句中是否包含这个被映射是否包含这个被映射的字段,默认为true
	lazy:指定实例变量第一次被访问时,这个属性是否延迟抓取,默认为false
	formula:可用一个SQL表达式定义了这个属性的值
	unique:使用DDL为该字段添加唯一的约束,此外,这也可以用做property-ref的目标属性
	optimistic-lock:指定这个属性在进行更新时是否需要获得乐观锁定(换句话说,它决定这个属性发生脏数据时版本version的值是否增长)
	access:用来让你控制Hibernate如何在运行时访问属性。默认情况下,Hibernate会使用属性的get/set方法对。如果你指明access="field",则Hibernate会忽略get/set方法对,直接使用反射来访问成员变量。

 -->
<property 
    name="accessname" 
    column="accessName" 
    type="java.lang.String" 
    not-null="true" />

<!-- 
组件映射:把多个属性打包在一起当一个属性使用,用来把类的粒度变小。
数据库同一张表分不通java类对象可用此组件映射
<component name="userDetail" class="UserDetail" lazy="true">
 <property name="name1"></property>
 <property name="name2"></property>
</component>
-->

<!-- 
<join>:一个对象映射多个表,该元素必须放在所有<property>之后。
<join table="tbl_test:子表名">
<key column="uuid:子表主键"></key>
<property name="name1:对象属性" column="name:子表字段"></property>
</join>
-->
</class>
</hibernate-mapping>

注:

generator的class类型:

1) assigned:

主键由外部程序负责生成,无需Hibernate参与。

2) hilo:

通过hi/lo 算法实现的主键生成机制,需要额外的数据库表保存主键生成历史状态。

3) seqhilo:

与hilo 类似,通过hi/lo 算法实现的主键生成机制,只是主键历史

状态保存在Sequence中,适用于支持Sequence的数据库,如Oracle。

4) increment:

主键按数值顺序递增。此方式的实现机制为在当前应用实例中维持

一个变量,以保存着当前的最大值,之后每次需要生成主键的时候

将此值加1作为主键。

这种方式可能产生的问题是:如果当前有多个实例访问同一个数据

库,那么由于各个实例各自维护主键状态,不同实例可能生成同样

的主键,从而造成主键重复异常。因此,如果同一数据库有多个实

例访问,此方式必须避免使用。

5) identity :

采用数据库提供的主键生成机制。

如DB2、SQL Server、MySQL中的主键生成机制。

6) sequence

采用数据库提供的sequence机制生成主键。

如Oralce 中的Sequence。

7) native

由Hibernate根据底层数据库自行判断采用identity、hilo、sequence

其中一种作为主键生成方式。

8) uuid.hex

由Hibernate基于128 位唯一值产生算法生成16 进制数值(编码后

以长度32 的字符串表示)作为主键。

9) uuid.string

与uuid.hex 类似,只是生成的主键未进行编码(长度16)。在某些

数据库中可能出现问题(如PostgreSQL)。

10) foreign

使用外部表的字段作为主键。

一般而言,利用uuid.hex方式生成主键将提供最好的性能和数据库平台适

应性。


四、hibernate常用对象

1. Configuration 对象:

负责管理Hibernate的配置信息,这些配置信息都是从配置文件hibernate.cfg.xml或者Hibernate.properties读取的,当然也可以自定义文件名称,只要在实例化Configuration的时候指定具体的路径就可以了;

//加载classpath中的hibernate.cfg.xml
Configuration config = new Configuration().configure();
//加载classpath中的指定名称.cfg.xml
Configuration config = new Configuration().configure("指定名称.cfg.xml");
//加载实体类BranchForm的属性
Configuration config = new Configuration().addClass(BranchForm.class);


2. SessionFactory 对象:

Configuration的实例会根据当前的配置信息,构造SessionFactory实例。SessionFactory是线程安全的,一般情况下一个应用中一个数据库共享一个SessionFactory实例

//构建SessionFactory要放在静态代码块中,因为它只在该类被加载时执行一次。
SessionFactory sessionFactory = config.buildSessionFactory();


3. Session 对象:

一般的持久化方法(CRUD)都是通过Session来调用的,Session是非线程安全的。Session的创建与关闭 :Session是一个轻量级对象,通常将每个Session实例和一个数据库事务绑定,也就是每执行一个数据库事务,都应该先创建一个新的Session实例,在使用Session后,还需要关闭Session。

//创建
Session session=sessionFactory.openSession();
//关闭
session.close();


4. Transaction 对象:

事务代表一个工作单元与数据库和大部分RDBMS支持事务功能。在Hibernate事务是由一个基本的事务管理器和事务(从JDBC或JTA)来处理。

这是一个可选的对象和Hibernate应用程序可以选择不使用这个接口,而不是在他们自己的应用程序代码管理事务。

Session sess = factory.openSession();
Transaction tx;
try {
	//开始事务
    tx = sess.beginTransaction();
    ...省略过程
    //事务提交
    tx.commit();
}catch (Exception e) {
	//事务回滚
    if (tx!=null) tx.rollback();
    throw e;
}finally {
    sess.close();
}


5. Query 对象:

查询对象使用SQL或Hibernate查询语言(HQL)字符串从数据库中检索数据并创建对象。

通过SessionFactory获得了session对象后,除了可以通过get(类名.class, id)方法得到相应的对象,还可以通过获得Query对象来取得需要的对象

查询语句同sql查询语句很想象,只是将表名换作类名,字段名换作属性名,如果查询需要条件可以使用占位符来替换对应的属性名,也可以使用:变量名来作为占位符。

Query query = session.createQuery("查询语句如from UserBean");
List list = query.list();//得到一个集合
query.uniqueResult();//得到一个单个的对象
分页查询:
query.setFirstResult(位置如0);//表示从哪个位置开始查询,返回query对象
query.setMaxResult(记录条数);//表示当页共几条记录,返回一个集合
session.createQuery("select count(*) from 类名").uniqueResult();//得到记录总数


6. Criteria 对象:

Criteria 是一个完全面向对象,可扩展的条件查询API,通过它完全不需要考虑数据库底层如何实现、SQL语句如何编写,是Hibernate框架的核心查询对象。


示例:

public static void main(String[] args) {
//实例化Configuration     
Configuration conf = new Configuration().configure();    
//实例化SessionFactory     
SessionFactory sf = conf.buildSessionFactory();    
//实例化Session     
Session sess = sf.openSession();    
//开始事务     
Transaction tx = sess.beginTransaction();  
  
List cats = sess.createCriteria(Cat.class) 
.add( Restrictions.like("name", "Fritz%") ) 
.add( Restrictions.between("weight", minWeight, maxWeight) ) 
.list();   

//提交事务     
tx.commit();    
//关闭Session     
sess.close();
}


五、hibernate对象3种状态

1) 临时状态/瞬时状态/临界状态(transient)

通过new新创建的对象就处于临时状态,

该对象也称为临时对象。

临时对象特点: 

  * 和Session没有关联(不受其管理)

  * 数据库中没有对应的记录


2) 持久化状态(persistent)

对象处于Session的缓存中和其关联

的状态,处于该状态的对象也称为持久化对象。

持久化对象特点:

  * 和Session关联(受其管理)

  * 数据库中有对应的记录


3) 游离状态(detached)(脱管状态)

数据库中有对应的记录但是没有处于

Session缓存中(和Session没有关联)的状态。

处于该状态的对象也称为游离对象。

游离对象特点: 

  * 数据库中有对应记录

  * 没有和Session关联(不受其管理)



六、session接口API 

方法摘要

Transaction

beginTransaction () 
开始一个工作单位,并返回值相关的事务对象。

Session.LockRequest

buildLockRequest ( LockOptions lockOptions) 
建立一个LockRequest指定LockMode,悲观锁超时和锁的范围。

void

cancelQuery () 
取消当前查询的执行。

void

clear () 
彻底清除会话。

Connection

close () 
结束释放JDBC连接。

Connection

connection () 
Deprecated.已过时。( 去除率定于4.x的)。更换取决于需要;做直接使用JDBC的东西doWork(org.hibernate.jdbc.Work) ;开一个'临时方法'的使用(待定)。

boolean

contains ( Object object) 
检查该实例与此相关的方法 。

Criteria

createCriteria ( Class persistentClass) 
创建一个新的标准的实体类的实例,对于给定的,或一个类的超类的一个实体。

Criteria

createCriteria ( Class persistentClass, String alias) 
创建一个新的标准的实体类的实例,对于给定的,或一个类的超类的一个实体的别名,用给定的。

Criteria

createCriteria ( String entityName) 
创建一个新的标准的实体名称的实例,对于给定。

Criteria

createCriteria ( String entityName, String alias) 
创建一个新的标准的实体名称的实例,对于给定的别名,用给定的。

Query

createFilter ( Object collection, String queryString) 
指定过滤器的字符串创建一个新的收集和查询的实例。

Query

createQuery ( String queryString) 
创建一个查询字符串中给定的HQL 查询新的实例。

SQLQuery

createSQLQuery ( String queryString) 
创建一个新的查询字符串给定的SQL实例SQLQuery的。

void

delete ( Object object) 
从数据存储中删除持久化实例。

void

delete ( String entityName, Object object) 
从数据存储中删除持久化实例。

void

disableFetchProfile ( String name) 
禁用特定魂在本次方法概况。

void

disableFilter ( String filterName) 
禁用命名为本类方法的过滤器。

Connection

disconnect () 
connection.断开连接会话从当前的JDBC。

void

doWork ( Work work) 
控制器允许用户执行JDBC的相关工作,用本次常委会方法管理的连接。

void

enableFetchProfile ( String name) 
启用魂在本类方法特别配置文件。

Filter

enableFilter ( String filterName) 
本类方法启用此命名的过滤器。

void

evict ( Object object) 
从会话中删除此缓存实例。

void

flush () 
本次方法冲洗力。

Object

get ( Class clazz, Serializable id) 
返回值具有给定给定的实体类的持久化实例标识符,则返回值null,如果不存在这样的持久化实例。

Object

get ( Class clazz, Serializable id, LockMode lockMode) 
Deprecated. 已过时LockMode 参数应改为LockOptions

Object

get ( Class clazz, Serializable id, LockOptions lockOptions) 
返回值具有给定给定的实体类的持久化实例标识符,则返回值null,如果不存在这样的持久化实例。

Object

get ( String entityName, Serializable id) 
返回值给定的命名实体具有给定标识符或NULL,如果不存在这样的持久化实例的持久化实例。

Object

get ( String entityName, Serializable id, LockMode lockMode) 
Deprecated.已过时LockMode 参数应改为LockOptions

Object

get ( String entityName, Serializable id, LockOptions lockOptions) 
返回值具有给定给定的实体类的持久化实例标识符,则返回值null,如果不存在这样的持久化实例。

CacheMode

getCacheMode () 
获取当前缓存模式。

LockMode

getCurrentLockMode ( Object object) 
确定给定对象当前的锁定模式。

Filter

getEnabledFilter ( String filterName) 
目前检索启用筛选器的名称。

EntityMode

getEntityMode () 
检索在本次方法的影响的实体模式。

String

getEntityName ( Object object) 
返回值一个持久化实体的实体名称

FlushMode

getFlushMode () 
获取此会话的当前flush模式。

Serializable

getIdentifier ( Object object) 
返回值给定实体标识符值与此会话相关联。

Query

getNamedQuery ( String queryName) 
获取一个字符串命名查询一个查询实例中定义的映射文件。

Session

getSession ( EntityMode entityMode) 
启动一个给定实体的有效模式新的Session。

SessionFactory

getSessionFactory () 
获取会话工厂,创造了这个方法。

SessionStatistics

getStatistics () 
获得本次方法的统计资料。

Transaction

getTransaction () 
交易实例获取与此相关的方法。

boolean

isConnected () 
检查当前连接的会话。

boolean

isDefaultReadOnly () 
将实体和所装载的代理到本次方法作出只读默认?要确定一个特定的实体或代理read-only/modifiable设置:

boolean

isDirty () 
本次方法是否包含任何必须与数据库同步变化?换言之,任何DML操作会被执行,如果我们这次方法刷新?

boolean

isFetchProfileEnabled ( String name) 
是一个特定的配置文件读取这个会话上启用?

boolean

isOpen () 
检查会话仍然开启。

boolean

isReadOnly ( Object entityOrProxy) 
是指定的单位或者代理只读?若要获取默认read-only/modifiable设置实体和所加载到会话代理使用:

Object

load ( Class theClass, Serializable id) 
返回值给定的给定实体类的持久化实例的标识符,假设实例存在。

Object

load ( Class theClass, Serializable id, LockMode lockMode) 
Deprecated.已过时LockMode 参数应改为LockOptions

Object

load ( Class theClass, Serializable id, LockOptions lockOptions) 
返回值给定的实体类的持久化实例与指定的标识符,获得指定的锁定模式,假设实例存在。

void

load ( Object object, Serializable id) 
阅读与给定的持久状态到给定的瞬时实例标识符相关联。

Object

load ( String entityName, Serializable id) 
返回值给定的给定实体类的持久化实例的标识符,假设实例存在。

Object

load ( String entityName, Serializable id, LockMode lockMode) 
Deprecated. 已过时LockMode 参数应改为LockOptions

Object

load ( String entityName, Serializable id, LockOptions lockOptions) 
返回值给定的实体类的持久化实例与指定的标识符,获得指定的锁定模式,假设实例存在。

void

lock ( Object object, LockMode lockMode) 
Deprecated. 已过时。 改为调用buildLockRequestLockMode)。锁(对象)

void

lock ( String entityName, Object object, LockMode lockMode) 
Deprecated.已过时。 改为调用buildLockRequestLockMode)。锁(entityName,对象)

Object

merge ( Object object) 
复制到具有相同的持久对象给定对象的状态标识符。

Object

merge ( String entityName, Object object) 
复制到具有相同的持久对象给定对象的状态标识符。

void

persist ( Object object) 
做一个瞬态的实例持久化。

void

persist ( String entityName, Object object) 
做一个瞬态的实例持久化。

void

reconnect () 
Deprecated.已过时。 手动数据连接只需要在连接的情况下应用程序提供的,在这种情况下, reconnect(java.sql.Connection)为应使用。

void

reconnect ( Connection connection) 
数据连接到给定的JDBC连接。

void

refresh ( Object object) 
重读从基础数据库中的特定实例的状态。

void

refresh ( Object object, LockMode lockMode) 
Deprecated.已过时LockMode 参数应改为LockOptions

void

refresh ( Object object, LockOptions lockOptions) 
重新阅读给定的数据库实例并从项目的根本,用给定的LockMode。

void

replicate ( Object object, ReplicationMode replicationMode) 
坚持项目给定的实例分离,再利用当前标识值。

void

replicate ( String entityName, Object object, ReplicationMode replicationMode) 
坚持项目给定的实例分离,再利用当前标识值。

Serializable

save ( Object object) 
坚持给定的瞬态的实例,先分配一个生成的标识。

Serializable

save ( String entityName, Object object) 
坚持给定的瞬态的实例,先分配一个生成的标识。

void

saveOrUpdate ( Object object) 
无论是save(Object)update(Object)给定的实例,检查不同值的未保存的决议后,(见检查手册未保存价值的讨论-)。

void

saveOrUpdate ( String entityName, Object object) 
无论是save(String, Object)update(String, Object)给定的实例,检查不同值的未保存的决议后,(见检查手册未保存价值的讨论-)。

void

setCacheMode ( CacheMode cacheMode) 
设置缓存模式。

void

setDefaultReadOnly (boolean readOnly) 
更改为实体,与这个方法装入修改为只读模式,或者从修改为只读模式代理默认。

void

setFlushMode ( FlushMode flushMode) 
本类方法设置刷新模式。

void

setReadOnly ( Object entityOrProxy, boolean readOnly) 
一个未经修改的持久化对象设置为只读模式,或只读对象修改的模式。

void

update ( Object object) 
更新持久实例与给定分离实例标识符。

void

update ( String entityName, Object object) 
更新持久实例与给定分离实例标识符。


七、映射关系

关联映射就是将关联关系映射到数据库里,在对象模型中就是一个或多个引用。

a、Hibernate多对一关联映射:就是在“多”的一端加外键,指向“一”的一端。

比如多个学生对应一个班级,多个用户对应一个级别等等,都是多对一关系。
1、“多”端实体加入引用“一”端实体的变量及getter,setter方法。
比如说多个学生对应一个班级,在学生实体类加入:private Grade grade;
2、“多”端配置文件,student.hbm.xml里的标签设置:
<many-to-one name="grade" column="gradeId" ></many-to-one>

b、Hibernate单向的一对一主键关联映射:就是让两个实体的主键一样,就不需要加入多余的字段了。

比如一个学生对应一个身份证号,一个学生对应一条户口信息等等,都是一对一关联映射。
1、Person实体里要持有IdCard的引用。在Person实体里加入属性:Private IdCard idCard;
2、Person端维护关系,所以需要重点看Person的配置文件,Person.hbm.xml通俗来讲 ,就是就是Person中的Id既为主键又为外键。
所以需要修改Person中的id标签:通俗来讲是告诉Person里的id去关联哪个实体里的id。
此处的foreign生成策略,会取得关联对象的标识。
此处的property标签内是关联对象。
<id name="id">
    <generator class="foreign">
    <param name="property">idCard</param>
    </generator>
</id>
3、在Person.hbm.xml中添加关联关系的标签:<one-to-one name="idCard" constrained="true"><one-to-one/>
这里的one-to-one标签指示hibernate如何加载其关联对象,默认根据主键加载也就是拿到关系字段值,根据对端的主键来加载关联对象。
这里的constrained="true"表示当前主键Person的id主键,还是一个外键,参照了对应端的主键IdCard的id主键,会生成外键约束语句。
注:采用foreign映射策略在保存person对象的同时也会保存关联的对象,也就是idCard,他们之间还有级联关系。但是反之就不可以,也就是说,如果只保存IdCard对象,是会出错的,不会保存Person对象,因为关系的维护端在Person端,IdCard根本就不知道Person的存在。主键关联映射有弊端,不好维护。

c、Hibernate双向一对一关联映射:有些需求要求从一端可以查到另一端,从另一端又可以查到这一端,就需要双向的关联映射。

比如说,想要根据人的信息查到他的户口信息,也想根据户口信息查到这是哪个人的信息等。
1、修改对象模型,在IdCard.java 的实体里加入Person的引用,添加属性:private Person person;(在Person.java实体里也有IdCard的引用哦)
2、修改IdCard.hbm.xml文件,添加one-to-one标签。
<one-to-one name="person"/>
注1:one-to-one标签不影响存储,只影响加载,不会修改数据库,也就是说不会添加字段,而many-to-one会修改数据库,会增加一个字段。
注2:了解抓取策略:fetch="select" 可以控制查取数据的顺序。

d、单向一对一唯一外键关联映射:一对一主键关联不好维护,用外键关联对象比较好。原理:多对一的特殊情况。

比如说还是Person和IdCard的例子。
1、Person.java是实体里有IdCard的引用,即加入属性:private IdCard idCard;IdCard.java里没有Person引用。
2、配置文件:IdCard.hbm.xml里都是普通属性。Person.hbm.xml的主键生成策略需要改变:改回:
<generator class="native"/>
使用标签many-to-one和unique  : <many-to-one name="idCard" unique="true"/> ,这样就限制了多的一端的唯一性。
注:这里需要先保存IdCard.否则报错。

e、双向一对一唯一外键关联:如果有需求要求的情况下,也可以建立双向的外键关联。

1、在Person和IdCard里添加对应端的引用,即添加相应属性。
2、person.hbm.xml和例子(四)中一样,修改IdCard.hbm.xml文件,添加one-to-one标签:<one-to-one name="person" property-ref="idCard"></one-to-one>.
注:必须指定one-to-one标签中的property-ref属性为关系字段的名称。

f、Hibernate单向一对多关联映射:让一的一端维护关系,和多对一的映射原理是一样的,都是在多的一端加入一个外键指向一的一端;

区别在于维护的关系不同:
多对一维护的关系:多指向一的关系,如果维护了多指向一的关系,那么加载多的一端的时候会把一的一端加载上来;
一对多维护的关系:一指向多的关系,如果维护了一指向多的关系,那么加载一的一端的时候会把多的一端加载上来。
比如说一个班里有多名学生。
1、Classes.java 和 Student.java里各有两个普通属性id和name。在Classes里加入新属性:private Set students;
2、映射文件的修改:Classes.hbm.xml里除了普通属性,加入集合映射:
<set name="students">
  <key column="classesid"></key>
  <one-to-many class="com.juyahong.hibernate.Student"/>
</set>
注1:“一”的一端维护关系。
注2:session.save(student),session.save(classes),保存student和classes对象。可以成功保存数据,但是需要发出多余的update语句来维持关系。

g、Hibernate双向一对多关联映射:让多的一端来维护关系。

主要是解决一对多单向关联的缺陷,而不是需求驱动的。
1、在Student.java实体类里添加Classes引用。private Classes classes;
2、Student.hbm.xml里添加many-to-one标签:<many-to-one name="classes" column="classesid"/>.Classes.hbm.xml在例子(六)里的那个的基础上加入反转属性inverse(以后将维护关系的工作交给了student)。
<set name="students" inverse="true">
    <key column="classesid"></key>
    <one-to-many class="com.juyahong.hibernate.Student"/>
</set>
注1:先保存classes,再保存student。
注2:一对多双向关联的映射方式:
           在一的一端的集合上采用key标签,可以使得多的一端加入一个外键。
           在多的一端采用many-to-one标签
注3:key标签和many-to-one标签加入的字段保持一致,否则会产生数据混乱。
注4:一对多关联映射通常在多的一端维护关系,让一的一端失效:
  ------inverse反转属性的使用:可以用在一对多和多对多双向关联上,inverse属性默认为false,即表示在本端可以维护关系,如果inverse为true,即表示本端不维护关系,要交给另一端来维护关系,本端失效。它是控制方向上的反转,只影响存储。
  ------cascade是操作上的连锁反应(暂时了解)。

h、Hibernate单向多对多关联映射:

比如学生和课程之间的关系,用户和角色之间的关系都是多对多关系。
1、User.java和Role.java实体类里都有两个普通属性id和name,在User.java里添加属性,private Set roles;
2、修改User.hbm.xml映射文件:映射集合:
<set name="roles" table="t_user_role">
    <key column="user_id"/>
    <many-to-many class="com.juyahong.hibernate.Role" column="role_id"/>
    </key>
</set>

i、Hibernate双向多对多关联映射:

1、Role.java里加入新集合private Set users;
2、在例子八的基础上,修改Role.hbm.xml文件
<set name="users" table="t_user_role">
   <key column="role_id"/>
   <many-to-many class="com.juyahong.hibernate.User" column="user_id"/>
   </key>
</set>


八、注解

1. 类级别注解 

@Entity     映射实体类

@Table    映射数句库表


@Entity(name="tableName") - 必须,注解将一个类声明为一个实体bean。 

属性: 

name - 可选,对应数据库中的一个表。若表名与实体类名相同,则可以省略。

  

@Table(name="",catalog="",schema="") - 可选,通常和@Entity 配合使用,只能标注在实体的class定义处,表示实体对应的数据库表的信息。 

属性:

name - 可选,表示表的名称,默认地,表名和实体名称一致,只有在不一致的情况下才需要指定表名;

catalog - 可选,表示Catalog名称,默认为 Catalog("");

schema - 可选 , 表示 Schema 名称 , 默认为 Schema("");


2. 属性级别注解

@Id     映射生成主键

@Version    定义乐观锁

@Column     映射表的列

@Transient     定义暂态属性  


2.1 与主键相关注解

@Id - 必须,定义了映射到数据库表的主键的属性,一个实体只能有一个属性被映射为主键,置于 getXxxx() 前。

@GeneratedValue(strategy=GenerationType,generator="") - 可选,用于定义主键生成策略。

属性:

Strategy - 表示主键生成策略,取值有: 

GenerationType.AUTO - 根据底层数据库自动选择(默认),若数据库支持自动增长类型,则为自动增长。

GenerationType.INDENTITY - 根据数据库的Identity字段生成,支持DB2、MySQL、MS、SQL Server、SyBase与HyperanoicSQL数据库的Identity类型主键。

GenerationType.SEQUENCE - 使用Sequence来决定主键的取值,适合Oracle、DB2等支持Sequence的数据库,一般结合@SequenceGenerator使用。

(Oracle没有自动增长类型,只能用Sequence)

GenerationType.TABLE  - 使用指定表来决定主键取值,结合@TableGenerator使用。

如:

@Id

@TableGenerator(name="tab_cat_gen",allocationSize=1)

@GeneratedValue(Strategy=GenerationType.Table)

Generator - 表示主键生成器的名称,这个属性通常和ORM框架相关 , 例如:

Hibernate 可以指定 uuid 等主键生成方式


@SequenceGenerator — 注解声明了一个数据库序列。

属性:

name - 表示该表主键生成策略名称,它被引用在@GeneratedValue中设置的“gernerator”值中。

sequenceName - 表示生成策略用到的数据库序列名称。

initialValue - 表示主键初始值,默认为0.

allocationSize - 每次主键值增加的大小,例如设置成1,则表示每次创建新记录后自动加1,默认为50.


示例 : 

    @Id 

    @GeneratedValues(strategy=StrategyType.SEQUENCE) 

    public int getPk() { 

       return pk;  

    }  


Hibernate的访问类型为field时,在字段上进行注解声;

访问类型为property时,在getter方法上进行注释声明。


2.2 与非主键相关注解

@Version - 可以在实体bean中使用@Version注解,通过这种方式可添加对乐观锁定的支持


@Basic - 用于声明属性的存取策略:

@Basic(fetch=FetchType.EAGER)   即时获取(默认的存取策略)

@Basic(fetch=FetchType.LAZY)    延迟获取


@Temporal - 用于定义映射到数据库的时间精度:

@Temporal(TemporalType=DATE)       日期

@Temporal(TemporalType=TIME)       时间

@Temporal(TemporalType=TIMESTAMP) 两者兼具


@Column - 可将属性映射到列,使用该注解来覆盖默认值,@Column描述了数据库表中该字段的详细定义,这对于根据 JPA 注解生成数据库表结构的工具非常有作用。

属性:

name - 可选,表示数据库表中该字段的名称,默认情形属性名称一致 

nullable - 可选,表示该字段是否允许为 null,默认为 true 

unique - 可选,表示该字段是否是唯一标识,默认为 false 

length - 可选,表示该字段的大小,仅对 String 类型的字段有效,默认值255.

insertable - 可选,表示在ORM框架执行插入操作时,该字段是否应出现INSETRT 语句中,默认为 true 

updateable - 可选,表示在ORM 框架执行更新操作时,该字段是否应该出现在 UPDATE 语句中,默认为 true. 对于一经创建就不可以更改的字段,该    属性非常有用,如对于 birthday 字段。

columnDefinition - 可选,表示该字段在数据库中的实际类型。通常ORM 框架可以根据属性类型自动判断数据库中字段的类型,但是对于Date 类型仍无法确定数据       库中字段类型究竟是 DATE,TIME 还是 TIMESTAMP. 此外 ,String 的默认映射类型为 VARCHAR, 如果要将 String 类型映射到特定数据库的 BLOB或 TEXT 字段类型,该属性非常有用。

示例 : 

    @Column(name="BIRTH",nullable="false",columnDefinition="DATE") 

    public String getBithday() { 

       return birthday; 

    } 

   

@Transient - 可选,表示该属性并非一个到数据库表的字段的映射,ORM框架将忽略该属性,如果一个属性并非数据库表的字段映射,就务必将其标示为 @Transient,否则ORM 框架默认其注解为 @Basic 

示例 : 

    // 根据 birth 计算出 age 属性 

    @Transient 

    public int getAge() { 

       return getYear(new Date()) - getYear(birth); 

    } 

    

2.3无注解属性的默认值

如果属性为单一类型,则映射为@Basic,

否则,如果属性对应的类型定义了@Embeddable注解,则映射为@Embedded,

否则,如果属性对应的类型实现了Serializable, 则属性被映射为@Basic并在一个列中保存该对象的serialized版本,

否则,如果该属性的类型为java.sql.Clob 或 java.sql.Blob,则作为@Lob并映射到适当的LobType.。


3.映射继承关系

@Inheritance注解来定义所选择的策略. 这个注解需要在每个类层次结构(class hierarchy) 最顶端的实体类上使用 


4.映射实体bean的关联关系


4.1关联映射的一些定义

单向一对多:一方有集合属性,包含多个多方,而多方没有一方的引用。用户--->电子邮件

单向多对一:多方有一方的引用,一方没有多方的引用。论文类别 ---> 类别

双向一对多:两边都有多方的引用,方便查询。班级 ---> 学生

双向多对一:两边都有多方的引用,方便查询。

单向多对多:需要一个中间表来维护两个实体表。论坛 --->文章

单向一对一:数据唯一,数据库数据也是一对一。舰船 ---> 水手

主键相同的一对一:使用同一个主键,省掉外键关联。客户 ---> 地址


单向:关系写哪边,就由谁管理。

双向:一般由多方管理。

@OneToMany(mappedBy="对方") //反向配置,对方管理。


4.2 关联映射的一些共有属性

@OneToOne、@OneToMany、@ManyToOne、ManyToMany的共有属性:

fetch - 配置加载方式。取值有

Fetch.EAGER -  及时加载,多对一默认是Fetch.EAGER  

Fetch.LAZY - 延迟加载,一对多默认是Fetch.LAZY

cascade - 设置级联方式,取值有:

CascadeType.PERSIST - 保存

CascadeType.REMOVE - 删除

CascadeType.MERGE - 修改

CascadeType.REFRESH - 刷新

CascadeType.ALL - 全部

targetEntity - 配置集合属性类型,如:@OneToMany(targetEntity=Book.class)


@JoinColumn - 可选,用于描述一个关联的字段。

@JoinColumn和@Column类似,介量描述的不是一个简单字段,而是一个关联字段,例如描述一个 @ManyToOne 的字段。


属性:

name - 该字段的名称,由于@JoinColumn描述的是一个关联字段,如ManyToOne, 则默认的名称由其关联的实体决定。

例如,实体 Order 有一个user 属性来关联实体 User, 则 Order 的 user 属性为一个外键 , 

其默认的名称为实体User的名称 + 下划线 + 实体User的主键名称 


4.3 一对一关联

@OneToOne – 表示一个一对一的映射

a.主表类A与从表类B的主键值相对应。

 主表:@OneToOne(cascade = CascadeType.ALL)

     @PrimaryKeyJoinColumn

     public B getB(){

  Return b;

    }

从表:无


b.主表A中有一个从表属性是B类型的b 

主表:@OneToOne(cascade = CascadeType.ALL)

   @JoinColumn(name="主表外键")   //这里指定的是数据库中的外键字段。

   public B getB(){

return b;

       } 

从表:无


c.主表A中有一个从表属性是B类型的b,同时,从表B中有一个主表属性是A类型的a

主表:@OneToOne(cascade = CascadeType.ALL)

   @JoinColumn(name="主表外键")   //这里指定的是数据库中的外键字段。

   public B getB(){

return b;

       }

从表:@OneToOne(mappedBy = "主表类中的从表属性")

   public 主表类 get主表类(){

return 主表对象

      }

  注意:@JoinColumn是可选的。默认值是从表变量名+"_"+从表的主键(注意,这里加的是主键。而不是主键对应的变量)。


4.4 多对一关联

@ManyToOne - 表示一个多对一的映射,该注解标注的属性通常是数据库表的外键。

a.单向多对一:多方有一方的引用,一方没有多方的引用。

    在多方

@ManyToOne(targetEntity=XXXX.class)   //指定关联对象

@JoinColumn(name="") //指定产生的外键字段名


b.双向多对一:配置方式同双向一对多。


示例 : 

    // 订单 Order 和用户 User 是一个 ManyToOne 的关系 

    // 在 Order 类中定义 

    @ManyToOne() 

    @JoinColumn(name="USER") 

    public User getUser() { 

       return user; 

}


4.5 一对多关联

@OneToMany - 描述一个一对多的关联,该属性应该为集合类型,在数据库中并没有实际字段。

a.单向一对多:一方有集合属性,包含多个多方,而多方没有一方的引用。

@OneToMany  默认会使用连接表做一对多关联

添加@JoinColumn(name="xxx_id") 后,就会使用外键关联,而不使用连接表了。


b.双向一对多

1)在多方

@ManyToOne

@JoinColumn(name="自己的数据库外键列名")


2)在一方

@OneToMany(mappedBy="多端的关联属性名")

@JoinColumn(name="对方的数据库外键列名")


4.6 多对多关联

@ManyToMany - 可选,描述一个多对多的关联。

属性:

targetEntity - 表示多对多关联的另一个实体类的全名,例如:package.Book.class 

mappedBy - 用在双向关联中,把关系的维护权翻转。


a.单向多对多关联:

    在主控方加入@ManyToMany注解即可。

b.双向多对多关联:

    两个实体间互相关联的属性必须标记为@ManyToMany,并相互指定targetEntity属性。有且只有一个实体的@ManyToMany注解需要指定mappedBy属性,指向targetEntity的集合属性名称。







注意:本文归作者所有,未经作者允许,不得转载