hibernate关联映射

来源:互联网 发布:java线程池的函数 编辑:程序博客网 时间:2024/05/17 09:23

Hibernate-01简介:Hibernate 开源O/R映射框架(ORM)

分层:下层为上层提供服务

表示层:struts  webWork JSF

业务层:spring

持久层:与业务无关 hibernate(冬眠:让对象冬眠) ibatis

数据库:

 

OOA:面向对象的分析

OOD:面向对象的设计

OOP:面型对象的编程

 

阻抗不匹配(Java类中的继承关系不能体现在关系型数据库中)

 

创建的其他O/R映射框架:

ApacheOJB

JDO java数据对象

Toplink(oracle)

EJB(2.0cmp)(3.0 JPA)

IBatis(严格意义上讲不是OR框架,轻量级)

 

Hibernate优点:

 1,无需SQL,效率更高(JDBC不需要我们写了)

 2,使开发更面向对象化

 3,移植性高

 4,实现了透明持久化,不需要继承或实现Hibernate包中的任何类或接口(pojo)

 5,没有侵入性(轻量级)

Hibernate缺点:

 1,不支持批量操作

 2,使用到数据库特用功能的时候就不能使用Hibernate(因为sql是自动生成的)

Hibernate-02例子

pojo.hbm.xml:映射文件

1,新建项目

 

