在前面我們學完了Struts2,接下來我們就要去學習第二個框架Hibernate。
那什麼是Hibernate?
Hibernate是一個開放源代碼的對象關係映射框架,它對JDBC進行了非常輕量級的對象封裝,它將POJO與數據庫表建立映射關係,是一個全自動的ORM框架,Hibernate可以自動生成SQL語句,自動執行,使得Java程序員可以隨心所欲地使用對象編程思維來操縱數據庫,Hibernate可以應用在任何使用JDBC的場合,既可以在Java的客戶端程序使用,也可以在Servlet/JSP的Web應用中使用。
順帶介紹一下什麼是ORM。
ORM:對象關係映射,是一種程序技術,簡單來說就是把我們程序中的實體類和數據庫表建立起來對應關係。
那爲什麼要有對象關係映射呢?
假設一下,當你開發一個應用程序的時候,你可能會寫不少數據訪問層的代碼,用來從數據庫保存、刪除、讀取對象信息等等。你在DAO中寫了很多的方法來讀取對象數據,改變狀態對象等等任務,而這些代碼很多都是重複的。
對象映射關係賦予了程序一種強大的能力,讓開發者僅僅掌握面向對象的思維來操作數據庫,即在關係型數據庫和業務實體對象之間作一個映射,這樣,我們在具體的操作業務對象的時候,就不需要再去和複雜的SQL語句打交道,只要像平時操作對象一樣操作它就可以了。
HelloWorld
關於Hibernate的一些基本知識瞭解完之後,我們來編寫一個Hibernate的入門項目。
首先我們得編寫hibernate的配置文件,在src目錄下新建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="connection.username">root</property>
<property name="connection.password">123456</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql:///test</property>
<!-- 配置hibernate的基本信息 -->
<property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
<!-- 執行操作時是否在控制檯打印sql -->
<property name="show_sql">true</property>
<!-- 是否對sql進行格式化 -->
<property name="format_sql">true</property>
<!-- 指定自動生成數據表的策略 -->
<property name="hbm2ddl.auto">update</property>
<!-- 指定關聯的.hbm.xml文件 -->
<mapping
resource="com/itcast/hibernate/helloworld/Account.hbm.xml" />
</session-factory>
</hibernate-configuration>
這裏面就是配置一些相關的信息。
然後我們創建一個Bean類Account:
package com.itcast.hibernate.helloworld;
public class Account {
private Integer id;
private String name;
private double money;
public Account() {
}
public Account(String name, double money) {
this.name = name;
this.money = money;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
@Override
public String toString() {
return "Account [id=" + id + ", name=" + name + ", money=" + money + "]";
}
}
接下來我們需要創建對象關係映射的配置文件,在與該類同級的目錄下新建Account.hbm.xml文件:
<?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>
<!-- 使Account類對應數據表ACCOUNT -->
<class name="com.itcast.hibernate.helloworld.Account" table="ACCOUNT">
<!-- id標籤中的name爲類中的屬性名;colum標籤中的name爲數據表中的列名 -->
<id name="id" type="java.lang.Integer">
<column name="ID" />
<!-- 指定主鍵的生成方式 native:使用數據庫本地的方式-->
<generator class="native" />
</id>
<!-- property表示非id的其它列 -->
<property name="name" type="java.lang.String">
<column name="NAME" />
</property>
<property name="money" type="double">
<column name="MONEY" />
</property>
</class>
</hibernate-mapping>
簡單地配置一下,該配置文件目的是使類和表進行一個映射。
然後我們編寫一下測試代碼:
// 1、創建一個SessionFactory對象
SessionFactory sessionFactory = null;
// 1)、創建Configuration對象:對應hibernate的基本配置信息和對象關係映射信息
// 默認關聯的是hibernate.hbm.xml文件,如果你的配置文件名是hibernate.hbm.xml,使用無參構造即可
Configuration configuration = new Configuration().configure();
sessionFactory = configuration.buildSessionFactory();
// 2、創建一個Session對象
Session session = sessionFactory.openSession();
// 3、開啓事務
Transaction transaction = session.beginTransaction();
// 4、執行保存操作
Account account = new Account("張三",1000);
session.save(account);
// 5、提交事務
transaction.commit();
// 6、關閉Session
session.close();
// 7、關閉SessionFactory
sessionFactory.close();
然後運行測試代碼,hibernate就會把數據保存到數據庫,如果你沒有這張表,hibernate會自動幫我們創建好表然後插入數據。
因爲hibernate版本的問題,所以這裏面會有很多的坑,具體報了什麼錯大家可以自己百度解決。我這裏的hibernate版本是5.X的。
+----+------+-------+
| ID | NAME | MONEY |
+----+------+-------+
| 1 | 張三 | 1000 |
+----+------+-------+
1 row in set (0.00 sec)
那麼在創建持久化類的時候需要注意下面幾個問題:
- 必須提供一個無參的構造器
因爲Hibernate需要使用Constructor.newInstance()來實例化持久化類 - 提供一個標識屬性
通常映射爲數據表的主鍵字段,如果沒有該屬性,一些功能將不起作用 - 爲類的持久化類字段聲明訪問方法
- 使用非final類
在運行時生成代理是Hibernate的一個重要的功能,如果持久化類沒有實現任何接口,Hibernate將使用CGLIB生成代理,如果使用的是final類,則無法生成CGLIB代理 - 重寫equals和hashCode方法
如果需要把持久化類的實例放到Set中(當需要進行關聯映射時),則應該重寫這兩個方法
入門案例我們就編寫完了, 相信兩個配置文件的配置信息大家都能明白,註釋也寫得很清楚,那麼關於測試代碼的一些類API,這裏分別介紹一下。
- Configuration:
Configuration類負責管理Hibernate的配置信息,包括如下內容:
Hibernate運行的底層信息:數據庫的URL、用戶名、密碼、JDBC驅動類,數據庫Dialect、數據庫連接池等(對應hibernate.cfg.xml文件)
創建Configuration的兩種方式:
屬性文件(hibernate.properties):
Configuration cfg = new Configuration();
Xml文件(hibernate.cfg.xml)
Configuration cfg = new Configuration().configure();
Configuration的configure方法還支持帶參訪問:
File file = new File(“文件名”);
Configuration cfg = new Configuration().configure(file); - SessionFactory:
針對單個數據庫映射關係經過編譯後的內存鏡像,是線程安全的
SessionFactory對象一旦構造完畢,即被賦予特定的配置信息
SessionFactory是生產Session的工廠
構造SessionFactory很消耗資源,一般情況下一個應用中只初始化一個SessionFactory對象 - Session:
Session是應用程序與數據庫之間交互操作的一個而單線程對象,是Hibernate運作的中心,所有持久化對象必須在session的管理下纔可以進行持久化操作。此對象的生命週期很短。Session對象有一個一級緩存,顯式執行flush之前,所有的持久化層操作的數據都緩存在session對象處,相當於JDBC中的Connection - Transaction:
事務,學過數據庫的應該都明白,不重複說
更新
上面說到了插入數據,那麼這裏說一下如何使用hibernate完成更新操作。
- session.save(obj); 【保存一個對象】
- session.update(obj); 【更新一個對象】
- session.saveOrUpdate(obj); 【保存或者更新的方法】
沒有設置主鍵,執行保存;
有設置主鍵,執行更新操作;
如果設置主鍵不存在報錯!
SessionFactory sessionFactory = null;
Configuration configuration = new Configuration().configure();
sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
Account account = session.get(Account.class, 1);
account.setMoney(2000);
session.update(account);
transaction.commit();
session.close();
sessionFactory.close();
運行然後查詢數據庫:
+----+------+-------+
| ID | NAME | MONEY |
+----+------+-------+
| 1 | 張三 | 2000 |
+----+------+-------+
1 row in set (0.00 sec)
查詢
接下來是查詢。
SessionFactory sessionFactory = null;
Configuration configuration = new Configuration().configure();
sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
Account account = session.load(Account.class, 1);
System.out.println(account);
transaction.commit();
session.close();
sessionFactory.close();
運行結果:
刪除
最後是刪除。
SessionFactory sessionFactory = null;
Configuration configuration = new Configuration().configure();
sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
Account account = session.get(Account.class, 1);
session.delete(account);
transaction.commit();
session.close();
sessionFactory.close();
運行結果:
mysql> select * from account;
Empty set (0.00 sec)
總結
關於增刪改查的操作是非常簡單的,只要會一個,其它的就都能會,因爲道理是一樣的。當然關於hibernate的使用遠不止這麼點功能,但本篇文章只是爲了讓你儘快入門,所以一些更高級的功能我打算寫在進階裏。