WEB开发网
开发学院WEB开发Jsp 初学者想学Hibernate,初级基础教程 阅读

初学者想学Hibernate,初级基础教程

 2008-01-05 20:32:25 来源:WEB开发网   
核心提示:Hibernate理论基础 1. 什么是hibernate? 2. hibernate的知识内容 3. 什么是对象持久化?对象持久化有什么用?(解决的问题) 4. 如何对象持久化? 5. 如何用数据库的方法做对象持久化? 6. ORM(对象关系映射)是什么?有什么作用? 7. ORM从对象到表所要考虑的问题 8. 什么

Hibernate理论基础

1. 什么是hibernate?
2. hibernate的知识内容
3. 什么是对象持久化?对象持久化有什么用?(解决的问题)
4. 如何对象持久化?
5. 如何用数据库的方法做对象持久化?
6. ORM(对象关系映射)是什么?有什么作用?
7. ORM从对象到表所要考虑的问题
8. 什么是ORM框架?有什么用?
9. 使用hibernate的方法做对象持久化的工作,程序员应该怎么做?
10. hibernate有什么用?
11. 程序员和hibernate的整体工作流程

什么是hibernate:

持久化的框架,属于设计方面的内容,类库,用来做对象持久化的,什么是对象持久化呢?

Hibernate的知识内容:

语法部分(类库)

程序设计思想,也就是持久层的设计

什么是对象持久化?对象持久化有什么用?(解决的问题):

发现问题:

程序设计的架构: 表现层—业务层—持久层—数据库层,其中表现层和业务层是JVM来执行,应用程序会产生许多的对象,假如断电了,对象就消失了,也就是说在内存中的对象是不稳定的,状态不能持久

发现问题:

将一个对象从A电脑复制到B电脑,如何做到呢?

那么有三种方法解决上面的问题:
1. 序列化: 通过网络传递,或者硬盘共享
2. 存储到数据库中,谁想用,从数据库中拿
3. EJB Entity Bean(实体Bean)

序列化的方法比较死板:假如当一个对象的结构比较复杂的时候,我们这时只需要一部分内容,没有办法,只能整个写入到文件,整个读取
序列化的缺点: 不能检索,不能分离一个对象,不方便共享
所以说第一种方法只能用于做临时的持久化,简单的传输,但不适合复杂的持久化工作

第二种方法(数据库持久化):检索方便,分布式共享,永久数据

总结:
什么是对象持久化: 对象持久化就是把内存中的对象永久的保存起来,保护对象的状态,方便使用
对象持久化有什么用: 1.解决掉电的问题 2.共享方便 3.保证对象安全检索方便

如何对象持久化:
1. 对象序列化
2. 数据库(JDBC,EJB,Hibernate)

如何用数据库的方法做对象持久化:
1. JDBC
发现问题: 需要做大量的工作,难度大
2. EJB
使用的是其中的一个功能来做持久化,解决了使用JDBC方法的的大量工作的问题
发现问题: EJB是重量级的组件,要使用它,有两个问题 1.成本 2.性能

发现问题: 以上两种方式还有个共同的问题,对象不是简单存储在数据库中的,比如多态的特点就不能处理 A b=new B(); B为A的子类

3. Hibernate
解决了以上的所有问题,作用:1.不用做大量的工作 2.移植性能好 3.提高了代码的质量,简单 4.检索共享重用成本调试

ORM(对象关系映射)是什么?有什么作用?
发现问题:
java中的对象的属性类型和数据库中的字段类型是不一样的,那么如何来存储java中的对象呢?这就需要做对象关系的映射,也就是ORM
什么是ORM: 将内存中的对象和数据库做转化,这样就实现了java与数据库之间的访问等功能

ORM从对象到表所要考虑的问题:
Orm的复杂问题:
1. 数据库如何保证对象的唯一性:在内存中,两个对象属性值都一样,但是内存地址不一样,可以做区分,但是在数据库中如何分辨呢?
2. 继续关系如何转化
3. 集合如何映射呢?

