hibernate简介

一:hibernate 是什么?
1: hibernate 是对JDBC进行了封装,负责对象持久化,位于中间层,在应用程序和数据库之间起到了桥梁作用的一种映射工具。
二:为什么使用hibernate?
1:使用hibernate,应用程序层就可以专注于业务逻辑的实现,只需要知道怎么使用hibernate 所提供的接口,而不用知道具体实现的细节。
2:封装了JDBC之后,就可以连接数据库时减少代码的冗余。
3:直接用映射文件,可以方便的实现与不同数据库连接。
三:hibernate 的使用
1:配置文件
(1):全局配置文件:hibernate.cfg.xml: 主要用来实现整个应用程序中使用的数据库,以及这个应用程序中的对象关系映射。
例子:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN" "/home/soft01/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.driver_class"> com.mysql.jdbc.Driver
</property> 指定数据库的驱动程序
<property name="connection.url">jdbc:mysql://127.0.0.1:3306/test
</property> 指定连接数据库的URL
<property name="connection.username">root
</property> 联结数据库的用户名,
<property name="connection.password">831022</property> 密码
<propertyname="dialect">org.hibernate.dialect.MySQLDialect
</property> 指定数据库使用的方言,本质上就是hibernate API 中的一个用来标示不同数据库的接口
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
用来在控制台输出hibernate 产生的SQL语句
<property name="format_sql">true</property> 对SQL语句进行format

<mapping 对象关系映射
resource="com/allanlxf/hibernate/basic/entity/Student.hbm.xml" />
</session-factory>
</hibernate-configuration>
*******************************************************************
使用注意:
◆任何一个应用程序的全局配置文件名字都是hibernate.cfg.xml,并且默认放在工程的根目录下,也就是与源程序代码同级。每一个工程只能有一个这样的全局配置文件,如果想要使用别的位置的配置文件,调用configuration 的有参的构造方法,指定这个配置文件的位置。
如果不是用工具编写的,那么这个配置文件应该跟.classpath放在一块。
(2):对象---关系映射文件:
◆命名规则:className.hbm.xml
◆ORM的具体细节
Class to Table
Identifier to PK
Properties to columns
java type vs database type
◆作用及应用:用来使实体类对象(class)与数据库的表产生一一对应关系
<?xml version="1.0" encoding="gbk"?>

<!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.allanlxf.hibernate.basic.entity.Student" table="student">
<id name="id" column="id" type="integer">
<generator class="assigned" />
</id>
<property name="name" column="name" type="string" />
<property name="email" column="email" type="string" />
<property name="birthday" column="birthday" type="date" />
<property name="address" column="address" type="string" />
</class>
</hibernate-mapping>
*******************************************************************
◆使用注意事项:
(1)建表的时候一般会使用一个根业务逻辑没有关系的字段作为这个表的主键。
(2)这种映射文件可以一个类一个,也可以把多个类的映射关系去不写在一个对象关系映射文件中,但是推荐使用前者,因为这样在开发的过程中便于区分管理。
(3)该文件最好同实体的类文件放在一起.
*******************************************************************
2:hibernate 接口的使用六步曲
(1)Configuration config = new Configuration();
//根据默认的位置hibernate的配置文件,创建一个configuration对象

(2)SessionFactory factory =config.configure().buildSessionFactory();
(3)Session session=factory.openSession();//应用程序与数据打交道的一个对象
(4)Transaction trans = session.beginTransaction();
(5)通过session对象操作数据库
    session.delete();
    session.save()
    session.update()
    session.load();
    session.find();
(6)trans.commit();
(7)关闭资源
*******************************************************************
◆使用注意:
(1)在创建SessionFactory对象后,如果再修改配置文件,那么后边的操作不回被影响,因为创建SessionFactory对象的时候已经把原来的配置文件信息加载到sessionfactory的缓存中了,sessionfactory是一个重量级的对象,一般在产生一个之后不要随便销毁,因为创建和销毁一个sessionfactory 对象需要消耗很多的资源
(2)session是一个轻量级的对象,通常一个session对象只在一个事务中使用,适用完就关闭,当然开始一个事务的时候也要先创建一个这样的对象。
◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆
话题二 DB中主键的生成规则
学习方向:区分并牢记几种经常使用的ID产生方式

一:映射文件中的体现:
<id name="id" column="id" type="integer">
<generator class="assigned" />
</id>
oracle: sequence, seqhilo,hilo,increment ,native
mysql: identity, increment ,hilo,native
1:Assigned: 由用户自己指定一个与业务逻辑相关的,如果不加generator,那么系统默认由用户指定,这种情况比较少,最好主键不要跟业务逻辑相关
2:Native:更具有通用性,Mysql.sqlserver: identity              
            Oracle.db2: sequence