2,创建User Library,加入jar包

  *HIBERNATE_HOME/hibernate3.jar

  *HIBERNATE_HOME/lib/*.jar

  *数据库驱动jar

 

3,创建Hibernate配置文件:hibernate.cfg.xml(HIBERNATE_HOME/etc)

  为了便于调试,将log4j.properties加入到项目中

 

4,创建一个实体类pojo

 

5,定义User类的映射文件POJO.hbm.xml

 

6,将POJO.hbm.xml引入到件ibernate.cfg.xml中

7,写一个类,将实体类生成数据库表

       Configurationcfg = new Configuration().configure();

         SchemaExport se = newSchemaExport(cfg);

         se.create(true, true);

8,通过      Configuration cfg = newConfiguration().configure();

           SessionFactorysf = cfg.buildSessionFactory();

           Sessionsession = sf.openSession();

            session.beginTransaction();

            session.save(u);

            session.getTransaction().commit();

            session.close();

9,show_sql=true:显示hibernate执行的SQL语句

Hibernate-03核心接口

JNDI:同一管理对象资源,通过友好字符串可以获得一个对象(数据库连接池)

JDBC:事务管理只能针对同一个数据库

JTA:Java事务API,可以实现跨数据库事务的统一管理(跨行转账)

 

Hibernate-05_Session接口的基本用法及生命周期

 

1,了解Hibernate中的CRUD操作

  save()

  update()

  saveOrUpdate()

  get()

  post()

2,了解get和load的区别:

                get(),采用get方法加载数据库中的数据,如果不存在,返回null

        load(),延迟加载,在执行load方法的时候不会发出sql语句,只是返回一个CGLIB代理对象,只有在真正第一次使用查询出对象的时候才发出SQL语句查询数据库;采用load方法加载数据库中的数据,如果不存在,则抛出异常

3,transient状态的特征:

    *在数据库中没有与之匹配的数据

    *没有加入session的管理

  persistent状态的特征:

    *在数据库中存在(不绝对)

    *同时纳入了session管理

    *在清理缓存(脏数据检查)的时候会和数据库同步

 4,detached状态的特征:

    *在数据库中有与之对应的记录

*没有纳入session的管理

 

 

 

 

 

 

Hibernate-04持久对象的生命周期

 

瞬态:新创建的对象,在数据库中没有与之对应的记录

持久态:存入数据库,接收session的管理

游离态:在数据库中有与之对应的记录,但是脱离了session的管理

 

 

 

 

 

 

 

Hibernate-06_Query接口

 

1,Query查询所有记录:

  Query query = session.createQuery("fromUser");

2,Query的分页:                        

  //设置从的几条开始查询

  query.setFirstResult(3);

  //设置查询多少条

  query.setMaxResults(2);

 

 

 

 

 

 

 

Hibernate-07基本映射标签和属性

Hibernate的基本映射:

  实体类---表

  实体类中的属性---表字段

 

  采用<class></class>标签将实体类映射成数据库表

         name

         table

         lazy

 

  采用<property/>标签将普通属性映射成表字段

         name

         column

         length

         type(指定数据库中该字段的类型:一般情况下不需要指定)

         update true|false  该字段不会出现在update的Sql语句中

         insert true|false

         unique 唯一性

         not-null 是否为空

 

  采用<id></id>配置数据库主键

         <generator class="native"/>设置主键的自动增长

         class="native/uuid/identity/sequence"

         native----Hibernate完成的数字自增1,2,3...

         uuid----生成一个32位的字符串

         identity----sqlserver的自增

        sequence----oracle的自增(1,2,...)

         assigned----手动分配主键

 

采用<composite-id></composite-id>设置联合主键

 

实体类的设计原则(POJO):

         1,实现一个默认的无参的构造方法

         2,提供一个标识属性

         3,使用非final的类(影响预加载)

         4,为持久化字段声明访问器(提供get和set方法)

防止已经存在的表在重新导出的时候被覆盖:

         在hibernate.cfg.xml里面加上配置

         <propertyname="hbm2ddl.auto">true</property>

 


 

Hibernate-11一对一唯一外键关联映射-单向

一个人只有一个身份证:Person---->IDCard

Person            IDCard

-----------          -----------

id:int             id:int

name:String       cardNo:String

idCard:IDCard

单向时指:站在Person这一段可以看到IDCard对象

外键关联:在一张表中添加一个外键,指向关联表的主键(在Person表中添加外键指向IDCard的主键)

IDCard.hbm.xml

-----------------------------------------------

<classname="com.softeem.IDCard">

    <id name="id">

        <generatorclass="native"/>

    </id>

    <property name="cardNo"/>

</class>

 

Person.hbm.xml

-----------------------------------------------

<classname="com.softeem.Person">

    <id name="id">

        <generatorclass="native"/>

    </id>

    <property name="name"/>

    一对一就是多对一中的特例:给外键条件了一个唯一性约束

    <many-to-one name="idCard"unique="true"/>

</class>

Hibernate-12一对一唯一外键关联映射-双向

一个人只有一个身份证:Person<---->IDCard

Person            IDCard

-----------          -----------

id:int             id:int

name:String       cardNo:String

idCard:IDCard    person:Person

外键双向关联:在一张表中添加一个外键,指向关联表的主键(在Person表中添加外键指向IDCard的主键)

-----------------------IDCard.hbm.xml------------------------

<classname="com.softeem.IDCard">

    <id name="id">

        <generatorclass="native"/>

    </id>

    <property name="cardNo"/>

    一对一关联映射默认的是通过主键加载指定的对象

    添加了property-ref属性之后,就表示加载的时候就根据person对象的idCard加载,因为icard也是唯一的,所以实现了一对一的关联

    <one-to-one name="person"property-ref="idCard"/>

</class>

---------------------Person.hbm.xml-------------------------

<classname="com.softeem.Person">

<id name="id">

<generatorclass="native"/>

 </id>

    <property name="name"/>

    一对一就是多对一中的特例:给外键条件了一个唯一性约束

    <many-to-one name="idCard"unique="true"/>

</class>

Hibernate-15多对多关联映射-单向

 

一个用户对用多个角色,多个用户也可能具有同一个角色:User---->Role

 

User              Role

--------------    --------------

id:int            id:int

name:String       name:String

roles:Set

 

多对多关联映射通常要采用第三方表,用来存放两者之间的关系

 

tb_user                tb_user_role            tb_role

-----------------      -------------------     --------------------

id   |  name           userid |roleid        id  |  name

-----------------      -------------------     --------------------

1    |  张三             1    | 2             1  |  经理

2    |  李四             1    | 3             2  |  主管

3    |  王五             2    | 1             3  |  领班

 

User.hbm.xml

-----------------------------------------------------------------

<classclass="com.softeem.User">

    <id name="id">

        <generator class="native"/>

    </id>

    <property name="name"/>

    <!--添加table="tb_user_role",指明要引用第三方表,并且hibernate会自动创建这张表-->

    <set name="roles"table="tb_user_role" order-by="userid">

        <!--key标签表示,使用user的主键作为第三方表的一个外键,字段名为userid-->

        <key column="userid"/>

        <!--声明set集合映射到Role类对应得表,并且将映射表的主键作为第三方表的一个字段,并且将引入的这两个字段作为“复合主键”-->

        <many-to_manycalss="com.softeem.Role" column="roleid"/>

    </set>

</class>

 

Role.hbm.xml

-----------------------------------------------------------------

<classclass="com.softeem.Role">

    <id name="id">

        <generatorclass="native"/>

    </id>

    <property name="name"/>

</class>


 

Hibernate-16多对多关联映射-双向

 

一个用户对用多个角色,一个Role也对用多个用户:User<---->Role

 

User              Role

--------------    --------------

id:int            id:int

name:String       name:String

roles:Set         users:Set

 

 

多对多关联映射通常要采用第三方表,用来存放两者之间的关系

 

tb_user                tb_user_role            tb_role

-----------------           -------------------        --------------------

id   |   name         userid | roleid        id |  name

-----------------           -------------------         --------------------

1    |  张三          1    | 2           1  |  经理

2    |  李四          1    | 3           2  |  主管

3    |  王五          2    | 1           3 |  领班

 

User.hbm.xml

-----------------------------------------------------------------

<classclass="com.softeem.User">

    <id name="id">

        <generatorclass="native"/>

    </id>

    <property name="name"/>

    <!--添加table="tb_user_role",指明要引用第三方表,并且hibernate会自动创建这张表-->

    <set name="roles"table="tb_user_role">

        <!--key标签表示,使用user的主键作为第三方表的一个外键,字段名为userid-->

        <key column="userid"/>

        <!--声明set集合映射到Role类对应得表,并且将映射表的主键作为第三方表的一个字段,并且将引入的这两个字段作为“复合主键”-->

        <many-to-manycalss="com.softeem.Role" column="roleid"/>

    </set>

</class>

 

Role.hbm.xml

-----------------------------------------------------------------

<classclass="com.softeem.Role">

    <id name="id">

        <generatorclass="native"/>

    </id>

    <property name="name"/>

    <!--指定的第三方表要与User中指定的完全一致-->

    <set column="users"table="tb_user_role">

        <key column="roleid"/>

        <many-to-manyclass="com.softeem.User" column="userid"/>

    </set>

</class>


 

Hibernate-17延迟加载lazy

 

延迟加载(懒加载):查询出的对象在使用的时候才加载进来

 

可以用在class标签  property标签  set标签 one2one和many2one

 

<class>标签上,可以取值:true/false

<property>标签上,可以取值:true/false 使用类增强工具,修改字节码达到代理的目的

<set><list>标签上,可以取值:true/false/extra

one2one和many2one单端关联,可以取值:false/proxy/noproxy

 

lazy概念,只有真正使用该对象时才会创建;对于Hibernate而言,只有真正使用对象的时候才会发出sql语句

 

 

CGLib可以对普通类进行代理

JDK的代理只能代理实现了接口的类




Hibernate-08多对一关联映射

 

多个用户属于一个组:User----Group

 

User             Group

-----------          -----------

id:int             id:int

name:String       name:String

group:Group

 

关联映射的本质:

       将关联关系映射到数据库, 所谓的关联关系是对象模型在内存中的一个或 多个引用

 

User.hbm.xml:

<class name=”com.softeem.User”>

    <idname="id">

       <generator class="native"/>

    </id>

    <propertyname="name"/>

       <many-to-onename="group" column="groupid"casecade="save-update">

</class>

 

 

Group.hbm.xml

<class name=”com.softeem.Group”>

    <idname="id">

       <generator class="native"/>

    </id>

    <propertyname="name"/>

</class>

Hibernate-09一对一主键关联映射-单向

 

一个人只有一个身份证:Person---->IDCard

 

Person           IDCard

-----------      -----------

id:int           id:int

name:String      cardNo:String

idCard:IDCard

 

单向时指:站在Person这一段可以看到IDCard对象

双向是指:站在Person这一段可以看到IDCard对象同时站在IDCard对象一段页可以看到对用的Person对象

 

主键关联:让关联对象的id(主键)保持一致,不用加任何字段;就是让Person的主键和IDCard保持一致,而不是自动增长

 

IDCard.hbm.xml

-----------------------------------------------

<class name="com.softeem.IDCard">

    <idname="id">

       <generator class="native"/>

    </id>

    <propertyname="cardNo"/>

</class>

 

Person.hbm.xml

-----------------------------------------------

<class name="com.softeem.Person">

    <idname="id">

       <generator class="foreign"> :设置成外键关联

           <param name="property">idCard</param>:关联icCard对应主键

       </gennerator>

    </id>

    <propertyname="name"/>

   <one-to-one name="idCard" constrained="true"/>

       添加上外键约束:指示hibernate怎样加载他的关联对象(默认根据主键加载)

       一对一主键关联映射中,默认了casecade属性

</class>

Hibernate-10一对一主键关联映射-双向

 

一个人和一个身份证只能唯一对应:Person<---->IDCard

 

Person           IDCard

-----------      -----------

id:int           id:int

name:String      cardNo:String

idCard:IDCard   person:Person

 

 

双向是指:站在Person这一段可以看到IDCard对象同时站在IDCard对象一段页可以看到对用的Person对象

 

主键关联:让关联对象的id(主键)保持一致,不用加任何字段;就是让Person的主键和IDCard保持一致,而不是自动增长

 

IDCard.hbm.xml

-----------------------------------------------

<class name="com.softeem.IDCard">

    <idname="id">

       <generator class="native"/>

    </id>

    <propertyname="cardNo"/>

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

       默认抓取策略fetch=“jion”,只发一条外连接查询语句

</class>

Person.hbm.xml

-----------------------------------------------

<class name="com.softeem.Person">

    <idname="id">

       <generator class="foreign"> :设置成外键关联

           <param name="property">idCard</param>:关联icCard对应主键

       </gennerator>

    </id>

    <propertyname="name"/>

   <one-to-one name="idCard" constrained="true"/>

       添加上外键约束:指示hibernate怎样加载他的关联对象(默认根据主键加载)

       一对一主键关联映射中,默认了casecade属性

</class>

 

Hibernate-13一对多关联映射-单向

 

一个班级对应多名学生:Classes---->Student

 

Classes                   Student

--------------------            ------------

id:int                    id:int

name:String               name:String

students:Set<Student>

多对一关联映射:在一得一端加一个外键,指向多的一端,维护的关系是多指向一

一对多关联映射:在加载一个班级的时候能够加载班级中所有的学生,在多的一端加一个外键,指向一的一端,维护的关系是一指向多

--------------------------Classess.hbm.xml---------------------------

<class name="com.softeem.Classes">

<id name="id">

<generatorclass="native"/>

 </id>

    <propertyname="name"/>

    <setname="students">

        <!--这一句话的作用是在student表中添加一个主键,指向classes的id-->

              <!--执行的时候student表中的classis字段为空,添加classes记录之后执行修改,所以这个字段不能添加非空约束,不然就不能保存-->

        <keycolumn="classid"/>

        <!--指定执行时的加载对象-->

       <one-to-many class="com.softeem.Student"/>

    </set>

</class>

 

--------------------------Student.hbm.xml--------------------------

<class class="com.softeem.Student">

<id name="id">

<generatorclass="native"/>

</id>

    <propertyname="name"/>

</class>

 

Hibernate-14一对多关联映射-双向

 

一对多关联映射双向:Classes<---->Student

Classes                   Student

--------------------           ------------

id:int                    id:int

name:String               name:String

students:Set<Student>     classes:Classes

 

一对多双向关联映射:加载Classes的时候能够加载这个班级所有的学生信息,同时在加载一个Student的时候能够加载这个学生所在的班级信息

 

-------------------------Classess.hbm.xml----------------------------

<class name="com.softeem.Classes">

<id name="id">

<generatorclass="native"/>

</id>

    <propertyname="name"/>

<!--invase反转属性:允许在多的一端维护关系(在学生的classid为null但是关系存在)-->

<!--相当于反转成了多对一关系:不会再发出update语句-->

<!--设置反转之后,先将Classes给student对象设置进去,student不用sava了,通过级联完成存储-->

    <setname="students" inverse="true" casecade="all">

        <keycolumn="classid"/><!--指定执行时的加载对象-->

       <one-to-many class="com.softeem.Student"/>

    </set>

</class>

 

------------------------Student.hbm.xml-----------------------------

<class class="com.softeem.Student">

<id name="id">

<generatorclass="native"/>

</id>

    <propertyname="name"/>

   <!--映射的时候需要注意,这个字段的名字要和一的一端指定的字段名字相同-->

    <!--多对一存储的时候:需要先存储多的一端的对象-->

    <!--一对多存储的时候:需要先存储多的一端的对象-->

   <many-to-one name="classes" column="classid"/>

</class>

Hibernate-18继承映射

 

继承映射的三种策略:

1,(单表继承)每棵类继承树映射成一张表

2,(具体表继承)每个子类映射成一张表

3,(类表继承)每个具体类映射成一张表

 

 

1,每棵继承树映射成一张表(就是将父类和子类中所有的属性都映射成一张表的字段)

Id

Name

Sex

Weight

Height

type

 对于每一个子类,在生成的表中添加一个字段来区别他们

Animal                  Pig(继承Animal)      Bird(继承Animal)

---------------------           ------------------        -----------------------

id                      weight              height

name

sex

 

extends.hbm.xml


<classname=”com.softeem.Animal” table=”t_animal”>

         <id name=”id”>

                  <generatorclass=”native”/>

         </id>

         <!—加入鉴别器:用来区别子类的类型,对应于type字段-->

        <discriminator column=”type”type=”string”/>

         <property name=”name”/>

         <property name=”sex”/>

</class>

<sub- classname=”Pig”extends=”Animal” discriminator-value=”p”>

         <property name=”weight”/>

</sub-class>

<sub- class name=”Bird”extends=”Animal” discriminator-value=”b”>

         <property name=”height”/>

</sub-class>

<hibernate-mappingpackage=”com.softeem”>

<classname=” Animal” table=”t_animal”>

         <id name=”id”>

                   <generatorclass=”native”/>

         </id>

         <!—加入鉴别器:用来区别子类的类型,对应于type字段-->

        <discriminator column=”type”type=”string”/>

         <property name=”name”/>

         <property name=”sex”/>

         <sub- class name=”Pig” discriminator-value=”p”>

         <propertyname=”weight”/>

</sub-class>

<sub- class name=”Bird” discriminator-value=”b”>

         <propertyname=”height”/>

</sub-class>

</class>

</hibernate-mapping>


 


 


2,(具体表继承)每个子类映射成一张表

t_animal

Id

Name

sex

1

小猪

2

小鸟

t_pig

Pid(animal_id)

weight

1

30kg

 t_bird

Bid(animal_id)

height

2

12m

<hibernate-mappingpackage=”com.softeem”>

<class name=”Animal”table=”t_animal”>

     <idname=”id”>

              <generatorclass=”native”/>

     </id>

     <propertyname=”name”/>

     <propertyname=”sex”/>

     <joined-subclass name=”Pig”table=”t_pig”>

              <keycolumn=”pid”/>

              <propertyname=”weight”/>

     </joined-subclass>

     <joined-subclass name=”Bird”table=”t_bird”>

              <keycolumn=”bid”/>

              <propertyname=”height”/>

     </joined-subclass>

</class>

</hibernate-mapping>

3(类表继承)每个具体类映射成一张表

t_pig

Id

Name

Sex

weight

t_bird

Id

Name

Sex

height

<hibernate-mappingpackage=”com.softeem”>

<class name=”Animal”table=”t_animal”>

     <idname=”id”>

              <generatorclass=”uuid”/>

     </id>

     <propertyname=”name”/>

     <propertyname=”sex”/>

     <union-subclass name=”Pig” table=”t_pig”>

              <propertyname=”weight”/>

     </joined-subclass>

     < union -subclass name=”Bird”table=”t_bird”>

              <propertyname=”height”/>

     </joined-subclass>

</class>

</hibernate-mapping>

 

 

 

 

 

 

 


 

 



原创粉丝点击