1. 什么是hibernate?
2. hibernate的知識(shí)內(nèi)容
3. 什么是對(duì)象持久化?對(duì)象持久化有什么用?(解決的問(wèn)題)
4. 如何對(duì)象持久化?
5. 如何用數(shù)據(jù)庫(kù)的方法做對(duì)象持久化?
6. ORM(對(duì)象關(guān)系映射)是什么?有什么作用?
7. ORM從對(duì)象到表所要考慮的問(wèn)題
8. 什么是ORM框架?有什么用?
9. 使用hibernate的方法做對(duì)象持久化的工作,程序員應(yīng)該怎么做?
10. hibernate有什么用?
11. 程序員和hibernate的整體工作流程
什么是hibernate:
持久化的框架,屬于設(shè)計(jì)方面的內(nèi)容,類庫(kù),用來(lái)做對(duì)象持久化的,什么是對(duì)象持久化呢?
Hibernate的知識(shí)內(nèi)容:
語(yǔ)法部分(類庫(kù))
程序設(shè)計(jì)思想,也就是持久層的設(shè)計(jì)
什么是對(duì)象持久化?對(duì)象持久化有什么用?(解決的問(wèn)題):
發(fā)現(xiàn)問(wèn)題:
程序設(shè)計(jì)的架構(gòu): 表現(xiàn)層—業(yè)務(wù)層—持久層—數(shù)據(jù)庫(kù)層,其中表現(xiàn)層和業(yè)務(wù)層是JVM來(lái)執(zhí)行,應(yīng)用程序會(huì)產(chǎn)生許多的對(duì)象,如果斷電了,對(duì)象就消失了,也就是說(shuō)在內(nèi)存中的對(duì)象是不穩(wěn)定的,狀態(tài)不能持久
發(fā)現(xiàn)問(wèn)題:
將一個(gè)對(duì)象從A電腦復(fù)制到B電腦,如何做到呢?
那么有三種方法解決上面的問(wèn)題:
1. 序列化: 通過(guò)網(wǎng)絡(luò)傳遞,或者硬盤共享
2. 存儲(chǔ)到數(shù)據(jù)庫(kù)中,誰(shuí)想用,從數(shù)據(jù)庫(kù)中拿
3. EJB Entity Bean(實(shí)體Bean)
序列化的方法比較死板:如果當(dāng)一個(gè)對(duì)象的結(jié)構(gòu)比較復(fù)雜的時(shí)候,我們這時(shí)只需要一部分內(nèi)容,沒(méi)有辦法,只能整個(gè)寫入到文件,整個(gè)讀取
序列化的缺點(diǎn): 不能檢索,不能分離一個(gè)對(duì)象,不方便共享
所以說(shuō)第一種方法只能用于做臨時(shí)的持久化,簡(jiǎn)單的傳輸,但不適合復(fù)雜的持久化工作
第二種方法(數(shù)據(jù)庫(kù)持久化):檢索方便,分布式共享,永久數(shù)據(jù)
總結(jié):
什么是對(duì)象持久化: 對(duì)象持久化就是把內(nèi)存中的對(duì)象永久的保存起來(lái),保護(hù)對(duì)象的狀態(tài),方便使用
對(duì)象持久化有什么用: 1.解決掉電的問(wèn)題 2.共享方便 3.保證對(duì)象安全檢索方便
如何對(duì)象持久化:
1. 對(duì)象序列化
2. 數(shù)據(jù)庫(kù)(JDBC,EJB,Hibernate)
如何用數(shù)據(jù)庫(kù)的方法做對(duì)象持久化:
1. JDBC
發(fā)現(xiàn)問(wèn)題: 需要做大量的工作,難度大
2. EJB
使用的是其中的一個(gè)功能來(lái)做持久化,解決了使用JDBC方法的的大量工作的問(wèn)題
發(fā)現(xiàn)問(wèn)題: EJB是重量級(jí)的組件,要使用它,有兩個(gè)問(wèn)題 1.成本 2.性能
發(fā)現(xiàn)問(wèn)題: 以上兩種方式還有個(gè)共同的問(wèn)題,對(duì)象不是簡(jiǎn)單存儲(chǔ)在數(shù)據(jù)庫(kù)中的,比如多態(tài)的特點(diǎn)就不能處理 A b=new B(); B為A的子類
3. Hibernate
解決了以上的所有問(wèn)題,作用:1.不用做大量的工作 2.移植性能好 3.提高了代碼的質(zhì)量,簡(jiǎn)單 4.檢索共享重用成本調(diào)試
ORM(對(duì)象關(guān)系映射)是什么?有什么作用?
發(fā)現(xiàn)問(wèn)題:
java中的對(duì)象的屬性類型和數(shù)據(jù)庫(kù)中的字段類型是不一樣的,那么如何來(lái)存儲(chǔ)java中的對(duì)象呢?這就需要做對(duì)象關(guān)系的映射,也就是ORM
什么是ORM: 將內(nèi)存中的對(duì)象和數(shù)據(jù)庫(kù)做轉(zhuǎn)化,這樣就實(shí)現(xiàn)了java與數(shù)據(jù)庫(kù)之間的訪問(wèn)等功能
ORM從對(duì)象到表所要考慮的問(wèn)題:
Orm的復(fù)雜問(wèn)題:
1. 數(shù)據(jù)庫(kù)如何保證對(duì)象的唯一性:在內(nèi)存中,兩個(gè)對(duì)象屬性值都一樣,但是內(nèi)存地址不一樣,可以做區(qū)分,但是在數(shù)據(jù)庫(kù)中如何分辨呢?
2. 繼承關(guān)系如何轉(zhuǎn)化
3. 集合如何映射呢?
什么是ORM框架?有什么用?
就是一個(gè)類庫(kù),通過(guò)這個(gè)類庫(kù)完成持久化層的設(shè)計(jì)
使用hibernate的方法做對(duì)象持久化的工作,程序員應(yīng)該怎么做?
1. 將ORM方案定下來(lái),就是類到數(shù)據(jù)庫(kù)的轉(zhuǎn)化 2.利用hibernate生成代碼
hibernate有什么用?
1. 完成jdbc的代碼
2. 管理持久化對(duì)象的狀態(tài)
3. 提供一個(gè)查詢的API
程序員和hibernate的整體工作流程
程序員:
1. 設(shè)計(jì)ORM方案
2. 寫配置文件
3. 調(diào)用Hibernate的API,向Hibernate發(fā)出命令
hibernate:
4. 讀配置文件
5. 生成jdbc代碼
6. 執(zhí)行
Hibernate簡(jiǎn)單實(shí)例
Hibernate語(yǔ)法:
作用: 數(shù)據(jù)庫(kù)的增刪改查 HQL面向?qū)ο蟮牟樵冋Z(yǔ)句
大致步驟:
1. 設(shè)置環(huán)境 類庫(kù)
2. 定義映射
A 定義映射的實(shí)體po
B 建立數(shù)據(jù)庫(kù)表
C 寫XML配置文件(表,數(shù)據(jù)庫(kù))
3. 調(diào)用Hibernate API
A 管理po的狀態(tài)(增刪改,恢復(fù)po狀態(tài))
B 檢索(查詢)
Hibernate第一個(gè)簡(jiǎn)單的實(shí)例: 引例(frisHbn包)
1. 設(shè)置環(huán)境
hibernate配置環(huán)境需要的資源
Hibernate的jar包: lib.zip dtd.zip: dtd.zip可以不設(shè)置
2. 定義映射
建立項(xiàng)目:
bussiness包: entity包 Biz包業(yè)務(wù)
client包: 測(cè)試
util包: 工具
先寫持久化類: 以花為實(shí)體,建立花類,并且建立數(shù)據(jù)庫(kù)表
/**
* 建表語(yǔ)句:
* 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;
//持久化類(花類),注意因?yàn)椴捎玫氖莌ilo的方式獲得id,所以需要有setid的方法
public class Fruit {
private Integer fid;//hibernate中的id不能識(shí)別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:
建表語(yǔ)句:
CREATE TABLE T_HILO(HILO_ID NUMBER(10));
INSERT INTO T_HILO VALUES(1);
寫hibernate的連接數(shù)據(jù)庫(kù)的配置文件:
<?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
racle: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的方式 詳細(xì)信息(如: hilo的表名和字段)
C. 屬性—字段
使用hibernate API(FruitManager.java):
package Yuchen.fristHbn.business.Biz;
//業(yè)務(wù)邏輯類:負(fù)責(zé)增刪改查通過(guò)使用hibernate API進(jìn)行
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();//檢查事務(wù)開(kāi)啟
session.save(fruit);//存儲(chǔ)insert
tt.commit();//提交
session.close();//關(guān)閉資源
}
}
寫測(cè)試類: 插入一個(gè)對(duì)象到數(shù)據(jù)庫(kù)中
/**
* 知識(shí)點(diǎn):
* hibernate基礎(chǔ):練習(xí)語(yǔ)法部分API和簡(jiǎn)單的映射關(guān)系
* 程序目標(biāo):
* 使用hibernate方法將對(duì)象進(jìn)行持久化
* 實(shí)現(xiàn)數(shù)據(jù)庫(kù)的增刪改查
* API:
* 1.Configuration:這個(gè)類負(fù)責(zé)讀取XML文檔(映射配置文件)
* configure():讀xml
* buildSessionFactory():創(chuàng)建一個(gè)生產(chǎn)session對(duì)象的工廠,其實(shí)是再次檢查
* 因?yàn)閔ibernate和jdbc不一樣,jdbc是如果不手動(dòng)設(shè)置開(kāi)啟事務(wù),那它
* 就是馬上執(zhí)行sql的,hibernate的不會(huì)馬上執(zhí)行,是事務(wù)提交后執(zhí)行
* 默認(rèn)情況下就是打開(kāi)事務(wù)的狀態(tài),這里只是再檢查以下
* 2.SessionFactory:負(fù)責(zé)生產(chǎn)session對(duì)象
* openSession():創(chuàng)建一個(gè)session
* 3.Session類:這個(gè)是主要的類,負(fù)責(zé)增刪改查,開(kāi)啟事務(wù)等
* beginTransaction():產(chǎn)生一個(gè)事務(wù)對(duì)象(Transaction)
* save():增加相當(dāng)于操作sql中的insert語(yǔ)句
* 4.Transaction類:負(fù)責(zé)管理事務(wù)的
* commit():提交一個(gè)事務(wù)
*
*/
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 自動(dòng)生成方法存根
Test t=new Test();
t.test1();
}
}
hibernate API(一):
Configuration: 讀取配置文件信息用來(lái)初始化的
SessionFactory: 重量級(jí)對(duì)象,特點(diǎn):消耗資源大,線程是安全,所以可以被共享
上面兩個(gè)對(duì)象只實(shí)例化一個(gè)就行了,都是用于初始化的
Session: 線程是不安全的,所以要避免多個(gè)線程共享它,是輕量級(jí)的對(duì)象,使用后關(guān)閉
Session對(duì)象的狀態(tài):
順態(tài): 還沒(méi)有被持久化,也就是說(shuō)數(shù)據(jù)庫(kù)中沒(méi)有該對(duì)象的記錄,并且Session中的緩沖區(qū)里沒(méi)有這個(gè)對(duì)象的引用
持久態(tài): 在數(shù)據(jù)庫(kù)中有該對(duì)象的記錄,并且在session中的緩沖區(qū)里有這個(gè)對(duì)象的引用,和順態(tài)正好相反
游離態(tài): 在數(shù)據(jù)庫(kù)中有記錄,但是不在session的緩沖區(qū)里
對(duì)象狀態(tài)的轉(zhuǎn)換:
做一個(gè)工具類,將hibernate中重復(fù)的代碼包裝起來(lái):
package Yuchen.fristHbn.util;
//生產(chǎn)session對(duì)象的工具類
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;
//業(yè)務(wù)邏輯類:負(fù)責(zé)增刪改查通過(guò)使用hibernate API進(jìn)行
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();//通過(guò)工具更方便了
Integer id=null;
// Configuration config=new Configuration();
// config.configure();//讀配置文件
// SessionFactory sf=config.buildSessionFactory();//得到工廠
// Session session=sf.openSession();//得到session
Transaction tt=session.beginTransaction();//檢查事務(wù)開(kāi)啟
id=(Integer)session.save(fruit);//存儲(chǔ)insert
tt.commit();//提交
session.close();//關(guān)閉資源
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();
}
}
測(cè)試對(duì)象狀態(tài)的轉(zhuǎn)換:
/**
* 知識(shí)點(diǎn):
* hibernate基礎(chǔ):練習(xí)語(yǔ)法部分API和簡(jiǎn)單的映射關(guān)系
* 程序目標(biāo):
* 使用hibernate方法將對(duì)象進(jìn)行持久化
* 實(shí)現(xiàn)數(shù)據(jù)庫(kù)的增刪改查
* API:
* 1.Configuration:這個(gè)類負(fù)責(zé)讀取XML文檔(映射配置文件)
* configure():讀xml
* buildSessionFactory():創(chuàng)建一個(gè)生產(chǎn)session對(duì)象的工廠,其實(shí)是再次檢查
* 因?yàn)閔ibernate和jdbc不一樣,jdbc是如果不手動(dòng)設(shè)置開(kāi)啟事務(wù),那它
* 就是馬上執(zhí)行sql的,hibernate的不會(huì)馬上執(zhí)行,是事務(wù)提交后執(zhí)行
* 默認(rèn)情況下就是打開(kāi)事務(wù)的狀態(tài),這里只是再檢查以下
* 2.SessionFactory:負(fù)責(zé)生產(chǎn)session對(duì)象
* openSession():創(chuàng)建一個(gè)session
* 3.Session類:這個(gè)是主要的類,負(fù)責(zé)增刪改查,開(kāi)啟事務(wù)等
* beginTransaction():產(chǎn)生一個(gè)事務(wù)對(duì)象(Transaction)
* save():增加相當(dāng)于操作sql中的insert語(yǔ)句
* 4.Transaction類:負(fù)責(zé)管理事務(wù)的
* commit():提交一個(gè)事務(wù)
* test1():測(cè)試插入的功能
* test2():測(cè)試數(shù)據(jù)同步更新的功能
* test3():測(cè)試saveOrUpdate()
* test4():測(cè)試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(){
//測(cè)試同步更新的功能
Fruit fruit=new Fruit("meigui","hongse",70);//順態(tài)
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");//這里修改了對(duì)象
fruit2=fm.selectId(id);
System.out.println(fruit2.getFid());//但是結(jié)果沒(méi)有更新
System.out.println(fruit2.getName());
//因?yàn)閒ruit在Integer id=fm.insert(fruit);后變成游離態(tài)了
//也就是說(shuō)只有持久態(tài)才能實(shí)現(xiàn)同步更新
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);//順態(tài)
Fruit fruit2=new Fruit();
FruitManager fm=new FruitManager();
session.save(fruit);//fruit在運(yùn)行完此句后變?yōu)橛坞x態(tài)
fruit2=(Fruit) session.get(Fruit.class, fruit.getFid());
//從數(shù)據(jù)庫(kù)讀并打印出來(lái)
System.out.println(fruit2.getFid()+":"+fruit2.getName());
session.saveOrUpdate(fruit);//如果該對(duì)象為游歷態(tài)就更新數(shù)據(jù)庫(kù)update
//否則就是順態(tài),增加insert
fruit2=(Fruit) session.get(Fruit.class, fruit.getFid());
//saveOrUpdate后再?gòu)臄?shù)據(jù)庫(kù)讀并打印出來(lái)
System.out.println(fruit2.getFid()+":"+fruit2.getName());
//兩個(gè)打印結(jié)果一樣,saveOrUpdate方法判斷如果id為null,就
//順態(tài),否則就是游離態(tài)
t.commit();
session.close();
}
public void test4(){
Session session=HbnUtil.getSession();
Transaction t=session.beginTransaction();
Fruit fruit=new Fruit("guihua","fense",300);//順態(tài)
Fruit fruit2=new Fruit();
session.saveOrUpdate(fruit);//執(zhí)行insert因?yàn)閷?duì)象為順態(tài)
// session.flush();
session.clear();//fruit變成游離態(tài)了,并且不會(huì)執(zhí)行insert語(yǔ)句
//因?yàn)閔ibernate不是馬上執(zhí)行sql,而是等t.commit()提交事務(wù)
//后才執(zhí)行,clear后,對(duì)象為游離態(tài)
session.saveOrUpdate(fruit);//這里驗(yàn)證上面的話,執(zhí)行update
//做個(gè)select查看一下,可以證明,因?yàn)閏lear后,沒(méi)有馬上執(zhí)行
//sql語(yǔ)句,所以表里沒(méi)有數(shù)據(jù),這里update也沒(méi)有用,所以表中
//一個(gè)對(duì)象也沒(méi)插入,但是如果加入flush()刷新就是馬上執(zhí)行sql了
t.commit();
session.close();
}
public static void main(String[] args) {
// TODO 自動(dòng)生成方法存根
Test t=new Test();
// t.test1();
// t.test2();
// t.test3();
t.test4();
}
}
hibernate API(二):
flush(): 從上面的例子可以看出,flush是刷新session的緩沖區(qū),并執(zhí)行里面的命令
flush()的事務(wù)管理模式: flushMode()里面有三個(gè)常量,可以用數(shù)字來(lái)表示
Load(): 另一種讀取數(shù)據(jù)的方法,和get的區(qū)別是: 1.異常處理: load有異常處理,get沒(méi)有,它返回null,2.get從數(shù)據(jù)庫(kù)讀數(shù)據(jù),load可能去讀緩沖區(qū)
事務(wù)的隔離級(jí)別:
在hibernate的數(shù)據(jù)庫(kù)配置文件中設(shè)置
數(shù)字1為可以臟讀,數(shù)字2為不能,這個(gè)是最常用的
鎖機(jī)制:
避免并發(fā)沖突,在數(shù)據(jù)庫(kù)中寫數(shù)據(jù)是自動(dòng)加鎖的,讀一般不加,有悲觀鎖和樂(lè)觀鎖
樂(lè)觀鎖是可以是hibernate程序自己加
實(shí)現(xiàn)樂(lè)觀鎖: 引例(hbn2包)
步驟:
1. 在表中加個(gè)version字段
2. 在持久類里加個(gè)version屬性
3. 配置文件<version name=”versopm”> 每存一次值加1
引例:hbn2包
復(fù)雜的映射:
1. 基數(shù)關(guān)系映射
2. 繼承關(guān)系映射
3. 組件關(guān)系映射
4. 集合映射
基數(shù)關(guān)系的映射—one to one:
基數(shù)關(guān)系的映射需要考慮的問(wèn)題:
1. 數(shù)量問(wèn)題
2. 方向問(wèn)題
在one to one的關(guān)系中,我們有兩種方法可以體現(xiàn)類與類之間的關(guān)系
1. 共享主鍵
2. 外鍵唯一
引例: Joto包-此包引用了fristHbn包
建立與Fruit類有一對(duì)一關(guān)系的類:
我們認(rèn)為一個(gè)花有一個(gè)產(chǎn)地,一個(gè)產(chǎn)地生產(chǎn)一種花,所以要建立產(chǎn)地類
package Yuchen.Joto.business.entity;
//花的地址類
//問(wèn)題:為什么不能在構(gòu)造函數(shù)中寫Fruit?因?yàn)樯蓪?duì)象后要持久化
//這個(gè)對(duì)象,但是數(shù)據(jù)庫(kù)的表中不能插入另一個(gè)類的值,寫上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;
//持久化類(花類),注意因?yàn)椴捎玫氖莌ilo的方式獲得id,所以需要有setid的方法
public class Fruit {
private Integer fid;//hibernate中的id不能識(shí)別int
private String name;
private String comments;
private int price;
private Address address;//一朵花對(duì)應(yīng)一個(gè)地址
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);//因?yàn)楫?dāng)你給一個(gè)花設(shè)置產(chǎn)地的時(shí)候
//該產(chǎn)地也有了花
}
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)
持久化的框架,屬于設(shè)計(jì)方面的內(nèi)容,類庫(kù),用來(lái)做對(duì)象持久化的,什么是對(duì)象持久化呢?
Hibernate的知識(shí)內(nèi)容:
語(yǔ)法部分(類庫(kù))
程序設(shè)計(jì)思想,也就是持久層的設(shè)計(jì)
什么是對(duì)象持久化?對(duì)象持久化有什么用?(解決的問(wèn)題):
發(fā)現(xiàn)問(wèn)題:
程序設(shè)計(jì)的架構(gòu): 表現(xiàn)層—業(yè)務(wù)層—持久層—數(shù)據(jù)庫(kù)層,其中表現(xiàn)層和業(yè)務(wù)層是JVM來(lái)執(zhí)行,應(yīng)用程序會(huì)產(chǎn)生許多的對(duì)象,如果斷電了,對(duì)象就消失了,也就是說(shuō)在內(nèi)存中的對(duì)象是不穩(wěn)定的,狀態(tài)不能持久
發(fā)現(xiàn)問(wèn)題:
將一個(gè)對(duì)象從A電腦復(fù)制到B電腦,如何做到呢?
那么有三種方法解決上面的問(wèn)題:
1. 序列化: 通過(guò)網(wǎng)絡(luò)傳遞,或者硬盤共享
2. 存儲(chǔ)到數(shù)據(jù)庫(kù)中,誰(shuí)想用,從數(shù)據(jù)庫(kù)中拿
3. EJB Entity Bean(實(shí)體Bean)
序列化的方法比較死板:如果當(dāng)一個(gè)對(duì)象的結(jié)構(gòu)比較復(fù)雜的時(shí)候,我們這時(shí)只需要一部分內(nèi)容,沒(méi)有辦法,只能整個(gè)寫入到文件,整個(gè)讀取
序列化的缺點(diǎn): 不能檢索,不能分離一個(gè)對(duì)象,不方便共享
所以說(shuō)第一種方法只能用于做臨時(shí)的持久化,簡(jiǎn)單的傳輸,但不適合復(fù)雜的持久化工作
第二種方法(數(shù)據(jù)庫(kù)持久化):檢索方便,分布式共享,永久數(shù)據(jù)
總結(jié):
什么是對(duì)象持久化: 對(duì)象持久化就是把內(nèi)存中的對(duì)象永久的保存起來(lái),保護(hù)對(duì)象的狀態(tài),方便使用
對(duì)象持久化有什么用: 1.解決掉電的問(wèn)題 2.共享方便 3.保證對(duì)象安全檢索方便
如何對(duì)象持久化:
1. 對(duì)象序列化
2. 數(shù)據(jù)庫(kù)(JDBC,EJB,Hibernate)
如何用數(shù)據(jù)庫(kù)的方法做對(duì)象持久化:
1. JDBC
發(fā)現(xiàn)問(wèn)題: 需要做大量的工作,難度大
2. EJB
使用的是其中的一個(gè)功能來(lái)做持久化,解決了使用JDBC方法的的大量工作的問(wèn)題
發(fā)現(xiàn)問(wèn)題: EJB是重量級(jí)的組件,要使用它,有兩個(gè)問(wèn)題 1.成本 2.性能
發(fā)現(xiàn)問(wèn)題: 以上兩種方式還有個(gè)共同的問(wèn)題,對(duì)象不是簡(jiǎn)單存儲(chǔ)在數(shù)據(jù)庫(kù)中的,比如多態(tài)的特點(diǎn)就不能處理 A b=new B(); B為A的子類
3. Hibernate
解決了以上的所有問(wèn)題,作用:1.不用做大量的工作 2.移植性能好 3.提高了代碼的質(zhì)量,簡(jiǎn)單 4.檢索共享重用成本調(diào)試
ORM(對(duì)象關(guān)系映射)是什么?有什么作用?
發(fā)現(xiàn)問(wèn)題:
java中的對(duì)象的屬性類型和數(shù)據(jù)庫(kù)中的字段類型是不一樣的,那么如何來(lái)存儲(chǔ)java中的對(duì)象呢?這就需要做對(duì)象關(guān)系的映射,也就是ORM
什么是ORM: 將內(nèi)存中的對(duì)象和數(shù)據(jù)庫(kù)做轉(zhuǎn)化,這樣就實(shí)現(xiàn)了java與數(shù)據(jù)庫(kù)之間的訪問(wèn)等功能
ORM從對(duì)象到表所要考慮的問(wèn)題:
Orm的復(fù)雜問(wèn)題:
1. 數(shù)據(jù)庫(kù)如何保證對(duì)象的唯一性:在內(nèi)存中,兩個(gè)對(duì)象屬性值都一樣,但是內(nèi)存地址不一樣,可以做區(qū)分,但是在數(shù)據(jù)庫(kù)中如何分辨呢?
2. 繼承關(guān)系如何轉(zhuǎn)化
3. 集合如何映射呢?
什么是ORM框架?有什么用?
就是一個(gè)類庫(kù),通過(guò)這個(gè)類庫(kù)完成持久化層的設(shè)計(jì)
使用hibernate的方法做對(duì)象持久化的工作,程序員應(yīng)該怎么做?
1. 將ORM方案定下來(lái),就是類到數(shù)據(jù)庫(kù)的轉(zhuǎn)化 2.利用hibernate生成代碼
hibernate有什么用?
1. 完成jdbc的代碼
2. 管理持久化對(duì)象的狀態(tài)
3. 提供一個(gè)查詢的API
程序員和hibernate的整體工作流程
程序員:
1. 設(shè)計(jì)ORM方案
2. 寫配置文件
3. 調(diào)用Hibernate的API,向Hibernate發(fā)出命令
hibernate:
4. 讀配置文件
5. 生成jdbc代碼
6. 執(zhí)行
Hibernate簡(jiǎn)單實(shí)例
Hibernate語(yǔ)法:
作用: 數(shù)據(jù)庫(kù)的增刪改查 HQL面向?qū)ο蟮牟樵冋Z(yǔ)句
大致步驟:
1. 設(shè)置環(huán)境 類庫(kù)
2. 定義映射
A 定義映射的實(shí)體po
B 建立數(shù)據(jù)庫(kù)表
C 寫XML配置文件(表,數(shù)據(jù)庫(kù))
3. 調(diào)用Hibernate API
A 管理po的狀態(tài)(增刪改,恢復(fù)po狀態(tài))
B 檢索(查詢)
Hibernate第一個(gè)簡(jiǎn)單的實(shí)例: 引例(frisHbn包)
1. 設(shè)置環(huán)境
hibernate配置環(huán)境需要的資源
Hibernate的jar包: lib.zip dtd.zip: dtd.zip可以不設(shè)置
2. 定義映射
建立項(xiàng)目:
bussiness包: entity包 Biz包業(yè)務(wù)
client包: 測(cè)試
util包: 工具
先寫持久化類: 以花為實(shí)體,建立花類,并且建立數(shù)據(jù)庫(kù)表
/**
* 建表語(yǔ)句:
* 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;
//持久化類(花類),注意因?yàn)椴捎玫氖莌ilo的方式獲得id,所以需要有setid的方法
public class Fruit {
private Integer fid;//hibernate中的id不能識(shí)別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:
建表語(yǔ)句:
CREATE TABLE T_HILO(HILO_ID NUMBER(10));
INSERT INTO T_HILO VALUES(1);
寫hibernate的連接數(shù)據(jù)庫(kù)的配置文件:
<?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


<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的方式 詳細(xì)信息(如: hilo的表名和字段)
C. 屬性—字段
使用hibernate API(FruitManager.java):
package Yuchen.fristHbn.business.Biz;
//業(yè)務(wù)邏輯類:負(fù)責(zé)增刪改查通過(guò)使用hibernate API進(jìn)行
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();//檢查事務(wù)開(kāi)啟
session.save(fruit);//存儲(chǔ)insert
tt.commit();//提交
session.close();//關(guān)閉資源
}
}
寫測(cè)試類: 插入一個(gè)對(duì)象到數(shù)據(jù)庫(kù)中
/**
* 知識(shí)點(diǎn):
* hibernate基礎(chǔ):練習(xí)語(yǔ)法部分API和簡(jiǎn)單的映射關(guān)系
* 程序目標(biāo):
* 使用hibernate方法將對(duì)象進(jìn)行持久化
* 實(shí)現(xiàn)數(shù)據(jù)庫(kù)的增刪改查
* API:
* 1.Configuration:這個(gè)類負(fù)責(zé)讀取XML文檔(映射配置文件)
* configure():讀xml
* buildSessionFactory():創(chuàng)建一個(gè)生產(chǎn)session對(duì)象的工廠,其實(shí)是再次檢查
* 因?yàn)閔ibernate和jdbc不一樣,jdbc是如果不手動(dòng)設(shè)置開(kāi)啟事務(wù),那它
* 就是馬上執(zhí)行sql的,hibernate的不會(huì)馬上執(zhí)行,是事務(wù)提交后執(zhí)行
* 默認(rèn)情況下就是打開(kāi)事務(wù)的狀態(tài),這里只是再檢查以下
* 2.SessionFactory:負(fù)責(zé)生產(chǎn)session對(duì)象
* openSession():創(chuàng)建一個(gè)session
* 3.Session類:這個(gè)是主要的類,負(fù)責(zé)增刪改查,開(kāi)啟事務(wù)等
* beginTransaction():產(chǎn)生一個(gè)事務(wù)對(duì)象(Transaction)
* save():增加相當(dāng)于操作sql中的insert語(yǔ)句
* 4.Transaction類:負(fù)責(zé)管理事務(wù)的
* commit():提交一個(gè)事務(wù)
*
*/
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 自動(dòng)生成方法存根
Test t=new Test();
t.test1();
}
}
hibernate API(一):
Configuration: 讀取配置文件信息用來(lái)初始化的
SessionFactory: 重量級(jí)對(duì)象,特點(diǎn):消耗資源大,線程是安全,所以可以被共享
上面兩個(gè)對(duì)象只實(shí)例化一個(gè)就行了,都是用于初始化的
Session: 線程是不安全的,所以要避免多個(gè)線程共享它,是輕量級(jí)的對(duì)象,使用后關(guān)閉
Session對(duì)象的狀態(tài):
順態(tài): 還沒(méi)有被持久化,也就是說(shuō)數(shù)據(jù)庫(kù)中沒(méi)有該對(duì)象的記錄,并且Session中的緩沖區(qū)里沒(méi)有這個(gè)對(duì)象的引用
持久態(tài): 在數(shù)據(jù)庫(kù)中有該對(duì)象的記錄,并且在session中的緩沖區(qū)里有這個(gè)對(duì)象的引用,和順態(tài)正好相反
游離態(tài): 在數(shù)據(jù)庫(kù)中有記錄,但是不在session的緩沖區(qū)里
對(duì)象狀態(tài)的轉(zhuǎn)換:
做一個(gè)工具類,將hibernate中重復(fù)的代碼包裝起來(lái):
package Yuchen.fristHbn.util;
//生產(chǎn)session對(duì)象的工具類
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;
//業(yè)務(wù)邏輯類:負(fù)責(zé)增刪改查通過(guò)使用hibernate API進(jìn)行
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();//通過(guò)工具更方便了
Integer id=null;
// Configuration config=new Configuration();
// config.configure();//讀配置文件
// SessionFactory sf=config.buildSessionFactory();//得到工廠
// Session session=sf.openSession();//得到session
Transaction tt=session.beginTransaction();//檢查事務(wù)開(kāi)啟
id=(Integer)session.save(fruit);//存儲(chǔ)insert
tt.commit();//提交
session.close();//關(guān)閉資源
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();
}
}
測(cè)試對(duì)象狀態(tài)的轉(zhuǎn)換:
/**
* 知識(shí)點(diǎn):
* hibernate基礎(chǔ):練習(xí)語(yǔ)法部分API和簡(jiǎn)單的映射關(guān)系
* 程序目標(biāo):
* 使用hibernate方法將對(duì)象進(jìn)行持久化
* 實(shí)現(xiàn)數(shù)據(jù)庫(kù)的增刪改查
* API:
* 1.Configuration:這個(gè)類負(fù)責(zé)讀取XML文檔(映射配置文件)
* configure():讀xml
* buildSessionFactory():創(chuàng)建一個(gè)生產(chǎn)session對(duì)象的工廠,其實(shí)是再次檢查
* 因?yàn)閔ibernate和jdbc不一樣,jdbc是如果不手動(dòng)設(shè)置開(kāi)啟事務(wù),那它
* 就是馬上執(zhí)行sql的,hibernate的不會(huì)馬上執(zhí)行,是事務(wù)提交后執(zhí)行
* 默認(rèn)情況下就是打開(kāi)事務(wù)的狀態(tài),這里只是再檢查以下
* 2.SessionFactory:負(fù)責(zé)生產(chǎn)session對(duì)象
* openSession():創(chuàng)建一個(gè)session
* 3.Session類:這個(gè)是主要的類,負(fù)責(zé)增刪改查,開(kāi)啟事務(wù)等
* beginTransaction():產(chǎn)生一個(gè)事務(wù)對(duì)象(Transaction)
* save():增加相當(dāng)于操作sql中的insert語(yǔ)句
* 4.Transaction類:負(fù)責(zé)管理事務(wù)的
* commit():提交一個(gè)事務(wù)
* test1():測(cè)試插入的功能
* test2():測(cè)試數(shù)據(jù)同步更新的功能
* test3():測(cè)試saveOrUpdate()
* test4():測(cè)試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(){
//測(cè)試同步更新的功能
Fruit fruit=new Fruit("meigui","hongse",70);//順態(tài)
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");//這里修改了對(duì)象
fruit2=fm.selectId(id);
System.out.println(fruit2.getFid());//但是結(jié)果沒(méi)有更新
System.out.println(fruit2.getName());
//因?yàn)閒ruit在Integer id=fm.insert(fruit);后變成游離態(tài)了
//也就是說(shuō)只有持久態(tài)才能實(shí)現(xiàn)同步更新
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);//順態(tài)
Fruit fruit2=new Fruit();
FruitManager fm=new FruitManager();
session.save(fruit);//fruit在運(yùn)行完此句后變?yōu)橛坞x態(tài)
fruit2=(Fruit) session.get(Fruit.class, fruit.getFid());
//從數(shù)據(jù)庫(kù)讀并打印出來(lái)
System.out.println(fruit2.getFid()+":"+fruit2.getName());
session.saveOrUpdate(fruit);//如果該對(duì)象為游歷態(tài)就更新數(shù)據(jù)庫(kù)update
//否則就是順態(tài),增加insert
fruit2=(Fruit) session.get(Fruit.class, fruit.getFid());
//saveOrUpdate后再?gòu)臄?shù)據(jù)庫(kù)讀并打印出來(lái)
System.out.println(fruit2.getFid()+":"+fruit2.getName());
//兩個(gè)打印結(jié)果一樣,saveOrUpdate方法判斷如果id為null,就
//順態(tài),否則就是游離態(tài)
t.commit();
session.close();
}
public void test4(){
Session session=HbnUtil.getSession();
Transaction t=session.beginTransaction();
Fruit fruit=new Fruit("guihua","fense",300);//順態(tài)
Fruit fruit2=new Fruit();
session.saveOrUpdate(fruit);//執(zhí)行insert因?yàn)閷?duì)象為順態(tài)
// session.flush();
session.clear();//fruit變成游離態(tài)了,并且不會(huì)執(zhí)行insert語(yǔ)句
//因?yàn)閔ibernate不是馬上執(zhí)行sql,而是等t.commit()提交事務(wù)
//后才執(zhí)行,clear后,對(duì)象為游離態(tài)
session.saveOrUpdate(fruit);//這里驗(yàn)證上面的話,執(zhí)行update
//做個(gè)select查看一下,可以證明,因?yàn)閏lear后,沒(méi)有馬上執(zhí)行
//sql語(yǔ)句,所以表里沒(méi)有數(shù)據(jù),這里update也沒(méi)有用,所以表中
//一個(gè)對(duì)象也沒(méi)插入,但是如果加入flush()刷新就是馬上執(zhí)行sql了
t.commit();
session.close();
}
public static void main(String[] args) {
// TODO 自動(dòng)生成方法存根
Test t=new Test();
// t.test1();
// t.test2();
// t.test3();
t.test4();
}
}
hibernate API(二):
flush(): 從上面的例子可以看出,flush是刷新session的緩沖區(qū),并執(zhí)行里面的命令
flush()的事務(wù)管理模式: flushMode()里面有三個(gè)常量,可以用數(shù)字來(lái)表示
Load(): 另一種讀取數(shù)據(jù)的方法,和get的區(qū)別是: 1.異常處理: load有異常處理,get沒(méi)有,它返回null,2.get從數(shù)據(jù)庫(kù)讀數(shù)據(jù),load可能去讀緩沖區(qū)
事務(wù)的隔離級(jí)別:
在hibernate的數(shù)據(jù)庫(kù)配置文件中設(shè)置
數(shù)字1為可以臟讀,數(shù)字2為不能,這個(gè)是最常用的
鎖機(jī)制:
避免并發(fā)沖突,在數(shù)據(jù)庫(kù)中寫數(shù)據(jù)是自動(dòng)加鎖的,讀一般不加,有悲觀鎖和樂(lè)觀鎖
樂(lè)觀鎖是可以是hibernate程序自己加
實(shí)現(xiàn)樂(lè)觀鎖: 引例(hbn2包)
步驟:
1. 在表中加個(gè)version字段
2. 在持久類里加個(gè)version屬性
3. 配置文件<version name=”versopm”> 每存一次值加1
引例:hbn2包
復(fù)雜的映射:
1. 基數(shù)關(guān)系映射
2. 繼承關(guān)系映射
3. 組件關(guān)系映射
4. 集合映射
基數(shù)關(guān)系的映射—one to one:
基數(shù)關(guān)系的映射需要考慮的問(wèn)題:
1. 數(shù)量問(wèn)題
2. 方向問(wèn)題
在one to one的關(guān)系中,我們有兩種方法可以體現(xiàn)類與類之間的關(guān)系
1. 共享主鍵
2. 外鍵唯一
引例: Joto包-此包引用了fristHbn包
建立與Fruit類有一對(duì)一關(guān)系的類:
我們認(rèn)為一個(gè)花有一個(gè)產(chǎn)地,一個(gè)產(chǎn)地生產(chǎn)一種花,所以要建立產(chǎn)地類
package Yuchen.Joto.business.entity;
//花的地址類
//問(wèn)題:為什么不能在構(gòu)造函數(shù)中寫Fruit?因?yàn)樯蓪?duì)象后要持久化
//這個(gè)對(duì)象,但是數(shù)據(jù)庫(kù)的表中不能插入另一個(gè)類的值,寫上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;
//持久化類(花類),注意因?yàn)椴捎玫氖莌ilo的方式獲得id,所以需要有setid的方法
public class Fruit {
private Integer fid;//hibernate中的id不能識(shí)別int
private String name;
private String comments;
private int price;
private Address address;//一朵花對(duì)應(yīng)一個(gè)地址
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);//因?yàn)楫?dāng)你給一個(gè)花設(shè)置產(chǎn)地的時(shí)候
//該產(chǎn)地也有了花
}
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)
|