Hibernate 应用

来源:互联网 发布:怎样下载cad软件 编辑:程序博客网 时间:2024/06/04 19:02

Hibernate对象关系映射,基本工作原理是将对象数据保存到关系数据库的表中,以及将关系数据库中数据读入到对象中。
对象关系映射Object Relation Mapping, ORM,数据持久化

Hibernate 工作过程

搭建Hibernate实验环境 需要引入Hibernate下的核心包hibernate3.jar 、依赖包即 \lib 文件夹下的所有jar文件 、mysql驱动包 、Hibernate核心配置文件 hibernate.cfg.xml。

驱动包jar包,如下所示:
antlr-2.7.6.jar
commons-collections-3.1.jar
dom4j-1.6.1.jar
hibernate3.jar
javassist-3.4.GA.jar
jta-1.1.jar
slf4j-api-1.5.2.jar
log4j-1.2.15.jar
slf4j-log4j12-1.5.2.jar
mysql-connector-java-5.1.6-bin.jar
ddl.sql(自定义的mysql语句,在首先Hibernate执行之前,需要先用mysql命令行执行这一个文件)
hibernate.cfg.xml文件配置如下:

<!DOCTYPE hibernate-configuration PUBLIC    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"    "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"><hibernate-configuration>    <session-factory>        <!-- 数据库方言设置 -->        <property name="hibernate.dialect">            org.hibernate.dialect.MySQLInnoDBDialect        </property>        <!-- 数据库连接参数设置 -->        <property name="hibernate.connection.driver_class">            com.mysql.jdbc.Driver        </property>        <property name="hibernate.connection.url">jdbc:mysql:///hb_01</property>        <property name="hibernate.connection.username">root</property>        <property name="hibernate.connection.password">root</property>        <!--实际操作数据库时是否显示SQL -->        <!--         <property name="hibernate.show_sql">true</property>         -->        <property name="hibernate.format_sql">true</property>        <!--将数据库schema的DDL导出到数据库 -->        <property name="hibernate.hbm2ddl.auto">update</property>        <!-- 以下定义实体类与数据库表的映像文件 -->        <mapping resource="com/qiujy/domain/Account.hbm.xml" />    </session-factory></hibernate-configuration>

之后,对一个真正的类Accout进行定义,定义如下:

/** * Filename: Account.java * Author: qiujy * Createtime: 2009-1-11 * Copyrights 2009 qiujy All rights reserved. * EMail: qjyong@gmail.com */package com.qiujy.domain;import java.util.Date;public class Account {    private Long id;                //对象标示符(OID)    private String loginname;           private String password;            private String email;               private Date registrationTime;      public Account(){}              //省略了getters和setters方法    public Long getId() {        return id;    }    public void setId(Long id) {        this.id = id;    }    public String getLoginname() {        return loginname;    }    public void setLoginname(String loginname) {        this.loginname = loginname;    }    public String getPassword() {        return password;    }    public void setPassword(String password) {        this.password = password;    }    public String getEmail() {        return email;    }    public void setEmail(String email) {        this.email = email;    }    public Date getRegistrationTime() {        return registrationTime;    }    public void setRegistrationTime(Date registrationTime) {        this.registrationTime = registrationTime;    }}

之后,映射持久化类到数据库表中。
Account.hbm.xml文件

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE hibernate-mapping PUBLIC        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><!-- Hibernate对象关系映射文件的根元素 --><hibernate-mapping>    <!-- class元素用来定义一个持久化类及对应的数据库表 -->    <class name="com.qiujy.domain.Account" table="account">        <!--         id元素:指定每个持久化类的唯一标识(即对象标识符OID)到数据库表主键字段的映射         name属性:指定持久化类的OID名        column属性:指定数据库表主键字段名。此属性的名和映射到数据库表的字段名相同时,可省略        type属性:指定主键映射时所使用的Hibernate类型名。此属性的类型为基本数据类型和String类型时,可省略        -->        <id name="id"  column="id" type="long">            <!-- generator元素:指定对象标识符的生成器名。                     native生成器把对象标识符值的生成工作交由底层数据库来完成          -->            <generator class="native" />        </id>        <!--             property元素:指定持久化类的每一个要映射到数据库表的字段的属性的信息。            name属性;指定持久化类中要映射到数据库表字段的属性名。            column属性:指定对应的表的字段名。此属性的名和映射到数据库表的字段名相同时,可省略            type属性:指定属性映射所使用的Hibernate类型名。此属性的类型为基本数据类型和String类型时,可省略            not-null属性:指定此属性映射到数据库表的字段值是否允许为值          -->        <property name="loginname" column="loginname" type="string" not-null="true"/>        <property name="password" column="password" type="string" not-null="true"/>        <property name="email" column="email" type="string"/>        <!-- 属性类型为Date类型的必须要明确指定使用的Hibernate类型名 -->        <property name="registrationTime" column="registration_time" type="timestamp"/>    </class></hibernate-mapping>

之后就用一个测试用例,利用Hibernate API进行持久化操作了!!!

/** * Filename: CreateAccountTest.java * Author: qiujy * Createtime: 2009-1-11 * Copyrights 2009 qiujy All rights reserved. * EMail: qjyong@gmail.com */import java.util.Date;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.cfg.Configuration;import com.qiujy.domain.Account;/** * 新增账号的测试 * @author qiujy */public class CreateAccountTest {    public static void main(String[] args) {        //根据hibernate的默认配置文件构建一个SessoinFactory实例        SessionFactory sessionFactory =             new Configuration().configure().buildSessionFactory();         //获取Session实例        Session session = sessionFactory.openSession();        //开启事务        session.beginTransaction();        //创建一个账号        Account acc = new Account();        acc.setLoginname("张三");        acc.setPassword("1234");        acc.setEmail("zs@test.com");        acc.setRegistrationTime(new Date());        //利用Session实例进行持久化操作        session.save(acc);        //提交事务        session.getTransaction().commit();         //关闭Session        session.close();    }}

下面是Hibernate 工作的过程
这里写图片描述

掌握持久化类的实例的状态及状态之间的转变,Session的使用与之有关

这里写图片描述

Hibernate 高级映射

01 集合映射
分别对set,list,bag 和map进行介绍
set
学生有很多爱好,hobbies ( type = “string” ), 可以在Student.hbm.xml中进行如下配置:

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE hibernate-mapping PUBLIC        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping>    <class name="com.qiujy.domain.Student" table="student">        <id name="id" column="id" type="long">            <generator class="native" />        </id>        <property name="name" not-null="true" />        <!--            set元素用来映射java.util.Set类型的属性               name属性:指定要映射的属性名               table属性:指定对应的数据库表名        -->        <set name="hobbies" table="student_hobby">            <!-- key子元素:指定集合属性对应的表的外键列 -->            <key column="student_id" />            <!-- element子元素:映射集合内的元素 -->            <element type="string" column="hobby_name" not-null="true" />        </set>    </class></hibernate-mapping>

同理,list

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE hibernate-mapping PUBLIC        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping>    <class name="com.qiujy.domain.Student" table="student">        <id name="id"  column="id" type="long">            <generator class="native" />        </id>        <property name="name" not-null="true"/><!--    list元素用来映射java.util.List类型的属性       name属性:指定要映射的属性名       table属性:指定对应的数据库表名--><list name="hobbies" table="student_hobby">    <!-- key元素:指定集合属性对应的表的外键列 -->    <key column="student_id" />    <!-- list-index元素:指定索引列 -->    <list-index column="posistion"/>    <!-- element元素:映射集合内的元素 -->    <element type="string" column="hobby_name" not-null="true"/></list>    </class></hibernate-mapping>

bag( 允许重复元素的无序集合,可以使用java.Util.Collection 或者java.util.List接口 来表示这种语义)
如student中有一个Collection<String> hobbies 字段。
对应的hbm.xml如下:

<bag name="hobbies" table="student_hobby">    <!-- key元素:指定集合属性对应的表的外键列 -->    <key column="student_id" />    <!-- element元素:映射集合内的元素 -->    <element type="string" column="hobby_name" not-null="true"/></bag>

映射map
private Map<Long,String> hobbies; //个人爱好

<map name="hobbies" table="student_hobby">    <!-- key元素:指定集合属性对应的表的外键列 -->    <key column="student_id" />    <!-- map-key元素:指定Map属性的键在对应表中的列 -->    <map-key column="hobby_id" type="long"/>    <!-- element元素:映射集合内的元素 -->    <element type="string" column="hobby_name" not-null="true"/></map>

排序集合与有序集合太多东西,具体可以看代码。

02 组件映射

1 组件类座位持久化类的单个属性

举个例子,在设计一个购物系统时,客户Customer需要有联系地址,还需要有送货地址,可以Customer中,有homeAddress类和deliverAddress类。
同时,数据库那么在对应的数据库中只设计单一Customer表。
映射关系可以写成如下:

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE hibernate-mapping PUBLIC        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping>    <class name="com.qiujy.domain.Customer" table="customer">        <id name="id"  column="id" type="long">            <generator class="native" />        </id>        <property name="loginname" not-null="true"/>        <property name="password" not-null="true"/>             <property name="email"/>        <!-- 用component元素映射组件类属性homeAddress -->        <component name="homeAddress" class="com.qiujy.domain.Address">            <!-- 用property映射组件类的每个属性 -->            <property name="province" column="home_province"/>            <property name="city" column="home_city"/>            <property name="detail" column="home_detail"/>            <property name="zipcode" column="home_zipcode"/>            <property name="telephone" column="home_telephone"/>            <property name="mobilephone" column="home_mobilephone"/>        </component>        <!-- 用component元素映射组件类属性deliverAddress -->        <component name="deliverAddress" class="com.qiujy.domain.Address">            <property name="province" column="deliver_province"/>            <property name="city" column="deliver_city"/>            <property name="detail" column="deliver_detail"/>            <property name="zipcode" column="deliver_zipcode"/>            <property name="telephone" column="deliver_telephone"/>            <property name="mobilephone" column="deliver_mobilephone"/>        </component>    </class></hibernate-mapping>

第二种,组件类作为持久化类的集合属性
例如,一个相册里有很多照片,Album, Photo,持久化类和组件类的区别是,前者有对象标示符,后者没有。
映射文件可以为:

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE hibernate-mapping PUBLIC        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping>    <!-- 映射持久化类 -->    <class name="com.qiujy.domain.Album" table="album">        <!-- 映射对象标识符 -->        <id name="id"  column="id" type="long">            <!-- 指定对象标识符生成器 -->            <generator class="native" />        </id>        <!-- 用property映射每个普通属性 -->        <property name="title"/>        <property name="description"/>              <property name="creationTime" column="creation_time"/>        <!-- 用bag来映射List集合属性 -->        <bag name="photos" table="photo">            <!-- key元素:指定集合属性对应的表的外键列 -->            <key column="album_id" not-null="true" />            <!-- composite-element元素:映射集合里的元素                    class属性:指定集合里的元素的类类型            -->            <composite-element class="com.qiujy.domain.Photo">                <!-- 用property映射每个普通属性 -->                <property name="name" />                <property name="filePath" column="file_path" />                <property name="description" />                <property name="width" />                <property name="height" />            </composite-element>        </bag>    </class></hibernate-mapping>

详情见: hb_03_component.

3 组件类作为持久化对象的对象标识符属性
比如User这张表,把first_name和last_name 两个字段作为联合主键,要映射到持久化类的话,必须把这两个字段定义到一个组件类:UserOid,用来表示复合对象标识符。
同时,这个组件类,必须实现Serializable接口和重写hashcode()和equals()方法。
详情见: hb_03_componentOid.

03关联关系映射
1. 单向多对一
多对一:多个员工属于同一部门。Department类与Employee类
可以见hb_04_many2one_unidirectional.
2. 单向一对一
每一个中国公民,都有一张身份证,单向的意思是:只考虑从公民这一端找到它的身份证,而身份证这一端不知道公民的存在。
有两种方式。。。
一 基于唯一外键
公民把身份证的主键作为外键,并且这个外键是唯一的。
在citizen.hbm.xml中,配置如下:

<hibernate-mapping>  <!-- 映射持久化类 -->    <class name="com.qiujy.domain.Citizen" table="citizen">        <!-- 映射对象标识符 -->        <id name="id" column="id" type="long">            <generator class="native" />        </id>        <!-- 映射普通属性 -->        <property name="name"/>        <property name="gender"/>        <!-- 用many-to-one元素映射基于唯一外键的一对一关联             name属性:指定关联的属性名             column属性:指定此关联属性在数据库表中的外键字段名             unique属性:指定值为“true”来限制多端的多重性为一             cascade属性:用来指定两个对象之间的操作联动关系         -->        <many-to-one name="idCard"                             column="idcard_id"                             unique="true"                            cascade="all"/>    </class></hibernate-mapping>

详情可见:hb_04_one2one_unidirectional_fk
二:基于主键
公民的id就是idcard的id,这种方式叫做基于主键的单向一对一。

citizen.hb.xml<hibernate-mapping>  <!-- 映射持久化类 -->    <class name="com.qiujy.domain.Citizen" table="citizen">        <!-- 映射对象标识符 -->        <id name="id" column="id">             <!-- foreign表示使用另外一个相关联的对象(用property属性指定的那个属性)的标识符 -->             <generator class="foreign">         <param name="property">idCard</param>       </generator>        </id>        <!-- 映射普通属性 -->        <property name="name"/>        <property name="gender"/>        <!-- 用one-to-one元素映射基于主键的一对一关联             name属性:指定关联的属性名             constrained属性:true表示该类对应的数据库表和被关联的对象所对应的数据库表之间,通过一个外键引用对主键进行约束。         -->        <one-to-one name="idCard" constrained="true"/>    </class></hibernate-mapping>

详情可见:hb_04_one2one_unidirectional_pk

  1. 双向一对一

也有两种实现方式,基于唯一外键和基于主键的方式。
基于唯一外键的一对一双向关联,其外键可以存放在任意一端,在需要存放外键的一端,使用Many-to-one元素来映射关联对象,同时添加unique=true属性; 没有存放外键的那一端需要使用one-to-one元素,此时还需要通过property-ref属性来指定这一端只是关联另外一端的属性的反向引用,并不需要额外的列或者外键约束,由Hibernate管理这个关系。
例子:hb_04_one2one_bidirecrtional_fk.
基于主键的双向一对一
hb_04_one2one_bidirecrtional_pk.

  1. 单向一对多
    一个账号可以有多个订单(set<Order>),但是订单上没有写是哪个账号信息
    hb_04_many2one_unidirecrtional

5.多向一对多(多向多对一)
一个账号可以有多个订单(set<Order>),订单上有写是哪个账号信息account_id
hb_04_one2many_bidirecrtional

  1. 单向多对多
    大学学生和课程之间的关联就是单向多对多关联。 课程不知道有哪些学生选了。
    在关系模型中,是无法直接表达两个表之间的多对多关联的,需要有一个中间连接表。在连接表中用外键关联到两个表中。
    hb_04_many2many_unidirecrtional

  2. 双向多对多
    大学学生和课程之间的关联就是单向多对多关联。 课程知道有哪些学生选了。
    同样,需要一个中间表。

hb_04_many2many_bidirecrtional

04 继承关系映射

1:整体继承层次一张表

singer 父类有两个子类:SingleSinger, Bands. 全部放在一张表,需要一个鉴别字段,判断是SingleSinger还是Bands.
2:每个子类一个表
父类也有表,子类也有表,子类的字段都是独有的字段。
3:每一个具体类一个表。
上面父类的通用字段每一个表中都有。父类没有表。
hb_05_inheritancemapping_1
hb_05_inheritancemapping_2
hb_05_inheritancemapping_3

源代码地址如下:
01-03
http://download.csdn.net/detail/chengyangyy/9119523
04
http://download.csdn.net/detail/chengyangyy/9119537
05
http://download.csdn.net/detail/chengyangyy/9119545

0 0
原创粉丝点击