什么是ORM框架?有什么用?
就是一个类库,通过这个类库完成持久化层的设计

使用hibernate的方法做对象持久化的工作,程序员应该怎么做?
1. 将ORM方案定下来,就是类到数据库的转化 2.利用hibernate生成代码
hibernate有什么用?
1. 完成jdbc的代码
2. 治理持久化对象的状态
3. 提供一个查询的API

程序员和hibernate的整体工作流程
程序员:
1. 设计ORM方案
2. 写配置文件
3. 调用Hibernate的API,向Hibernate发出命令
hibernate:
4. 读配置文件
5. 生成jdbc代码
6. 执行

Hibernate简单实例
Hibernate语法:
作用: 数据库的增删改查 HQL面向对象的查询语句

大致步骤:
1. 设置环境 类库
2. 定义映射
A 定义映射的实体po
B 建立数据库表
C 写xml配置文件(表,数据库)
3. 调用Hibernate API
A 治理po的状态(增删改,恢复po状态)
B 检索(查询)

Hibernate第一个简单的实例: 引例(frisHbn包)
1. 设置环境
hibernate配置环境需要的资源
Hibernate的jar包: lib.zip dtd.zip: dtd.zip可以不设置
2. 定义映射
建立项目:
bussiness包: entity包 Biz包业务
client包: 测试
util包: 工具

先写持久化类: 以花为实体,建立花类,并且建立数据库表
/**
* 建表语句:
* CREATE TABLE T_FRUIT(
FID NUMBER(10) PRIMARY KEY,

NAME VARCHAR(20) NOT NULL,
COMMENTS VARCHAR(50),
PRICE NUMBER(5) NOT NULL
);
*/
package YUChen.fristHbn.business.entity;
//持久化类(花类),注重因为采用的是hilo的方式获得id,所以需要有setid的方法
public class Fruit {

private Integer fid;//hibernate中的id不能识别int
private String name;
private String comments;
private int price;

public Fruit() {
super();
}

public Fruit(String name, String comments, int price) {
super();
this.name = name;
this.comments = comments;
this.price = price;
}

public String getComments() {
return comments;
}
public void setComments(String comments) {
this.comments = comments;
}

public Integer getFid() {
return fid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}

public void setFid(Integer fid) {
this.fid = fid;
}

}

使用hilo的方式获得id:
建表语句:
CREATE TABLE T_HILO(HILO_ID NUMBER(10));
INSERT INTO T_HILO VALUES(1);

写hibernate的连接数据库的配置文件:
<?xml version="1.0"?>
<!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="show_sql">true</property>
<property name="connection.driver_class">Oracle.jdbc.driver.OracleDriver</property>
<property name="connection.url">jdbc:oracle:thin:@127.0.0.1:1521:name</property>
<property name="connection.username">scott</property>
<property name="connection.passWord">tiger</property>
<property name="connection.isolation">2</property>
<property name="dialect">org.hibernate.dialect.Oracle9Dialect</property>
<mapping resource="Yuchen/fristHbn/business/entity/Fruit.hbm.xml"/>
</session-factory>
</hibernate-configuration>

写映射配置文件:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="Yuchen.fristHbn.business.entity">
<class name="Fruit" table="T_FRUIT">
<id name="fid" column="fid">
<generator class="hilo">

<param name="table">t_hilo</param>
<param name="column">hilo_id</param>
</generator>
</id>
<property name="name" column="name" />
<property name="comments" column="comments"></property>
<property name="price" column="price"></property>
</class>
</hibernate-mapping>
A. 类名—表名
B. id—id 获得id的方式 具体信息(如: hilo的表名和字段)
C. 属性—字段

使用hibernate API(FruitManager.java):
package Yuchen.fristHbn.business.Biz;
//业务逻辑类:负责增删改查通过使用hibernate API进行
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

