1. Hibernate是什么
1.1 框架是什么
- 1.框架是用來提高開發(fā)效率的
- 2.封裝了好了一些功能.我們需要使用這些功能時,調用即可.不需要再手動實現(xiàn).
- 3.所以框架可以理解成是一個半成品的項目.只要懂得如何駕馭這些功能即可.
1.2 hibernate框架是什么
1.3 hibernate的好處
操作數(shù)據(jù)庫的時候,可以以面向對象的方式來完成.不需要書寫SQL語句
1.4 hibernate是一款orm框架
-
ORM:object relationg mapping. 對象關系映射
ORM之Hibernate - orm分4級
- hibernate屬于4級:完全面向對象操作數(shù)據(jù)庫
- mybatis屬于2級
- dbutils屬于1級
2 Hibernate框架的搭建
2.1 導包
- 下載hibernate-release-5.2.12.Final.zip
-
解壓脓杉,復制導入hibernate-release-5.2.12.Final\lib\required目錄下的所有jar包
hibernate核心jar包 - MySQL驅動包:mysql-connector-java-5.1.40-bin.jar
2.2 創(chuàng)建數(shù)據(jù)庫莲祸、表、實體
- 創(chuàng)建數(shù)據(jù)庫
hibernate_32
- 創(chuàng)建表
CREATE TABLE `cst_customer` (
`cust_id` BIGINT(32) NOT NULL AUTO_INCREMENT COMMENT '客戶編號(主鍵)',
`cust_name` VARCHAR(32) NOT NULL COMMENT '客戶名稱(公司名稱)',
`cust_source` VARCHAR(32) DEFAULT NULL COMMENT '客戶信息來源',
`cust_industry` VARCHAR(32) DEFAULT NULL COMMENT '客戶所屬行業(yè)',
`cust_level` VARCHAR(32) DEFAULT NULL COMMENT '客戶級別',
`cust_linkman` VARCHAR(64) DEFAULT NULL COMMENT '聯(lián)系人',
`cust_phone` VARCHAR(64) DEFAULT NULL COMMENT '固定電話',
`cust_mobile` VARCHAR(16) DEFAULT NULL COMMENT '移動電話',
PRIMARY KEY (`cust_id`)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
- Customer.java
public class Customer {
private Long cust_id;
private String cust_name;
private String cust_source;
private String cust_industry;
private String cust_level;
private String cust_linkman;
private String cust_phone;
private String cust_mobile;
public Long getCust_id() {
return cust_id;
}
public void setCust_id(Long cust_id) {
this.cust_id = cust_id;
}
public String getCust_name() {
return cust_name;
}
public void setCust_name(String cust_name) {
this.cust_name = cust_name;
}
public String getCust_source() {
return cust_source;
}
public void setCust_source(String cust_source) {
this.cust_source = cust_source;
}
public String getCust_industry() {
return cust_industry;
}
public void setCust_industry(String cust_industry) {
this.cust_industry = cust_industry;
}
public String getCust_level() {
return cust_level;
}
public void setCust_level(String cust_level) {
this.cust_level = cust_level;
}
public String getCust_linkman() {
return cust_linkman;
}
public void setCust_linkman(String cust_linkman) {
this.cust_linkman = cust_linkman;
}
public String getCust_phone() {
return cust_phone;
}
public void setCust_phone(String cust_phone) {
this.cust_phone = cust_phone;
}
public String getCust_mobile() {
return cust_mobile;
}
public void setCust_mobile(String cust_mobile) {
this.cust_mobile = cust_mobile;
}
@Override
public String toString() {
return "Customer [cust_id=" + cust_id + ", cust_name=" + cust_name + "]";
}
}
2.3 書寫orm元數(shù)據(jù)(對象實體Customer與數(shù)據(jù)庫表cst_customer的映射配置文件)
- Customer.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- 配置表與實體對象的關系 -->
<!-- package屬性:填寫一個包名.在元素內部凡是需要書寫完整類名的屬性,可以直接寫簡答類名了. -->
<hibernate-mapping package="domain" >
<!--
class元素: 配置實體與表的對應關系的
name: 完整類名
table:數(shù)據(jù)庫表名
-->
<class name="Customer" table="cst_customer" >
<!-- id元素:配置主鍵映射的屬性
name: 填寫主鍵對應屬性名
column(可選): 填寫表中的主鍵列名.默認值:列名會默認使用屬性名
type(可選):填寫列(屬性)的類型.hibernate會自動檢測實體的屬性類型.
每個類型有三種填法: java類型|hibernate類型|數(shù)據(jù)庫類型
not-null(可選):配置該屬性(列)是否不能為空. 默認值:false
length(可選):配置數(shù)據(jù)庫中列的長度. 默認值:使用數(shù)據(jù)庫類型的最大長度
-->
<id name="cust_id" >
<!-- generator:主鍵生成策略(明天講) -->
<generator class="native"></generator>
</id>
<!-- property元素:除id之外的普通屬性映射
name: 填寫屬性名
column(可選): 填寫列名
type(可選):填寫列(屬性)的類型.hibernate會自動檢測實體的屬性類型.
每個類型有三種填法: java類型|hibernate類型|數(shù)據(jù)庫類型
not-null(可選):配置該屬性(列)是否不能為空. 默認值:false
length(可選):配置數(shù)據(jù)庫中列的長度. 默認值:使用數(shù)據(jù)庫類型的最大長度
-->
<property name="cust_name" column="cust_name" >
<!-- <column name="cust_name" sql-type="varchar" ></column> -->
</property>
<property name="cust_source" column="cust_source" ></property>
<property name="cust_industry" column="cust_industry" ></property>
<property name="cust_level" column="cust_level" ></property>
<property name="cust_linkman" column="cust_linkman" ></property>
<property name="cust_phone" column="cust_phone" ></property>
<property name="cust_mobile" column="cust_mobile" ></property>
</class>
</hibernate-mapping>
2.4 書寫hibernate主配置文件
- hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!--
#hibernate.dialect org.hibernate.dialect.MySQLDialect
#hibernate.dialect org.hibernate.dialect.MySQLInnoDBDialect
#hibernate.dialect org.hibernate.dialect.MySQLMyISAMDialect
#hibernate.connection.driver_class com.mysql.jdbc.Driver
#hibernate.connection.url jdbc:mysql:///test
#hibernate.connection.username gavin
#hibernate.connection.password
-->
<!-- 數(shù)據(jù)庫驅動 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<!-- 數(shù)據(jù)庫url -->
<property name="hibernate.connection.url">jdbc:mysql:///hibernate_32</property>
<!-- 數(shù)據(jù)庫連接用戶名 -->
<property name="hibernate.connection.username">root</property>
<!-- 數(shù)據(jù)庫連接密碼 -->
<property name="hibernate.connection.password">root</property>
<!-- 數(shù)據(jù)庫方言
不同的數(shù)據(jù)庫中,sql語法略有區(qū)別. 指定方言可以讓hibernate框架在生成sql語句時.針對數(shù)據(jù)庫的方言生成.
sql99標準: DDL 定義語言 庫表的增刪改查
DCL 控制語言 事務 權限
DML 操縱語言 增刪改查
注意: MYSQL在選擇方言時,請選擇最短的方言.
-->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- #hibernate.show_sql true
#hibernate.format_sql true
-->
<!-- 將hibernate生成的sql語句打印到控制臺 -->
<property name="hibernate.show_sql">true</property>
<!-- 將hibernate生成的sql語句格式化(語法縮進) -->
<property name="hibernate.format_sql">true</property>
<!--
## auto schema export 自動導出表結構. 自動建表
#hibernate.hbm2ddl.auto create 自動建表.每次框架運行都會創(chuàng)建新的表.以前表將會被覆蓋,表數(shù)據(jù)會丟失.(開發(fā)環(huán)境中測試使用)
#hibernate.hbm2ddl.auto create-drop 自動建表.每次框架運行結束都會將所有表刪除.(開發(fā)環(huán)境中測試使用)
#hibernate.hbm2ddl.auto update(推薦使用) 自動生成表.如果已經存在不會再生成.如果表有變動.自動更新表(不會刪除任何數(shù)據(jù)).
#hibernate.hbm2ddl.auto validate 校驗.不自動生成表.每次啟動會校驗數(shù)據(jù)庫中表是否正確.校驗失敗.
-->
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- 引入orm元數(shù)據(jù)
路徑書寫: 填寫src下的路徑
-->
<mapping resource="domain/Customer.hbm.xml" />
</session-factory>
</hibernate-configuration>
2.5 使用測試
- TestHibernate.java
package hello;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.Test;
import domain.Customer;
public class TestHibernate {
@Test
public void test(){
Configuration conf = new Configuration().configure();
SessionFactory sessionFactory = conf.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
//---------------
Customer c = new Customer();
c.setCust_name("伊爾");
session.save(c);
//---------------
transaction.commit();
session.close();
sessionFactory.close();
}
}
-
運行測試
第一次使用Hibernate
3. 配置文件詳解
3.1 orm元數(shù)據(jù)(Customer.hbm.xml)
- 根元素
<!-- 配置表與實體對象的關系 -->
<!-- package屬性:填寫一個包名.在元素內部凡是需要書寫完整類名的屬性,可以直接寫簡答類名了. -->
<hibernate-mapping package="domain" >
- class元素
<!--
class元素: 配置實體與表的對應關系的
name: 完整類名
table:數(shù)據(jù)庫表名
-->
<class name="Customer" table="cst_customer" >
- id元素
<!-- id元素:配置主鍵映射的屬性
name: 填寫主鍵對應屬性名
column(可選): 填寫表中的主鍵列名.默認值:列名會默認使用屬性名
type(可選):填寫列(屬性)的類型.hibernate會自動檢測實體的屬性類型.
每個類型有三種填法: java類型|hibernate類型|數(shù)據(jù)庫類型
not-null(可選):配置該屬性(列)是否不能為空. 默認值:false
length(可選):配置數(shù)據(jù)庫中列的長度. 默認值:使用數(shù)據(jù)庫類型的最大長度
-->
<id name="cust_id" >
<!-- generator:主鍵生成策略 -->
<generator class="native"></generator>
</id>
- property元素
<!-- property元素:除id之外的普通屬性映射
name: 填寫屬性名
column(可選): 填寫列名
type(可選):填寫列(屬性)的類型.hibernate會自動檢測實體的屬性類型.
每個類型有三種填法: java類型|hibernate類型|數(shù)據(jù)庫類型
not-null(可選):配置該屬性(列)是否不能為空. 默認值:false
length(可選):配置數(shù)據(jù)庫中列的長度. 默認值:使用數(shù)據(jù)庫類型的最大長度
-->
<property name="cust_name" column="cust_name" >
<!-- <column name="cust_name" sql-type="varchar" ></column> -->
</property>
這里的<property/>
元素要說一下,引用Hibernate官方文檔的一個例子:
<property name="date" type="timestamp" column="EVENT_DATE"/> <property name="title"/>
The two
<property/>
elements declare the remaining two persistent properties of theEvent(例子中的實體類)
class:date
andtitle
. Thedate
property mapping includes thecolumn
attribute, but thetitle
does not. In the absence of a column attribute, Hibernate uses the property name as the column name. This is appropriate fortitle
, but sincedate
is a reserved keyword in most databases, you need to specify a non-reserved word for the column name.The
title
mapping also lacks a type attribute. The types declared and used in the mapping files are neither Java data types nor SQL database types. Instead, they are Hibernate mapping types, which are converters which translate between Java and SQL data types. Hibernate attempts to determine the correct conversion and mapping type autonomously if the type attribute is not specified in the mapping, by using Java reflection to determine the Java type of the declared property and using a default mapping type for that Java type.In some cases this automatic detection might not chose the default you expect or need, as seen with the
date
property. Hibernate cannot know if the property, which is of typejava.util.Date
, should map to a SQL DATE, TIME, or TIMESTAMP datatype. Full date and time information is preserved by mapping the property to the timestamp converter, which identifies the converter classorg.hibernate.type.TimestampType
.
從上面可以看出來幾點:
- column屬性是可以省略的衙傀,默認屬性名和數(shù)據(jù)庫列名一致
- type屬性也是可以省略的梢为,Hibernate會自動檢測實體屬性的類型
- 但是上述例子中的屬性date,它的column屬性不能省略弛针,因為
date
是大多數(shù)數(shù)據(jù)庫的保留關鍵字(reserved keyword)叠骑,所以要為其指定列名;而且type屬性也不能省略削茁,需要具體指定一種日期時間類型宙枷,這里使用的是Hibernate映射類型timestamp
3.2 hibernate主配置文件(hibernate.cfg.xml)
- 必選屬性配置(5個)
<!-- 數(shù)據(jù)庫驅動 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<!-- 數(shù)據(jù)庫url -->
<property name="hibernate.connection.url">jdbc:mysql:///hibernate_32</property>
<!-- 數(shù)據(jù)庫連接用戶名 -->
<property name="hibernate.connection.username">root</property>
<!-- 數(shù)據(jù)庫連接密碼 -->
<property name="hibernate.connection.password">root</property>
<!-- 數(shù)據(jù)庫方言
不同的數(shù)據(jù)庫中,sql語法略有區(qū)別. 指定方言可以讓hibernate框架在生成sql語句時.針對數(shù)據(jù)庫的方言生成.
sql99標準:DDL 定義語言 庫表的增刪改查
DCL 控制語言 事務 權限
DML 操縱語言 增刪改查
注意: MYSQL在選擇方言時,請選擇最短的方言(指下面的第一個hibernate.dialect org.hibernate.dialect.MySQLDialect).
#hibernate.dialect org.hibernate.dialect.MySQLDialect
#hibernate.dialect org.hibernate.dialect.MySQLInnoDBDialect
#hibernate.dialect org.hibernate.dialect.MySQLMyISAMDialect
-->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
- 可選屬性配置(3個)
<!-- 將hibernate生成的sql語句打印到控制臺 -->
<property name="hibernate.show_sql">true</property>
<!-- 將hibernate生成的sql語句格式化(語法縮進) -->
<property name="hibernate.format_sql">true</property>
<!--
## auto schema export 自動導出表結構. 自動建表
#hibernate.hbm2ddl.auto create
自動建表.每次框架運行都會創(chuàng)建新的表.以前表將會被覆蓋,表數(shù)據(jù)會丟失.(開發(fā)環(huán)境中測試使用)
#hibernate.hbm2ddl.auto create-drop
自動建表.每次框架運行結束都會將所有表刪除.(開發(fā)環(huán)境中測試使用)
#hibernate.hbm2ddl.auto update (推薦使用)
自動生成表.如果已經存在不會再生成.如果表有變動.自動更新表(不會刪除任何數(shù)據(jù)).
#hibernate.hbm2ddl.auto validate
校驗.不自動生成表.每次啟動會校驗數(shù)據(jù)庫中表是否正確.校驗屬性與列名是否一致掉房,校驗失敗會拋出SchemaManagementException
-->
<property name="hibernate.hbm2ddl.auto">update</property>
- 元數(shù)據(jù)引入配置
<!-- 引入orm元數(shù)據(jù)
路徑: 填寫src下的路徑
右鍵Customer.hbm.xml,復制全限定名/Hibernate_CRM/src/domain/Customer.hbm.xml,
刪除前面的/Hibernate_CRM/src/
-->
<mapping resource="domain/Customer.hbm.xml" />
4. Hibernate API詳解
4.1 Configuration
- 創(chuàng)建
Configuration conf = new Configuration();
- 加載主配置(加載src目錄下的hibernate.cfg.xml。通過查看無參
configure()
方法的源碼可以知道慰丛,實際上是直接return
了有參方法configure(String resource)
,參數(shù)賦的是默認的路徑字符串hibernate.cfg.xml
)
conf.configure();
- 加載orm元數(shù)據(jù)(早期寫法卓囚,了解即可;如果主配置文件中已經進入映射配置诅病,則不需要手動加載)
conf.addResource(resourceName);
conf.addClass(persistentClass);
- 創(chuàng)建SessionFactory實例
SessionFactory sessionFactory = conf.buildSessionFactory();
4.2 SessionFactory
- SessionFactory功能: 用于創(chuàng)建操作數(shù)據(jù)庫核心對象session對象的工廠哪亿。簡單說功能就一個---創(chuàng)建session對象
- 注意:
- sessionFactory 負責保存和使用所有配置信息.消耗內存資源非常大.
- sessionFactory 屬于線程安全的對象設計.
- 保證在web項目中,只創(chuàng)建一個sessionFactory.
- 獲得session
//打開一個新的session對象
sf.openSession();
//獲得一個與線程綁定的session對象
sf.getCurrentSession();
4.3 Session & Transaction
- session對象功能: 表達hibernate框架與數(shù)據(jù)庫之間的連接(會話).session類似于JDBC的connection對象. 還可以完成對數(shù)據(jù)庫中數(shù)據(jù)的增刪改查操作.session是hibernate操作數(shù)據(jù)庫的核心對象。
- 調用session的save/update/delete/get方法將實體交給Hibernate進行管理睬隶,Hibernate負責為每個實體對數(shù)據(jù)庫執(zhí)行INSERT/UPDATE/DELETE/SELECT操作锣夹。
- 對象的簡單增刪改查操作:
@Test
//session的新增
public void fun2(){
//1 創(chuàng)建,調用空參構造
Configuration conf = new Configuration().configure();
//2 根據(jù)配置信息,創(chuàng)建 SessionFactory對象
SessionFactory sf = conf.buildSessionFactory();
//3 獲得session
Session session = sf.openSession();
//4 session獲得操作事務的Transaction對象
//獲得操作事務的tx對象
//Transaction tx = session.getTransaction();
//開啟事務并獲得操作事務的tx對象(建議使用)
Transaction tx2 = session.beginTransaction();
//----------------------------------------------
Customer c = new Customer();
c.setCust_name("Google");
session.save(c);
//----------------------------------------------
tx2.commit();//提交事務
session.close();//釋放資源
sf.close();//釋放資源
}
@Test
//session的查詢
//查詢id為1的customer對象
public void fun3(){
//1 創(chuàng)建,調用空參構造
Configuration conf = new Configuration().configure();
//2 根據(jù)配置信息,創(chuàng)建 SessionFactory對象
SessionFactory sf = conf.buildSessionFactory();
//3 獲得session
Session session = sf.openSession();
//4 session獲得操作事務的Transaction對象
//獲得操作事務的tx對象
//Transaction tx = session.getTransaction();
//開啟事務并獲得操作事務的tx對象(建議使用)
Transaction tx2 = session.beginTransaction();
//----------------------------------------------
Customer customer = session.get(Customer.class, 1l);
System.out.println(customer);
//----------------------------------------------
tx2.commit();//提交事務
session.close();//釋放資源
sf.close();//釋放資源
}
@Test
//session的修改
//修改id為1的customer對象的name屬性為黑馬程序員
public void fun4(){
//1 創(chuàng)建,調用空參構造
Configuration conf = new Configuration().configure();
//2 根據(jù)配置信息,創(chuàng)建 SessionFactory對象
SessionFactory sf = conf.buildSessionFactory();
//3 獲得session
Session session = sf.openSession();
//4 session獲得操作事務的Transaction對象
//獲得操作事務的tx對象
//Transaction tx = session.getTransaction();
//開啟事務并獲得操作事務的tx對象(建議使用)
Transaction tx2 = session.beginTransaction();
//----------------------------------------------
//1 獲得要修改的對象
Customer c = session.get(Customer.class, 1l);
//2 修改
c.setCust_name("黑馬程序員");
//3 執(zhí)行update
session.update(c);
//----------------------------------------------
tx2.commit();//提交事務
session.close();//釋放資源
sf.close();//釋放資源
}
@Test
//session的刪除
//刪除id為1的customer對象
public void fun5(){
//1 創(chuàng)建,調用空參構造
Configuration conf = new Configuration().configure();
//2 根據(jù)配置信息,創(chuàng)建 SessionFactory對象
SessionFactory sf = conf.buildSessionFactory();
//3 獲得session
Session session = sf.openSession();
//4 session獲得操作事務的Transaction對象
//獲得操作事務的tx對象
Transaction tx = session.getTransaction();
tx.begin();
//開啟事務并獲得操作事務的tx對象(建議使用)
Transaction tx2 = session.beginTransaction();
//----------------------------------------------
//1 獲得要修改的對象
Customer c = session.get(Customer.class, 1l);
//2 調用delete刪除對象
session.delete(c);
//----------------------------------------------
tx2.commit();//提交事務
session.close();//釋放資源
sf.close();//釋放資源
}
- Transaction封裝了事務的操作
@Test
//事務操作
public void fun1(){
//1 創(chuàng)建,調用空參構造
Configuration conf = new Configuration().configure();
//2 根據(jù)配置信息,創(chuàng)建 SessionFactory對象
SessionFactory sf = conf.buildSessionFactory();
//3 獲得session
Session session = sf.openSession();
//4 session獲得操作事務的Transaction對象
//獲得操作事務的tx對象
//Transaction tx = session.getTransaction();
//開啟事務并獲得操作事務的tx對象(建議使用)
Transaction tx2 = session.beginTransaction();
//----------------------------------------------
//do something here...
//----------------------------------------------
tx2.commit();//提交事務
tx2.rollback();//回滾事務
session.close();//釋放資源
sf.close();//釋放資源
}
4.4 封裝HibernateUtils.java
package utils;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateUtils {
private static SessionFactory sessionFactory;
static {
// 1 創(chuàng)建,調用空參構造
Configuration conf = new Configuration().configure();
// 2 根據(jù)配置信息,創(chuàng)建 SessionFactory對象
sessionFactory = conf.buildSessionFactory();
}
// 獲得session => 獲得全新session
public static Session openSession() {
// 3 獲得session
return sessionFactory.openSession();
}
// 獲得session => 獲得與線程綁定的session
public static Session getCurrentSession() {
// 3 獲得session
return sessionFactory.getCurrentSession();
}
public static void main(String[] args) {
System.out.println(HibernateUtils.openSession());
}
}