缺点:Oracle所有的表都使用一个sequence
3:Identity:
(1):使用规则:
底层的数据库生成标示赋,
(2):前提条件:底层的数据库支持自动增长字段类型
4:Sequence:
(1)使用方法:
为每一个表的ID创建一个单独的序列,然后从这个序列中获取自动增加的标识符。赋值给主键。一旦创建就可以把它当作一个类对象一样,获得当前或下一个值student_id_seq.curval/student_id_seq.nextval
(2)前提条件:数据库支持序列。oracle支持,mysql不支持
Create sequence student_id_seq by 2 start with 1
Create table student(id number primary key ,name varchar2(20));
Insert into student values(student_id_seq.curval,”xuzheng”);
5:Hilo:
根据high/low算法来生成ID,hibernate 根据特定表的字段作为high值,在默认的情况下选用hibernate_unique_hi
6:increment:
hibernate以自动增长的方式生成标示符,每次增量为1
◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆
话题三:关联关系 
学习方向:重点理解现实关联关系的抽象化,

一:一对一关系:
1:第一种实现方式是主键关联,本质就是一个表主键的产生要依赖另外一个表的主键。
◆只有被参照的对象存在了,才能创建参照对象
例子:
表一:create table car_pk (
id number(10,0) not null,
name varchar2(15),
primary key (id)
);
表二:create table engine_pk (
id number(10,0) not null,
model varchar2(20),
primary key (id)
);
alter table engine_pk
add constraint fk_engine_car_pk
foreign key (id)
references car_pk(id);
被参照方的配置文件
<hibernate-mapping package=" o2o.entity">
<class name="Car" table="car_pk">
<id name="id" column="id" type="integer">
<generator class="native" />
</id>
<property name="name" column="name" type="string" length="15" not-null="false"/>
(自己-to -别人)
<one-to-one name="engine" class="Engine" cascade="all"/>
</class>
</hibernate-mapping>
========================
表二的配置文件
<hibernate-mapping  package=" o2o.entity">
<class name="Engine"  table="engine_pk">
<id name="id" column="id" type="integer">
<generator class="foreign"> //参照者的id产生方式用foreign
<param name="property">car</param>//被参照者
</generator>
</id>
<property name="model" column="model" type="string" length="20"/>
<one-to-one name="car" class="Car" constrained="true" foreign-key="fk_engine_car_pk"/>
</class>

2:第二种实现方式是外键关联
例子:
表一:create table car_fk (
id number(10,0) not null,
name varchar2(15) not null,
primary key (id)
);

表二:create table engine_fk (
id number(10,0) not null,
carid number(10,0) unique,
primary key (id)
);
alter table engine_fk
add constraint fk_engine_car_fk
foreign key (carid)
references car_fk(id);
被参照方的配置文件
<hibernate-mapping package=" o2o.entity">
<class name="Car" table="car_fk">
<id name="id" column="id" type="integer">
<generator class="native" />
</id>
<property name="name" column="name" type="string" length="15" not-null="true"/>
<one-to-one  name="engine" class="Engine" property-ref="car" cascade="save-update"/>
//casecade放在被参照方。标示保存或者更新当前对象时,级联更改关联对象。默认为none 。
</class>
</hibernate-mapping>

参照方的配置文件
<hibernate-mapping package=" o2o.entity">
<class name="Engine" table="engine_fk">
<id name="id" column="id" type="integer">
<generator class="native"/>
</id>
<many-to-one  name="car" class="Car" column="carid" unique="true" foreign-key ="fk_engine_car_fk"/>
</class>
</hibernate-mapping>
二:一对多:
1:使用规则:
(1)建单方表时只保留自己的属性
(2)建多那方的表的时候,加些order_id作为自己的外键
(3)一对多、双向关联时,一方要指定inverse=“true”,即表示多方方拥有主控制权,一方的关联只是多方关联的一个镜像。即hibernate 检测到一方和多方均发生变化的时候,仅按照多方对象状态变化来同步更新数据库。
2:关联方向
(1)单向关联:在单的一方不需要设置存放多方的集合属性。
(2)双向关联:在单的一方需要有一个set属性来存储多的一方
3:双向关联例子
create table ec_order (
id number(10,0) not null,
primary key (id)
);
create table ec_item (
id number(10,0) not null,
orderid number(10,0) not null,
primary key (id)
);
alter table ec_item
add constraint fk_item_order
foreign key (orderid)
references ec_order(id);
一方配置文件:
<hibernate-mapping package=" o2m.entity">
<class name="Order" table="ec_order">
<id name="id" column="id" type="integer">
<generator class="native" />
</id>
<set name="items" cascade="all-delete-orphan" inverse="true">
<key column="orderid" />
<one-to-many class="Item" />
</set>
</class>
</hibernate-mapping>
多方配置文件
<hibernate-mapping package=" o2m.entity">
<class name="Item" table="ec_item">
<id name="id" column="id" type="integer">
<generator class="native" />
</id>
<many-to-one name="order" column="orderid" not-null="true" foreign-key="fk_item_order"/>
</class>
</hibernate-mapping>
三:多对多关系:
多对多只有双向关联。
多对多引用的是集合对象
需要用第三张表来维持多对多关系。
写配置文件的时候many-to-many标签要放在set标签内, <key column =””>总是和本类的主键id对应
<column=””>总是和关联类的主键id相对应
比如在student的配置文件内:
<set name="courses" table="ENROLLMENTS" inverse="true"  cascade="save-update">
<key column="sid"/>
<many-to-many class="Course" column="cid">
</many-to-many>
</set>
注意:两个配置文件的cascade都设置为save-updat。
添加关联关系时注意:
在多对多关系中,双方都有控制权(即双方都没有设置inverse=true)的时候,则双方都要把级联关系反映到数据库中去,引发的状况是执行了两条完全一样的sql语句,违反了数据库的主键唯一性约束,
☆代码见下:
应用程序中:
Stu.getCourses().add(course);
Course.getStudents().add(stu);
解决办法有两种:
在上述语句中任选一条执行即可
在某一方的配置文件中设置inverse=”true”,然后让没有设置的一方进行操作。
create table students(
sid integer primary key,
name varchar2(32) not null,
sex varchar2(8),
birthday date,
edu varchar2(64),
cardno varchar2(16) not null unique
);