import Yuchen.fristHbn.business.entity.Fruit;

public class FruitManager {
public void insert(Fruit fruit){
Configuration config=new Configuration();
config.configure();//读配置文件
SessionFactory sf=config.buildSessionFactory();//得到工厂
Session session=sf.openSession();//得到session
Transaction tt=session.beginTransaction();//检查事务开启
session.save(fruit);//存储insert
tt.commit();//提交
session.close();//关闭资源
}
}

写测试类: 插入一个对象到数据库中
/**
* 知识点:
* hibernate基础:练习语法部分API和简单的映射关系
* 程序目标:
* 使用hibernate方法将对象进行持久化
* 实现数据库的增删改查
* API:
* 1.Configuration:这个类负责读取XML文档(映射配置文件)
* configure():读xml
* buildSessionFactory():创建一个生产session对象的工厂,其实是再次检查
* 因为hibernate和jdbc不一样,jdbc是假如不手动设置开启事务,那它
* 就是马上执行sql的,hibernate的不会马上执行,是事务提交后执行
* 默认情况下就是打开事务的状态,这里只是再检查以下
* 2.SessionFactory:负责生产session对象
* openSession():创建一个session
* 3.Session类:这个是主要的类,负责增删改查,开启事务等
* beginTransaction():产生一个事务对象(Transaction)
* save():增加相当于操作sql中的insert语句
* 4.Transaction类:负责治理事务的
* commit():提交一个事务
*
*/
package Yuchen.fristHbn.client;

import Yuchen.fristHbn.business.Biz.FruitManager;
import Yuchen.fristHbn.business.entity.Fruit;

public class Test {

public static void test1(){
Fruit fruit=new Fruit("lisi","hello",100);
// fruit.setName("zhangsan");
// fruit.setComments("hello");
// fruit.setPrice(100);

FruitManager fm=new FruitManager();
fm.insert(fruit);
}
public static void main(String[] args) {
// TODO 自动生成方法存根
Test t=new Test();
t.test1();
}

}

hibernate API(一):
Configuration: 读取配置文件信息用来初始化的
SessionFactory: 重量级对象,特点:消耗资源大,线程是安全,所以可以被共享
上面两个对象只实例化一个就行了,都是用于初始化的
Session: 线程是不安全的,所以要避免多个线程共享它,是轻量级的对象,使用后关闭

Session对象的状态:
顺态: 还没有被持久化,也就是说数据库中没有该对象的记录,并且Session中的缓冲区里没有这个对象的引用
持久态: 在数据库中有该对象的记录,并且在session中的缓冲区里有这个对象的引用,和顺态正好相反
游离态: 在数据库中有记录,但是不在session的缓冲区里

对象状态的转换:
做一个工具类,将hibernate中重复的代码包装起来:
package Yuchen.fristHbn.util;
//生产session对象的工具类
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HbnUtil {

private static SessionFactory sf;
static{
sf=new Configuration().configure().buildSessionFactory();
}

public static Session getSession(){
return sf.openSession();
}
}

完善FruitManager类:
package Yuchen.fristHbn.business.Biz;
//业务逻辑类:负责增删改查通过使用hibernate API进行
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

import Yuchen.fristHbn.business.entity.Fruit;
import Yuchen.fristHbn.util.HbnUtil;

public class FruitManager {
public Integer insert(Fruit fruit){
Session session=HbnUtil.getSession();//通过工具更方便了
Integer id=null;
// Configuration config=new Configuration();
// config.configure();//读配置文件
// SessionFactory sf=config.buildSessionFactory();//得到工厂
// Session session=sf.openSession();//得到session
Transaction tt=session.beginTransaction();//检查事务开启
id=(Integer)session.save(fruit);//存储insert
tt.commit();//提交
session.close();//关闭资源
return id;
}

public Fruit selectId(Integer id){
Session session=HbnUtil.getSession();
Transaction t=session.beginTransaction();
Fruit fruit=(Fruit)session.get(Fruit.class, id);
t.commit();
session.close();
return fruit;
}

public void remove(Fruit fruit){
Session session=HbnUtil.getSession();
Transaction t=session.beginTransaction();
session.delete(fruit);
t.commit();
session.close();
}
}

