Hibernate 培训资料
1. Hibernate简介
Hibernate是非常流行的对象-关系映射工具。
2. 什么是ORM映射
ORM(Object Relational Mapping)简单的说,就是对象与关系的映射,对于实际应用来讲,对象一般指面向对象中的对象,关系指关系型数据库,对于我们具体的项目来说,就是将java中的对象与关系型数据库(oracle,mysql)中的表联系起来 。Hibernate是很强大的工具,当我们将建立联系的工作交给它后,就可以专注于与java中的对象打交道,而不需要知道它代表的是哪些表。
3. POJO(用来映射数据库中的表,构建我们的持久化层)
一个典型的POJO
public class Person{
private long id;
private String name;
public void setId(BigDecimal value) {
this.id = value;
}
public BigDecimal getId() {
return this.id;
}
public void setName(String value) {
this.name = value;
}
public String getName() {
return this.name;
}
}
表面上看来,一个POJO与一个普通的JavaBean没有什么区别,我们需要了解的是如何让POJO和一个表建立联系。
4. 建立联系的桥梁,映射文件XML。
一个典型的映射文件Person.hbm.xml(注意他的命名方式,一般是类名+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 schema="SCOTT" package="mapping">
<class name="Person" table="PERSON">
<id name="id" type="long" unsaved-value="null">
<column name="ID" not-null="true" index="SYS_C004143"/>
<generator class="native"/>
</id>
<property name="name" type="string" column="NAME"/>
</class>
</hibernate-mapping>
注意红线部分代表了Pojo对应的是那张表。
一般来说映射文件放在和Pojo同一个包
5. 和数据库的连接
Hibernate配置文件,可以采用xml或者property文件。
一个典型的配置文件
<?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">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.username">toposs</property>
<property name="hibernate.connection.password">toposs</property>
<property name="hibernate.dialect">
org.hibernate.dialect.Oracle9Dialect
</property>
<property name="hibernate.connection.url">
jdbc:oracle:thin:@172.16.1.3:1521:orcl
</property>
<property name="hibernate.connection.driver_class">
oracle.jdbc.driver.OracleDriver
</property>
</session-factory>
</hibernate-configuration>
6. Hibernate在Eclipse中快速应用
6.1 新建一个工程,将Hibernate3.jar和你需要的数据库驱动添加到工程path中
6.2 在数据库中新建一个名为person的表。
6.3 在工程的默认package下建立一个POJO,Person类与表person对应。
public class Person{
private long id;
private String name;
public void setId(long value) {
this.id = value;
}
public long getId() {
return this.id;
}
public void setName(String value) {
this.name = value;
}
public String getName() {
return this.name;
}
}
6.4 现在我们来建立一个xml的映射文件(Person.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="Person" table="PERSON">
<id name="id" type="long" unsaved-value="0">
<column name="ID" not-null="true"/>
<generator class="increment"/>
</id>
<property name="name" type="string" column="NAME"/>
</class>
</hibernate-mapping>
6.5 建立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">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.username">scott</property>
<property name="hibernate.connection.password">tiger</property>
<property name="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</property>
<property name="hibernate.connection.url">jdbc:oracle:thin:@172.16.1.2:1521:rsora</property>
<property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="hiberante.show_sql">true</property>
<mapping resource="Person.hbm.xml" />
</session-factory>
</hibernate-configuration>
注意红线的部分将mapping文件写到resource中,如果有多个文件,要写多个文件,文件的路径是对于根目录的绝对路径
6.6 项目结构图
6.7 所有准备工作都已经做好了,下面在Person中建立一个main方法,我们做一个简单的插入数据库的工作
6.7.1 Main函数的代码
Public static main(String[] args){
Configuration config=new Configuration().configure();
SessionFactory factory=config.buildSessionFactory();
Session session=factory.openSession();
Transaction tran=session.beginTransaction();
Person p=new Person();
p.setName("test");
session.save(p);
tran.commit();
session.close();
}
6.7.2 点击Run As Java Application,运行这个main函数
6.7.3 然后查看数据库
我们发现数据库已经新增加了一条记录
7. 最常见的关联关系,一对多关联。
7.1 用父子关系说明一对多(多对一关联)
在实际应用中,很少有一个表是独立的,大部分情况是表和表之间是有关联关系的,其中最常见的是一对多(多对一关联)。
父亲和儿子是典型的一对多关系,一个父亲有多个儿子,儿子只有一个父亲。在这个关系中,父亲是一方,儿子是多方。
7.2 在数据库中建立父子关系。
建表的sql语句:
CREATE TABLE father (
Father_id INTEGER NOT NULL,
name VARCHAR(10) NULL,
PRIMARY KEY (father_id) );
CREATE TABLE son (
Son_id INTEGER NOT NULL,
Son_name VARCHAR(10) NULL,
Father_ID INTEGER NULL
PRIMARY KEY (son_id),
FOREIGN KEY (father_id)
REFERENCES father
);
7.3 建立的表的结构
儿子的表
父亲的表
7.4 建立POJO
同样在我们的工程的defalt package下面新建类Father和Son。
7.4.1 Father类
public class Father {
private long fid;
private String name;
private Set sons = new HashSet();
public long getFid() {
return fid;
}
public void setFid(long fid) {
this.fid = fid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set getSons() {
return sons;
}
public void setSons(Set sons) {
this.sons = sons;
}
}
7.4.2 Son类
public class Son {
private long sid;
private String name;
private Father father;
public Father getFather() {
return father;
}
public void setFather(Father father) {
this.father = father;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getSid() {
return sid;
}
public void setSid(long sid) {
this.sid = sid;
}
}
7.5 注意到什么不同了吗,在Father类里多了个Set,Son类中多了个Father成员变量。
这里我们做的是双向关系,也可以做单向关系只在一方做关联。
7.6 映射文件的写法
7.6.1 Father.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="Father" table="father">
<id name="fid" type="long" unsaved-value="0">
<column name="father_ID" not-null="true" />
<generator class="increment" />
</id>
<property name="name" type="string" column="NAME" />
<set name="sons" table="son" cascade="save-update">
<key column="father_id"></key>
<one-to-many class="Son" />
</set>
</class>
</hibernate-mapping>
7.6.2 Son.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="Son" table="son">
<id name="sid" type="long" unsaved-value="0">
<column name="son_id" not-null="true" />
<generator class="increment" />
</id>
<property name="name" type="string" column="son_NAME" />
<many-to-one
name="father"
class="Father"
cascade="none"
outer-join="auto"
update="true"
insert="true"
column="father_id"
/>
</class>
</hibernate-mapping>
7.6.3 看到红线的部分是对应的关联关系的写法,其中没项具体的含义我们留到后面解释
7.7 不要忘了在配置文件中添加我们的映射文件。
<?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">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.username">scott</property>
<property name="hibernate.connection.password">tiger</property>
<property name="hibernate.dialect">
org.hibernate.dialect.Oracle9Dialect
</property>
<property name="hibernate.connection.url">
jdbc:oracle:thin:@172.16.1.2:1521:rsora
</property>
<property name="hibernate.connection.driver_class">
oracle.jdbc.driver.OracleDriver
</property>
<property name="hiberante.show_sql">true</property>
<mapping resource="Father.hbm.xml" />
<mapping resource="Person.hbm.xml" />
<mapping resource="Son.hbm.xml" />
</session-factory>
</hibernate-configuration>
7.8 所有准备工作做好了,下面在原来的Main函数中添加代码
public static void main(String[] args) {
Configuration config=new Configuration().configure();
SessionFactory factory=config.buildSessionFactory();
Session session=factory.openSession();
Transaction tran=session.beginTransaction();
Father father=new Father();
father.setName("fanta");
Son son1=new Son();
Son son2=new Son();
son1.setName("son1");
son2.setName("son2");
father.getSons().add(son1);
father.getSons().add(son2);
session.save(father);
tran.commit();
session.close();
}
7.9 点击Run As Java Application,运行这个main函数,看看数据库发生了什么
7.10 Father表插入了1条记录,son表插入了2条记录,然后回头看看我们的代码做了些什么
……
Father father=new Father();
father.setName("fanta");
Son son1=new Son();
Son son2=new Son();
son1.setName("son1");
son2.setName("son2");
father.getSons().add(son1);
father.getSons().add(son2);
session.save(father);
……
我们看到显式的调用存储就只有红线的这句话,只存了father,并没有存son,那为什么数据库会有son的记录呢,这就是Hibernate帮我们做的事情,回忆一下Father的POJO里有个Set吗
public class Father {
private long fid;
private String name;
private Set sons = new HashSet();
……
因为我们将Set中添加了东西(增加了2个儿子),所以Hibernate在存储Father的时候 “顺便”(J)将他的2个儿子也插入到数据库中了。
8. 常用的一对多和多对一映射选项
8.1 多对一设置
<many-to-one
name="propertyName" (1)
column="column_name" (2)
class="ClassName" (3)
cascade="cascade_style" (4)
unique="true|false" (5)
not-null="true|false" (6)
lazy="true|proxy|false" (7)
/>
(1) name: 属性名。
(2) column (可选): 外间字段名。它也可以通过嵌套的 <column>元素指定。
(3) class (可选 - 默认是通过反射得到属性类型): 关联的类的名字。
(4) cascade(级联) (可选): 指明哪些操作会从父对象级联到关联的对象。
(5) unique (可选): 使用DDL为外键字段生成一个唯一约束。此外, 这也可以用作property-ref的目标属性。这使关联同时具有 一对一的效果。
(6) not-null (可选): 使用DDL为外键字段生成一个非空约束。
(7) lazy (可选 - 默认为 proxy): 默认情况下,单点关联是经过代理的。lazy="true"指定此属性应该在实例变量第一次被访问时应该延迟抓取(fetche lazily)(需要运行时字节码的增强)。 lazy="false"指定此关联总是被预先抓取。
8.2 一对多配置
<set
name="propertyName" (1)
table="table_name" (2)
lazy="true|false" (3)
inverse="true|false" (4)
cascade="all|none|save-update|delete|all-delete-orphan" (5)
order-by="column_name asc|desc" (6)
>
<key column=”ColumnName”/>
<one-to-many Class=”ClassName”/>
</set>
(1) name 集合属性的名称
(2) table (可选——默认为属性的名称)这个集合表的名称(不能在一对多的关联关系 中使用)
(3) lazy (可选--默认为true) 可以用来关闭延迟加载,指定一直使用预先抓取(对数组 不适用)
(4) inverse (可选——默认为false) 标记这个集合作为双向关联关系中的方向一端。
(5) cascade (可选——默认为none) 让操作级联到子实体
(6) order-by (可选) 指定表的字段(一个或几个)再加上asc或者desc(可选), 定义Set的迭代顺序