目錄
1. Hibernate框架的概述
- 1.1 Hibernate簡介
- 1.2 為什么要學(xué)習(xí)Hibernate
- 1.3 Hibernate版本
2. Hibernate的日志記錄
3. Hibernate入門
- 3.1 Hibernate框架目錄結(jié)構(gòu)
- 3.2 Hibernate入門實(shí)例
4. Hibernate的CURD操作
- 4.1 保存記錄
- 4.2 根據(jù)主鍵進(jìn)行查詢
- 4.3 修改記錄
- 4.4 刪除記錄
- 4.5 查詢所有
5. Hibernate配置
- 5.1 核心配置文件hibernate.cfg.xml
- 5.2 映射文件的配置Customer.hbm.xml
6. Hibernate的核心API
- 6.1 Configuration
- 6.2 SessionFactory
- 6.3 Session
- 6.4 Transaction
- 6.5 Query
- 6.6 Criteria
Hibernate中的持久化類
Hibernate框架的概述
Hibernate簡介
Hibernate是一個開放源代碼的對象關(guān)系映射框架,它對JDBC進(jìn)行了非常輕量級的對象封裝,使得Java程序員可以隨心所欲的使用對象編程思維來操縱數(shù)據(jù)庫。 Hibernate可以應(yīng)用在任何使用JDBC的場合,既可以在Java的客戶端程序使用扇苞,也可以在Servlet/JSP的Web應(yīng)用中使用,最具革命意義的是,Hibernate可以在應(yīng)用EJB的J2EE架構(gòu)中取代CMP勺阐,完成數(shù)據(jù)持久化的重任。
Hibernate是輕量級JavaEE應(yīng)用的持久層解決方案矛双,是一個關(guān)系數(shù)據(jù)庫ORM框架.ORM:Object Relational Mapping渊抽,將Java中的實(shí)體類與數(shù)據(jù)庫的關(guān)系表建立一個映射.就可以操作Java中對象,從而操作數(shù)據(jù)庫.
為什么要學(xué)習(xí)Hibernate
- Hibernate對JDBC訪問數(shù)據(jù)庫的代碼做了封裝,大大簡化了數(shù)據(jù)訪問層繁瑣的重復(fù)性代碼
- Hibernate是一個基于jdbc的主流持久化框架议忽,是一個優(yōu)秀的orm實(shí)現(xiàn)懒闷,它很大程度的簡化了dao層編碼工作
- Hibernate使用java的反射機(jī)制,而不是字節(jié)碼增強(qiáng)程序類實(shí)現(xiàn)透明性
- Hibernate的性能非常好栈幸,因?yàn)樗且粋€輕量級框架愤估。映射的靈活性很出色固歪。它支持很多關(guān)系型數(shù)據(jù)庫仇轻,從一對一到多對多的各種復(fù)雜關(guān)系.
Hibernate版本
Hibernate3.x版本 和 Hibernate4.x
** 企業(yè)中常用的還是Hibernate3.x.**
Hibernate的日志記錄
在hibernate使用的日志標(biāo)準(zhǔn)都為slf,slf可以看作為它的接口募疮,因此需要找到它的實(shí)例芍锚,為我們做日志昔园,我們選擇使用log4j為實(shí)例。
需要導(dǎo)入log4j-1.2.16.jar和slf4j-log4j12-1.7.2.jar
編寫property文件(log4J的配置信息)參考模板在如下位置 Hibernate_HOME/project/etc 示例中可以將log4j.properties文件拷貝出來進(jìn)行修改放在項(xiàng)目中的classPath即src下
Hibernate入門
Hibernate框架目錄結(jié)構(gòu)
Hibernate入門實(shí)例
- 創(chuàng)建一個Java工程并炮,導(dǎo)入相應(yīng)的jar包和配置文件
- hibernate3.jar (核心jar包)
- antlr-2.7.6.jar (必選jar包)
- commons-collections-3.1.jar
- dom4j-1.6.1.jar
- javassist-3.12.0.GA.jar
- jta-1.1.jar
- slf4j-api-1.6.1.jar
- hibernate-jpa-2.0-api-1.0.1.Final.jar(實(shí)現(xiàn)jpa規(guī)范jar包)
- slf4j-log4j12-1.7.2.jar (日志記錄jar包)
- log4j-1.2.16.jar
- mysql-connector-java-5.0.4-bin.jar(數(shù)據(jù)庫驅(qū)動jar包)
- log4j.properties(日志配置文件放到src下)
- 創(chuàng)建一個表
create database hibernate3_day01;
use hibernate3_day01;
create table customer(
id int primary key auto_increment,
name varchar(20),
age int
);
- 創(chuàng)建一個實(shí)體類
public class Customer {
private int id;
private String name;
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
- 創(chuàng)建一個ORM映射文件
映射文件只要是一個XML格式文件就可以.名字任意,跟需要映射的類放在一個包下
通常情況下名稱規(guī)范:實(shí)體類名稱.hbm.xml
引入約束:hibernate3.jar/org.hibernate.hibernate-mapping-3.0.dtd
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<!-- 建立類與表的映射 -->
<!-- class標(biāo)簽:用于映射類與表的關(guān)系 name :類的全路徑 table:表名稱 -->
<class name="com.java.hibernate3.demo1.Customer" table="customer">
<!-- 建立類中屬性與表中的字段映射 -->
<!-- 唯一標(biāo)識 -->
<!-- 使用id的標(biāo)簽 配置唯一屬性 -->
<!-- 在<id>標(biāo)簽中配置一個主鍵的生成策略. -->
<id name="id" column="id">
<generator class="native"/>
</id>
<!-- 普通屬性 -->
<!-- property標(biāo)簽:映射類中的普通屬性 name:類中的屬性名稱, column:表中字段名稱 -->
<!--
type:三種寫法
* Java類型 :java.lang.String
* Hibernate類型 :string
* SQL類型 :不能直接使用type屬性,需要子標(biāo)簽<column>
* <column name="name" sql-type="varchar(20)"/>
-->
<property name="name" column="name" type="string"/>
<property name="age" column="age"/>
</class>
</hibernate-mapping>
- 創(chuàng)建hibernate核心配置文件
通知Hibernate連接是哪個數(shù)據(jù)庫,在src下創(chuàng)建一個hibernate.cfg.xml
<hibernate-configuration>
<session-factory>
<!-- 必須去配置的屬性 -->
<!-- 配置數(shù)據(jù)庫連接的基本信息: -->
<property name="hibernate.connection.driver_class">
com.mysql.jdbc.Driver
</property>
<property name="hibernate.connection.url">
jdbc:mysql:///hibernate3_day01
</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">123</property>
<!-- Hibernate的方言 -->
<!-- 生成底層SQL不同的 -->
<property name="hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</property>
<!-- 可選的屬性 -->
<!-- 顯示SQL -->
<property name="hibernate.show_sql">true</property>
<!-- 格式化SQL -->
<property name="hibernate.format_sql">true</property>
<!-- hbm:映射 to DDL: create drop alter -->
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- 通知Hibernate加載那些映射文件 -->
<mapping resource="com/java/hibernate3/demo1/Customer.hbm.xml" />
</session-factory>
</hibernate-configuration>
- 測試
@Test
// 向數(shù)據(jù)庫中插入一條記錄
public void demo1(){
// 1.Hiberante框架加載核心配置文件(有數(shù)據(jù)庫連接信息)
Configuration configuration = new Configuration().configure();
// 2.創(chuàng)建一個SessionFactory.(獲得Session--相當(dāng)連接對象)
SessionFactory sessionFactory = configuration.buildSessionFactory();
// 3.獲得Session對象.
Session session = sessionFactory.openSession();
// 4.默認(rèn)的情況下,事務(wù)是不自動提交.
Transaction tx = session.beginTransaction();
// 5.業(yè)務(wù)邏輯操作
// 向數(shù)據(jù)庫中插入一條記錄:
Customer customer = new Customer();
customer.setName("小明");
customer.setAge(18);
session.save(customer);
// 6.事務(wù)提交
tx.commit();
// 7.釋放資源
session.close();
sessionFactory.close();
}
Hibernate的CURD操作
- 保存記錄
session.save(customer);
- 根據(jù)主鍵查詢
Customer customer = (Customer)session.get(Customer.class ,1);
Customer customer = (Customer)session.load(Customer.class,1);
get 和load的區(qū)別
① 發(fā)送SQL的時機(jī):
load這個方法采用了一個技術(shù).lazy延遲加載(懶加載).真正使用這個對象的數(shù)據(jù)的時候.(對象的數(shù)據(jù)不包括主鍵).
get這個方法是立即檢索.當(dāng)執(zhí)行session.get()方法的時候,馬上發(fā)送SQL語句查詢.
② 返回的對象:
load方法返回的是代理對象.
get方法返回的是真實(shí)的對象.
③ 查詢一個不存在的數(shù)據(jù):
load方法拋異常:ObjectNotFoundException.
get方法拋異常:NullPointException.
- 修改記錄
session.update(customer);
修改有兩種方式 :
手動創(chuàng)建對象的方式
Customer customer = new Customer();
customer.setId(2);
customer.setName("蒼老師");
session.update(customer);
這種方式如果沒有設(shè)置的屬性,會將這個屬性的默認(rèn)值存入了
先查詢在修改的方式(推薦方式)
Customer customer = (Customer) session.get(Customer.class, 1);
customer.setName("鳳姐");
session.update(customer);
- 刪除記錄
session.delete(customer);
刪除記錄有兩種方式:
手動創(chuàng)建對象的方式
Customer customer = new Customer();
customer.setId(2);
session.delete(customer);
先查詢在刪除的方式
Customer customer = (Customer)session.get(Customer.class, 1);
session.delete(customer);
- 查詢所有
HQL:
HQL:Hibernate Query Language.
面向?qū)ο蟮膶懛?
Query query = session.createQuery("from Customer where name = ?");
query.setParameter(0, "蒼老師");
Query.list();
QBC:
Query By Criteria.(條件查詢)
Criteria criteria = session.createCriteria(Customer.class);
criteria.add(Restrictions.eq("name", "小明"));
List<Customer> list = criteria.list();
SQL:
SQLQuery query = session.createSQLQuery("select * from customer");
List<Object[]> list = query.list();
SQLQuery query = session.createSQLQuery("select * from customer");
query.addEntity(Customer.class);
List<Customer> list = query.list();
Hibernate配置和核心API
核心配置文件hibernate.cfg.xml
核心配置有兩種方式進(jìn)行配置:
- 屬性文件的配置:
hibernate.properties 格式:key=value
hibernate.connection.driver_class=com.mysql.jdbc.Driver
注意:沒有辦法在核心配置文件中加載映射文件.(必須手動編碼的方式進(jìn)行加載.) - XML格式文件配置:
hibernate.cfg.xml 格式:<property name="hibernate.connection.username">root</property>
在核心配置中:
- 必須的配置:
連接數(shù)據(jù)庫4個基本參數(shù):
hibernate.connection.driver_class 連接數(shù)據(jù)庫驅(qū)動程序
hibernate.connection.url 連接數(shù)據(jù)庫URL
hibernate.connection.username 數(shù)據(jù)庫用戶名
hibernate.connection.password 數(shù)據(jù)庫密碼
Hibernate的方言:
hibernate.dialect 操作數(shù)據(jù)庫方言 - 可選的配置:
hibernate.show_sql true 在控制臺上輸出SQL語句
hibernate.format_sql true 格式化控制臺輸出的SQL語句
hibernate.connection.autocommit true 事務(wù)是否自動提交
hibernate.hbm2ddl.auto create/create-drop/update/validate 4個選項(xiàng)
- create:每次執(zhí)行的時候,創(chuàng)建一個新的表.(如果以前有該表,將該表刪除重新創(chuàng)建.) 一般測試的時候的使用.
- create-drop:每次執(zhí)行的時候,創(chuàng)建一個新的表,程序執(zhí)行結(jié)束后將這個表,刪除掉了. 一般測試的時候使用.
- update:如果數(shù)據(jù)庫中沒有表,創(chuàng)建一個新的表,如果有了,直接使用這個表.可以更新表的結(jié)構(gòu).
- validate:會使用原有的表.完成校驗(yàn).校驗(yàn)映射文件與表中配置的字段是否一致.不一致報錯.
3.映射的配置:
在核心配置文件中加載映射文件:
<mapping resource="com/java/hibernate3/demo1/Customer.hbm.xml" />
映射文件的配置Customer.hbm.xml
ORM:對象和關(guān)系映射默刚,配置Java對象與數(shù)據(jù)庫表的映射。
配置類與表的映射:
name:類的全路徑逃魄,table:表的名稱:(可以省略的.使用類的名稱作為表名.)
<class name="cn.itcast.hibernate3.demo1.Order" table=”orders”>配置普通屬性與字段映射:
<property name="name" column="name" type="string" length=”20”/>
type:三種寫法
- Java類型:java.lang.String
- Hibernate類型:string
- SQL類型:不能直接使用type屬性,需要子標(biāo)簽
<column><column name="name" sql-type="varchar(20)"/>
- 配置唯一標(biāo)識與主鍵映射:
一個表中只有一個主鍵的形式:
<id name=”id” column=”id”></id>
一個表對應(yīng)多個主鍵形式:(復(fù)合主鍵:)---了解.
<composite-id></composite-id>
Hibernate的核心API
Configuration:負(fù)責(zé)管理 Hibernate 的配置信息
- 加載核心配置文件:
核心配置有兩種:
- hibernate.properties:
加載:Configuration configuration = new Configuration(); - hibernate.cfg.xml:
加載:Configuration configuration = new Configuration().configure();
- properties手動加載映射文件:
- 第一種寫法:
configuration.addResource("cn/itcast/hibernate3/demo1/Customer.hbm.xml"); - 第二種寫法:(要求:映射文件名稱要規(guī)范,類與映射在同一個包下)
configuration.addClass(Customer.class);
SessionFactory:Session工廠
Configuration對象根據(jù)當(dāng)前的配置信息生成 SessionFactory對象
SessionFactory對象中保存了當(dāng)前的數(shù)據(jù)庫配置信息和所有映射關(guān)系以及預(yù)定義的SQL語句
SessionFactory對象是線程安全的
SessionFactory還負(fù)責(zé)維護(hù)Hibernate的二級緩存
SessionFactory對象根據(jù)數(shù)據(jù)庫信息,維護(hù)連接池,創(chuàng)建Session(相當(dāng)于Connection)對象.
抽取工具類
public class HibernateUtils {
private static Configuration configuration;
private static SessionFactory sessionFactory;
static{
configuration = new Configuration().configure();
sessionFactory = configuration.buildSessionFactory();
}
public static Session openSession(){
return sessionFactory.openSession();
}
public static void main(String[] args) {
openSession();
}
}
在Hibernate中使用c3p0連接池:
- 引入c3p0的jar包
- 在核心配置hibernate.cfg.xml中添加一段配置:
<!-- C3P0連接池設(shè)定-->
<!-- 使用c3po連接池 配置連接池提供的供應(yīng)商-->
<propertyname="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
<!--在連接池中可用的數(shù)據(jù)庫連接的最少數(shù)目 -->
<property name="c3p0.min_size">5</property>
<!--在連接池中所有數(shù)據(jù)庫連接的最大數(shù)目 -->
<property name="c3p0.max_size">20</property>
<!--設(shè)定數(shù)據(jù)庫連接的過期時間,以秒為單位,
如果連接池中的某個數(shù)據(jù)庫連接處于空閑狀態(tài)的時間超過了timeout時間,就會從連接池中清除 -->
<property name="c3p0.timeout">120</property>
<!--每3000秒檢查所有連接池中的空閑連接 以秒為單位-->
<property name="c3p0.idle_test_period">3000</property>
Session:相當(dāng)于JDBC的Connection
Session 是應(yīng)用程序與數(shù)據(jù)庫之間交互操作的一個單線程對象荤西,是 Hibernate 運(yùn)作的中心
Session是線程不安全的
所有持久化對象必須在 session 的管理下才可以進(jìn)行持久化操作
Session 對象有一個一級緩存,顯式執(zhí)行 flush 之前嗅钻,所有的持久化操作的數(shù)據(jù)都緩存在 session 對象處
持久化類與 Session 關(guān)聯(lián)起來后就具有了持久化的能力
Session維護(hù)了Hiberante一級緩存.
save()/persist() :添加.
update() :修改
saveOrUpdate() :增加和修改對象
delete() :刪除對象
get()/load() :根據(jù)主鍵查詢
createQuery() :創(chuàng)建一個Query接口,編寫HQL語句
createSQLQuery() :創(chuàng)建一個SQLQuery接口,編寫SQL語句數(shù)據(jù)庫操作對象
createCriteria() :返回一個Criteria接口.條件查詢
Transaction
獲得:Transaction tx = session.beginTransaction();
常用方法:
commit() :提交相關(guān)聯(lián)的session實(shí)例
rollback() :撤銷事務(wù)操作
wasCommitted():檢查事務(wù)是否提交
如果沒有開啟事務(wù)皂冰,那么每個Session的操作,都相當(dāng)于一個獨(dú)立的事務(wù)
Query
Query代表面向?qū)ο蟮囊粋€Hibernate查詢操作
session.createQuery 接受一個HQL語句
HQL是Hibernate Query Language縮寫养篓, 語法很像SQL語法秃流,但是完全面向?qū)ο蟮?/p>
Criteria:條件查詢
Hibernate中的持久化類
持久化類=實(shí)體類 + 映射文件.
持久化類是有編寫規(guī)范
- 提供一個無參數(shù) public訪問控制符的構(gòu)造器 :用到反射.
- 提供一個標(biāo)識屬性,映射數(shù)據(jù)表主鍵字段 :
- java區(qū)分兩個對象是否是同一個:使用地址.
- 數(shù)據(jù)庫區(qū)分兩條記錄是否一致:使用主鍵.
- Hibernate中區(qū)分持久化對象是否是同一個,根據(jù)唯一標(biāo)識:
- 所有屬性提供public訪問控制符的 set get 方法 :框架中存值和取值的時候使用.
- 標(biāo)識屬性應(yīng)盡量使用基本數(shù)據(jù)類型的包裝類型(默認(rèn)值為null而不是0)
- 持久化類盡量不要使用final進(jìn)行修飾:用final修飾的類是不能被繼承.無法生成代理對象.(延遲加載的時候返回代理對象.延遲加載就失效.)
建表的時候:
- 自然主鍵:
創(chuàng)建一個人員表.人員表中某條記錄唯一確定.人都有身份證號.我們可以使用身份證號作為主鍵.(身份證號本身就是人員的一個屬性.作為主鍵.) - 代理主鍵:
創(chuàng)建一個人員表.人員表中某條記錄唯一確定.但是沒有使用身份證號作為主鍵,新建字段(用新建的字段作為主鍵.只是一個標(biāo)識作用.)
盡量要Hibernate自己去維護(hù)主鍵:
主鍵的生成策略:
- increment:自動增長.適合 short int long...不是使用數(shù)據(jù)庫的自動增長機(jī)制.使用Hibernate框架提供的自動增長方式.
- select max(id) from 表; 在最大值的基礎(chǔ)上+1.(多線程的問題.)在集群下不要使用
- identity :自動增長.適合 short int long...采用數(shù)據(jù)庫的自動增長機(jī)制.不適合于Oracle數(shù)據(jù)庫.
- sequence :序列.適用于 short int long ... 應(yīng)用在Oracle上 .
- uuid :適用于字符串類型的主鍵.采用隨機(jī)的字符串作為主鍵.
- native :本地策略.底層數(shù)據(jù)庫不同.自動選擇適用identity 還是 sequence.
- assigned :Hibernate框架不維護(hù)主鍵,主鍵由程序自動生成.
- foreign :主鍵的外來的.(應(yīng)用在多表一對一的關(guān)系.)