测试对象状态的转换:
/**
* 知识点:
* hibernate基础:练习语法部分API和简单的映射关系
* 程序目标:
* 使用hibernate方法将对象进行持久化
* 实现数据库的增删改查
* API:
* 1.Configuration:这个类负责读取XML文档(映射配置文件)
* configure():读xml
* buildSessionFactory():创建一个生产session对象的工厂,其实是再次检查
* 因为hibernate和jdbc不一样,jdbc是假如不手动设置开启事务,那它
* 就是马上执行sql的,hibernate的不会马上执行,是事务提交后执行
* 默认情况下就是打开事务的状态,这里只是再检查以下
* 2.SessionFactory:负责生产session对象
* openSession():创建一个session
* 3.Session类:这个是主要的类,负责增删改查,开启事务等
* beginTransaction():产生一个事务对象(Transaction)
* save():增加相当于操作sql中的insert语句
* 4.Transaction类:负责治理事务的
* commit():提交一个事务
* test1():测试插入的功能
* test2():测试数据同步更新的功能
* test3():测试saveOrUpdate()
* test4():测试clear()和flush()
*/
package Yuchen.fristHbn.client;

import org.hibernate.Session;
import org.hibernate.Transaction;

import Yuchen.fristHbn.business.Biz.FruitManager;
import Yuchen.fristHbn.business.entity.Fruit;
import Yuchen.fristHbn.util.HbnUtil;

public class Test {

public void test1(){
Fruit fruit=new Fruit("lisi","hello",100);
// fruit.setName("zhangsan");
// fruit.setComments("hello");
// fruit.setPrice(100);

FruitManager fm=new FruitManager();
fm.insert(fruit);
}

public void test2(){
//测试同步更新的功能
Fruit fruit=new Fruit("meigui","hongse",70);//顺态
FruitManager fm=new FruitManager();
Fruit fruit2=new Fruit();

Integer id=fm.insert(fruit);

fruit2=fm.selectId(id);
System.out.println(fruit2.getFid());
System.out.println(fruit2.getName());

fruit.setName("ziluolan");//这里修改了对象
fruit2=fm.selectId(id);
System.out.println(fruit2.getFid());//但是结果没有更新
System.out.println(fruit2.getName());
//因为fruit在Integer id=fm.insert(fruit);后变成游离态了
//也就是说只有持久态才能实现同步更新
System.out.println(fruit.getFid());
System.out.println(fruit.getName());
}

public void test3(){
Session session=HbnUtil.getSession();
Transaction t=session.beginTransaction();
Fruit fruit=new Fruit("ziluolan","lanse",100);//顺态
Fruit fruit2=new Fruit();
FruitManager fm=new FruitManager();
session.save(fruit);//fruit在运行完此句后变为游离态
fruit2=(Fruit) session.get(Fruit.class, fruit.getFid());
//从数据库读并打印出来
System.out.println(fruit2.getFid()+":"+fruit2.getName());

session.saveOrUpdate(fruit);//假如该对象为游历态就更新数据库update
//否则就是顺态,增加insert
fruit2=(Fruit) session.get(Fruit.class, fruit.getFid());
//saveOrUpdate后再从数据库读并打印出来
System.out.println(fruit2.getFid()+":"+fruit2.getName());
//两个打印结果一样,saveOrUpdate方法判定假如id为null,就
//顺态,否则就是游离态
t.commit();
session.close();
}

public void test4(){
Session session=HbnUtil.getSession();
Transaction t=session.beginTransaction();
Fruit fruit=new Fruit("guihua","fense",300);//顺态
Fruit fruit2=new Fruit();
session.saveOrUpdate(fruit);//执行insert因为对象为顺态
// session.flush();
session.clear();//fruit变成游离态了,并且不会执行insert语句
//因为hibernate不是马上执行sql,而是等t.commit()提交事务
//后才执行,clear后,对象为游离态

session.saveOrUpdate(fruit);//这里验证上面的话,执行update
//做个select查看一下,可以证实,因为clear后,没有马上执行
//sql语句,所以表里没有数据,这里update也没有用,所以表中
//一个对象也没插入,但是假如加入flush()刷新就是马上执行sql了

t.commit();
session.close();
}
public static void main(String[] args) {
// TODO 自动生成方法存根
Test t=new Test();
// t.test1();
// t.test2();
// t.test3();
t.test4();
}

}