create table courses(
cid integer primary key,
name varchar2(32) not null unique,
desc varchar2(256)
);
create table enrollments(
cid integer references courses(cid),
sid integer references students(sid),
constraint enrollments_pk primary key(cid, sid)
);
<hibernate-mapping package="hbn.many2many">
<class name="Student" table="STUDENTS">
<id name="sid" unsaved-value="null">
<generator class="native">
</generator>
</id>
<property name="name"/>
<property name="sex"/>
<property name="birthday"/>
<property name="edu"/>
<property name="cardno" unique="true" not-null="true"/>
<set name="courses" table="ENROLLMENTS" inverse="true" cascade="save-update">
<key column="sid"/>
<many-to-many class="Course" column="cid"></many-to-many>
</set>
</class>

<class name="Course" table="COURSES">
<id name="cid" unsaved-value="null">
<generator class="native">
</generator>
</id>
<property name="name" unique="true" not-null="true"></property>
<property name="desc"></property>
<set name="students" table="ENROLLMENTS" cascade="save-update">
<key column="cid"></key>
<many-to-many class="Student" column="sid"></many-to-many>
</set>
</class>
</hibernate-mapping>
======================
四:组合映射
Component Mapping包含的元素又是另外一个类(表)
两个类建一个表,主中的一个属性是多个对应表的多个字段的组合
create table account(
id integer primary key,
name varchar2(32) not null,
balance double not null,
street varchar2(32),
city varchar2(32),
province varchar2(32),
zip varchar2(16)
);===================================================================================================
<hibernate-mapping package="hbn.valuetype.component">
<class name="Account" table="ACCOUNT">
<id name="id" unsaved-value="null">
<generator class="hilo">
<param name="table">pk_table</param>
<param name="column">id_value</param>
</generator>
</id>
<property name="name"></property>
<property name="balance"></property>
<component name="addr">
<property name="street"></property>
<property name="city"></property>
<property name="province"/>
<property name="zip"/>
</component>
</class>

</hibernate-mapping>
===================================================================================================
五:继承关系的映射
table-per-concreate-class 一个应用建一张表
即父类分别出现在子类中,而不单独建一张表
--------不需要多态映射查询时适用,操作只对单表
缺点:修改父类的时候,其具体的子类所对应的表字段也都要随之改变;
不支持多态,一个支持多角色,则保持数据完整性很困难。
优点:简单易用,因为一个具体类只存在一张表中。
◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆
table-per-class-hierarchy 将整个层次写一张表
--------需要多态且子类属性较少的时候适用
缺点:会有大量的null字段,并且子类的属性不能有非空限制。
优点:只使用一个表格,查询时只需一次sql
◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆
table-per-subclass 一个类写一张表,包括父类
--------需要多态且子类属性叫多的时候适用
缺点:有太多的数据表,每张表对应一个类(在多对多关系中还需要用一张额外的表去维护关系);
查询的时候要多表查询,读取数据的时间较长。解决办法是将数据库中的数据组织到不同的磁盘面上(假定每一个磁头都是独立的操作)。这种模式的读写性能问题将会得到一定的缓解。
优点:很好的遵循了面向对象的思想,支持多态,只需要在合适的表中拥有角色所需要的字段即可。修改继承树中的父类和子类都很容易,因为只需要修改一个类或一个表。

话题四:小知识点

1:延迟加载lazy=”true”
本质:当调用student.load()方法时,不会立即把数据库中的内容全部加载到内存中,仅仅初始化了OID属性,当第一次使用这个实例的时候,才会把所有的内容加载到内存中。提高效率
2:Insert=false: 在往表中插入的时候,忽略这这个字段,缺省值=true
3: update=false:修改的时候,忽略这个字段,缺省值=true.
源:http://bbs.tarena.com.cn/viewthread.php?tid=133157
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值