hibernate API(二):
flush(): 从上面的例子可以看出,flush是刷新session的缓冲区,并执行里面的命令
flush()的事务治理模式: flushMode()里面有三个常量,可以用数字来表示
Load(): 另一种读取数据的方法,和get的区别是: 1.异常处理: load有异常处理,get没有,它返回null,2.get从数据库读数据,load可能去读缓冲区

事务的隔离级别:
在hibernate的数据库配置文件中设置
数字1为可以脏读,数字2为不能,这个是最常用的

锁机制:
避免并发冲突,在数据库中写数据是自动加锁的,读一般不加,有悲观锁和乐观锁
乐观锁是可以是hibernate程序自己加
实现乐观锁: 引例(hbn2包)
步骤:
1. 在表中加个version字段
2. 在持久类里加个version属性
3. 配置文件<version name=”versopm”> 每存一次值加1

引例:hbn2包

复杂的映射:
1. 基数关系映射
2. 继续关系映射
3. 组件关系映射
4. 集合映射

基数关系的映射—one to one:
基数关系的映射需要考虑的问题:
1. 数量问题
2. 方向问题
在one to one的关系中,我们有两种方法可以体现类与类之间的关系
1. 共享主键
2. 外键唯一
引例: Joto包-此包引用了fristHbn包

建立与Fruit类有一对一关系的类:
我们认为一个花有一个产地,一个产地生产一种花,所以要建立产地类
package Yuchen.Joto.business.entity;
//花的地址类
//问题:为什么不能在构造函数中写Fruit?因为生成对象后要持久化
//这个对象,但是数据库的表中不能插入另一个类的值,写上null又不
//大合适,所以就去掉它
public class Address {
private Integer aid;

private String nation;
private String postcode;
private Fruit fruit;
public Address() {

}
public Address(String nation, String postcode) {
super();
this.nation = nation;
this.postcode = postcode;
}
public Integer getAid() {
return aid;
}
public void setAid(Integer aid) {
this.aid = aid;
}
public Fruit getFruit() {
return fruit;
}
public void setFruit(Fruit fruit) {
this.fruit = fruit;
// fruit.setAddress(this);
}
public String getNation() {
return nation;
}
public void setNation(String nation) {
this.nation = nation;
}
public String getPostcode() {
return postcode;
}
public void setPostcode(String postcode) {
this.postcode = postcode;
}

}

修改Fruit类:
package Yuchen.Joto.business.entity;
//持久化类(花类),注重因为采用的是hilo的方式获得id,所以需要有setid的方法
public class Fruit {

private Integer fid;//hibernate中的id不能识别int
private String name;
private String comments;
private int price;
private Address address;//一朵花对应一个地址

public Fruit() {
super();
}

public Fruit(String name, String comments, int price) {
super();
this.name = name;
this.comments = comments;
this.price = price;
}

public Address getAddress() {
return address;
}

public void setAddress(Address address) {
this.address = address;
address.setFruit(this);//因为当你给一个花设置产地的时候
//该产地也有了花
}

public String getComments() {
return comments;
}
public void setComments(String comments) {
this.comments = comments;
}

public Integer getFid() {
return fid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price)


Tags:初学者 Hibernate 初级

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接