Hibernate快速入門
一、Hibernate的介紹
Hibernate是輕量級(jí)JavaEE應(yīng)用的持久層解決方案,是一個(gè)關(guān)系數(shù)據(jù)庫ORM框架。
ORM:Object Relational Mapping,對(duì)象關(guān)系映射
優(yōu)點(diǎn):
- Hibernate是基于jdbc的主流持久化框架。
- Hibernate是一個(gè)開源的ORM框架,。
- Hibernate對(duì)JDBC數(shù)據(jù)庫的操作進(jìn)行了封裝,簡化了數(shù)據(jù)庫操作的代碼,提高了開發(fā)效率。
- 程序員能夠利用Hibernate框架更好的使用面向?qū)ο蟮木幊趟季S來操縱數(shù)據(jù)庫。
二、 Hibernate使用入門
- 創(chuàng)建java項(xiàng)目
- 導(dǎo)入Hibernate所需jar包與數(shù)據(jù)庫驅(qū)動(dòng)連接
- 創(chuàng)建數(shù)據(jù)庫表
- 創(chuàng)建javaBean實(shí)體類
- 編寫數(shù)據(jù)庫表與javaBean實(shí)體類的映射(配置)文件
- 編寫Hibernate的核心配置文件
- 使用Hibernate
1. 導(dǎo)入jar包
- 數(shù)據(jù)庫驅(qū)動(dòng)
- Hibernate所需jar包
- 日志記錄jar包
2. 創(chuàng)建數(shù)據(jù)庫表
CREATE DATABASE hibernate_day01;
USE hibernate_day01;
CREATE TABLE USER(
uid INT PRIMARY KEY AUTO_INCREMENT,
uname VARCHAR(20),
upassword VARCHAR(20)
);
3. 創(chuàng)建實(shí)體類(略)
4. 編寫數(shù)據(jù)庫表與javaBean實(shí)體類的映射(配置文件)
在javaBean的同級(jí)目錄下創(chuàng)建文件名為
實(shí)體類名.hbm.xml
的配置文件.如:User.hbm.xml導(dǎo)入配置文件的DTD約束:mapping
class標(biāo)簽
定義javaBean與數(shù)據(jù)庫表的映射id標(biāo)簽
定義javaBean與數(shù)據(jù)庫表中的主鍵的映射關(guān)系-
property標(biāo)簽
定義普通字段的映射關(guān)系<?xml version="1.0" encoding="UTF-8"?> <!-- 引入DTD約束 --> <!-- 找到buildPath之后的Hibernate的Liberaries,打開hibernate的核心包:hibernate-core-5.0.7.Final.jar --> <!-- 打開和新包下的org.hibernate包,找到dtd結(jié)尾的映射配置文件mapping.dtd與hibernate的核心配置文件configuration.dtd --> <!-- 找到兩個(gè)文件的dtd約束,copy到對(duì)應(yīng)的xml配置文件中 --> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <!-- 創(chuàng)建javaBean實(shí)體類與數(shù)據(jù)庫表的映射 --> <class name="com.itdream.domain.User" table="user"> <!-- javaBean與表的主鍵的映射,相同時(shí),column可省略 --> <id name="uid" column="uid"></id> <!-- 創(chuàng)建javaBean于表的普通字段的映射,相同時(shí)column可省略 --> <property name="uname" column="uname"></property> <property name="upassword" column="upassword"></property> </class> </hibernate-mapping>
5. 編寫Hibernate的核心配置文件
- 在src目錄下創(chuàng)建文件名為 ``hibernate.cfg.xml```的配置文件.
- 導(dǎo)入配置文件的DTD約束:configuration
-
<hibernate-mapping></hibernate-mapping>標(biāo)簽中分為三部份:以property標(biāo)簽標(biāo)記
必要的配置信息 : 連接數(shù)據(jù)庫的基本參數(shù)
-
Hibernate的屬性
2.1 : Hibernate的方言 : 根據(jù)配置生成對(duì)應(yīng)的SQL語句,實(shí)現(xiàn)了跨數(shù)據(jù)域,切換數(shù)據(jù)庫只需更改這里的配置即可
Hibernate加載映射文件,
<maping resource="相對(duì)路徑" />
<?xml version="1.0" encoding="UTF-8"?>
<!-- 引入DTD約束 -->
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<!-- Hibernate核心配置 -->
<hibernate-configuration>
<session-factory>
<!-- 1.必要的配置信息:連接數(shù)據(jù)庫的基本參數(shù) -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate_day01</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">root</property>
<!-- 2. 與本地線程綁定 -->
<property name="hibernate.current_session_context_class">thread</property>
<!-- 3. Hibernate的屬性 -->
<!-- Hibernate的方言:根據(jù)配置的方言生成對(duì)應(yīng)的SQL語句.實(shí)現(xiàn)了跨數(shù)據(jù)庫 .切換數(shù)據(jù)庫時(shí)只需要更改此處的配置即可-->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- Hibernate顯示SQL語句 -->
<property name="hibernate.show_sql">true</property>
<!-- Hibernate格式化SQL語句 -->
<property name="hibernate.format_sql">true</property>
<!-- Hibernate的hbm2ddl,定義hibernate對(duì)數(shù)據(jù)庫表格的創(chuàng)建方式,開發(fā)一般用none -->
<!-- 取值:none,create,create-drop,update,validate -->
<property name="hibernate.hbm2ddl.auto">none</property>
<!-- 4. Hibernate加載映射 -->
<mapping resource="com/itdream/domain/User.hbm.xml"/>
</session-factory>
</hibernate-configuration>
6. 使用Hibernate完成用戶User的注冊(cè)
- 創(chuàng)建Hibernate的配置對(duì)象Configuration
- 通過配置對(duì)象,獲取SessionFactory工廠對(duì)象
- 通過工廠對(duì)象獲取Session對(duì)象
- 開啟事務(wù)
- 實(shí)現(xiàn)自己的業(yè)務(wù)邏輯
- 提交事務(wù)
- 關(guān)閉資源
代碼實(shí)現(xiàn):
@Test
//Hibernate入門案例,存儲(chǔ)用戶到MySQL數(shù)據(jù)庫
public void test01() {
//1. 創(chuàng)建Hibernate配置對(duì)象
Configuration configuration = new Configuration();
//默認(rèn)加載放在src下以hibernate.cfg.xml命名的Hibernate核心配置文件
//1.1 加載配置文件
configuration.configure();
//2. 通過配置對(duì)象創(chuàng)建SessionFactory對(duì)象
SessionFactory sessionFactory = configuration.buildSessionFactory();
//3. 通過工廠對(duì)象獲取Session對(duì)象
Session session = sessionFactory.openSession();
//4. 開啟事務(wù)
Transaction transaction = session.beginTransaction();
//5. 實(shí)現(xiàn)自己的業(yè)務(wù)邏輯
User user = new User();
user.setUname("唐嫣");
user.setUpassword("123");
//實(shí)現(xiàn)了insert into user values(null,'唐嫣','123')的操作
session.save(user);
//6. 提交事務(wù)
transaction.commit();
//7. 釋放資源
session.close();
sessionFactory.close();
}
三、Hibernate配置文件如何導(dǎo)入DTD約束
- 導(dǎo)入Hibernate的jar包后build path會(huì)產(chǎn)生對(duì)應(yīng)的liberary
- 在liberary中找到Hibernate的核心jar
hibernate-core-5.0.7.Final.jar
- 找到核心jar中的
org.hibernate包
,點(diǎn)擊打開這個(gè)包 - 分別找到
hibernate-mapping-3.0.dtd
和hibernate-configuration-3.0.dtd
的dtd約束 - copy兩個(gè)dtd文件中的約束
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-configuration-3.0.dtd:
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
6.點(diǎn)開eclipse的window的prference的屬性,設(shè)置約束的編寫提示。
7.找到xml catalog的窗口,點(diǎn)擊add
8.將約束中雙引內(nèi)的http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd 或(mapping) 填入key的輸入框,key type選URI,Location選擇FileSystem找到對(duì)應(yīng)的DTD文件導(dǎo)入即可.
四、 Hibernate的相關(guān)API
1. Configuration對(duì)象
用于配置并且啟動(dòng)Hibernate框架。
Hibernate框架通過該對(duì)象來獲得對(duì)象-關(guān)系映射文件中的元數(shù)據(jù),以及動(dòng)態(tài)配置Hibernate的屬性。
-
可以創(chuàng)建SessionFactory對(duì)象。
//獲取Configuration對(duì)象
Configuration conf = new Configuration();//加載配置文件: 以默認(rèn)方式加載,配置文件必須放在src目錄下,并以hibernate.cfg.xml命名
conf.configure();//推薦:conf.configure(String path);//不推薦
-
如果
hibernate.cfg.xml
中沒有使用mapping標(biāo)簽
加載映射文件,可以使用該配置對(duì)象加載。configuration.addResource(String path);
不推薦該方式,推薦在核心配置文件中直接配置映射文件的加載路徑。
2. SessionFactory : Session工廠對(duì)象
SessionFactory接口負(fù)責(zé)Hibernate的初始化,以及創(chuàng)建Session對(duì)象。它在Hibernate中起到一個(gè)緩沖區(qū)的作用,Hibernate可以將自動(dòng)生成的SQL語句、映射語句以及某些可以可重復(fù)利用的數(shù)據(jù)放在這個(gè)緩沖區(qū)中。同時(shí)它還保存了對(duì)數(shù)據(jù)庫配置的所有映射關(guān)系,維護(hù)了二級(jí)緩存。
SessionFactory的實(shí)例通過Configuration獲取:
SessionFactory factory = configuration.buildSessionFactory();
Session具有以下特點(diǎn):
1. 它是線程安全的,他的同一個(gè)實(shí)例可以被多個(gè)線程共享。
2. 它是重量級(jí)的,因此不能隨意的銷毀和創(chuàng)建。
由于這個(gè)特點(diǎn),因此一個(gè)項(xiàng)目中只需要一個(gè)SessionFactory對(duì)象,因此對(duì)其抽取一個(gè)工具類,使其只創(chuàng)建一次,并且能夠提供Session對(duì)象。
/**
* 1. 完成SessionFactory的初始化
* 2. 提供Session對(duì)象的獲取
*/
public class HibernateUtils {
//聲明SessionFactory對(duì)象,將其實(shí)例化放在static靜態(tài)代碼塊中,保證其在一開始就完成初始化
private static SessionFactory sf = null;
static {
//1. 創(chuàng)建Hibernate配置對(duì)象
Configuration configuration = new Configuration();
//2. 加載配置文件:hibernate.cfg.xml,默認(rèn)加載src目錄下的hibernate.cfg.xml
configuration.configure();
//3. 實(shí)例化SessionFactory對(duì)象
sf = configuration.buildSessionFactory();
//4. 關(guān)閉虛擬機(jī)時(shí),釋放SessionFactory
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
@Override
public void run() {
System.out.println("虛擬機(jī)關(guān)閉,釋放SessionFactory資源");
sf.close();
}
}));
}
//提供獲取Session對(duì)象的方法
public static Session openSession() {
return sf.openSession();
}
//獲得當(dāng)前線程中的綁定的Session
//注意:必須配置
//return
public static Session getCurrentSession() {
return sf.getCurrentSession();
}
}
3. Session對(duì)象
Session是應(yīng)用程序與數(shù)據(jù)庫之間交互操作的一個(gè)單線程對(duì)象,它的主要功能是為持久化對(duì)象提供增,刪,改,查的操作。
通過SessionFactory對(duì)象獲得Session對(duì)象,獲取Session實(shí)例有兩種方式:
1. 采用openSession方式:
Session session = sessionFactory.openSession();
2. 采用getCurrentSession方式:
Session session = sessionFactory.getCurrentSession();
他們的區(qū)別:
1. openSession獲取的Session對(duì)象,SessionFactory會(huì)直接創(chuàng)建一個(gè)Session實(shí)例,在使用完成后需要調(diào)用close方法手動(dòng)關(guān)閉。
2. getCurrentSession方法獲取的Session對(duì)象實(shí)例會(huì)被綁定到當(dāng)前線程中,它在事務(wù)提交或回滾后會(huì)自動(dòng)刪除。
Session是線程不安全的,多個(gè)并發(fā)線程同時(shí)操作一個(gè)Session對(duì)象會(huì)導(dǎo)致Session數(shù)據(jù)存取的混亂,(方法內(nèi)部定義與使用Session對(duì)象時(shí),不會(huì)出現(xiàn)線程問題),因此應(yīng)該避免成員位置定義Session,而在局部位置定義Session對(duì)象實(shí)例,從而避免線程問題。
Session對(duì)象的幾個(gè)API方法:
- save(obj) : 增
- get/load(obj,id) : 取
- delete(obj) : 刪,兩種方式,直接刪,先獲取再刪除.推薦先獲取在刪除。
- update(obj) : 改,兩種方式,直接修改,先獲取再修改.推薦先獲取再修改.防止數(shù)據(jù)丟失
- createQuery("hql") : 獲得Query對(duì)象
- createCriteria(Class) : 獲得Criteria對(duì)象
測試:
public class HibernateTest2 {
@Test
//使用Hibernate向數(shù)據(jù)庫中保存數(shù)據(jù)
public void save() {
//1.創(chuàng)建Hibernate配置對(duì)象
//2.創(chuàng)建SessionFactory對(duì)象
//3.獲取Session對(duì)象
Session session = HibernateUtils.openSession();
//4.開啟事務(wù)
Transaction transaction = session.beginTransaction();
//5.實(shí)現(xiàn)業(yè)務(wù)邏輯
User user = new User();
user.setUname("林志玲");
user.setUpassword("123");
session.save(user);
//6.提交事務(wù)
transaction.commit();
//7.關(guān)閉資源
session.close();
}
@Test
//根據(jù)主鍵獲取user對(duì)象
public void get() {
//1. 獲取Hibernate配置對(duì)象
//2. 通過配置對(duì)象獲取SessionFactory工廠對(duì)象
//3. 獲取Session對(duì)象
Session session = HibernateUtils.openSession();
//4. 開啟事務(wù)
Transaction transaction = session.beginTransaction();
//5. 實(shí)現(xiàn)業(yè)務(wù)邏輯
//參數(shù)1:javaBean的實(shí)體類 ; 參數(shù)2: 序列化,根據(jù)表的主鍵查找對(duì)應(yīng)的javaBean對(duì)象
User user = session.get(User.class, 1);
System.out.println(user);
//6. 提交事務(wù)
transaction.commit();
//7. 釋放資源
session.close();
}
@Test
//根據(jù)主鍵獲取user對(duì)象
public void load() {
//1. 創(chuàng)建配置對(duì)象
//2. 通過配置對(duì)象獲取SessionFactory工廠對(duì)象
//3. 獲取Session對(duì)象
Session session = HibernateUtils.openSession();
//4. 開啟事務(wù)
Transaction transaction = session.beginTransaction();
//5. 實(shí)現(xiàn)業(yè)務(wù)邏輯
//與get用法一致
User user = session.load(User.class, 2);
System.out.println(user);
//6. 提交事務(wù)
transaction.commit();
//7. 關(guān)閉資源
session.close();
}
//根據(jù)主鍵更改user對(duì)象的值
@Test
public void update() {
//1.獲取Hibernate配置對(duì)象
//2.通過配置對(duì)象獲取SessionFactory工廠對(duì)象
//3.獲取Session對(duì)象
Session session = HibernateUtils.openSession();
//4.開啟事務(wù)
Transaction transaction = session.beginTransaction();
//5.實(shí)現(xiàn)業(yè)務(wù)邏輯
//首先通過主鍵獲取到對(duì)象,然后在對(duì)對(duì)象進(jìn)行修改,這樣在更改對(duì)象的值的時(shí)候就不會(huì)發(fā)生丟失
User user = session.get(User.class, 1);
user.setUpassword("999");
session.update(user);
//6.提交事務(wù)
transaction.commit();
//7.釋放資源
session.close();
}
@Test
//根據(jù)主鍵刪除對(duì)應(yīng)user對(duì)象
public void delete() {
//1. 獲取Hibernate配置對(duì)象
//2. 通過配置對(duì)象獲取SessionFactory工廠對(duì)象
//3. 獲取Session對(duì)象
Session session = HibernateUtils.openSession();
//4. 開啟事務(wù)
Transaction transaction = session.beginTransaction();
//5. 實(shí)現(xiàn)業(yè)務(wù)邏輯
//首先獲取到這個(gè)要?jiǎng)h除的對(duì)象然后刪除
User user = session.get(User.class, 2);
session.delete(user);
//6. 提交事務(wù)
transaction.commit();
//7. 關(guān)閉資源
session.close();
}
}
get與load的區(qū)別:
get方法 : 立即加載策略:執(zhí)行g(shù)et,立即發(fā)送SQL語句
load方法 : 延遲加載(懶加載):執(zhí)行l(wèi)oad,不會(huì)發(fā)送sql語句;只要在真正使用數(shù)據(jù)的時(shí)候,才會(huì)發(fā)送sql語句。
4. Transction
負(fù)責(zé)事務(wù)管理
-
常用API :
- beginTransction() : 開啟事務(wù)
- commit() : 提交事務(wù)
- roolback() : 回滾事務(wù)
-
特點(diǎn)
- Hibernate框架默認(rèn)情況下事務(wù)不自動(dòng)提交,需要手動(dòng)提交事務(wù)
- 如果沒有開啟事務(wù),每一個(gè)Session操作,都相當(dāng)于一個(gè)獨(dú)立的事務(wù)
- 每段事務(wù)隱藏著異常,需要手動(dòng)添加try/catch
五、Hibernate整合C3P0實(shí)現(xiàn)連接池
hibernate中可以使用默認(rèn)的連接池,無論功能與性能都不如C3PO。
步驟:
- 找到Hibernate中的c3p0的jar包添加到項(xiàng)目中
- 修改hibernate.cfg.xml的配置文件,添加屬性,Hibernate會(huì)自動(dòng)發(fā)現(xiàn)所配置的信息,選擇c3p0作為連接池。
<!-- C3P0的供應(yīng)商 -->
<property name="hibernate.connection.provider_class">org.hibernate.c3p0.internal.C3P0ConnectionProvider</property>
<!-- 最小連接 -->
<property name="hibernate.c3p0.min_size">5</property>
<!-- 最大連接數(shù) -->
<property name="hibernate.c3p0.max_size">20</property>
<!-- 連接超時(shí)時(shí)長 -->
<property name="hibernate.c3p0.timeout">120</property>
<!-- 每120秒檢查空閑連接 -->
<property name="hibernate.c3p0.idle_test_period">120</property>
<!-- 最大statments數(shù)量 -->
<property name="hibernate.c3p0.max_statements">120</property>
<!-- 連接用完后,每次增加的連接數(shù) -->
<property name="hibernate.c3p0.acquire_increment">2</property>
<!-- 每次都驗(yàn)證連接是否可用 -->
<property name="hibernate.c3p0.validate">false</property>
3.查看連接池是否起作用
方法1:
修改log4j的log4j.properties,修改log4j.rootLogger=Info,這樣降低記錄與顯示日志的級(jí)別.
運(yùn)行程序時(shí)如果能看到控制臺(tái)出現(xiàn)[org.hibernate.connection.C3P0ConnectionProvider]說明
Hibernate已經(jīng)選擇了C3P0作為連接池
方法2:
在mysql中使用命令show processlist查看連接數(shù),如連接池中配置最小5個(gè)連接時(shí)將顯示:
六、 日志集成
- JCL規(guī)范。Java Commen logger
- SLF4J規(guī)范。Simple Logger fade for Java。
- log4j:實(shí)現(xiàn)。
規(guī)范的出現(xiàn)是因?yàn)樵谝粋€(gè)程序中多個(gè)框架用到了不同的日志系統(tǒng),日志雜亂。規(guī)范提供統(tǒng)一解決方案。
規(guī)范和實(shí)現(xiàn)的整合,需要中間整合橋梁。
Log4j與slf4j集成步驟:
-
導(dǎo)入jar包
- slf4j-api-x.x.x.jar : 規(guī)范接口jar
- slf4j-log4j12-x.x.x.jar : log4j與Slf4j整合的jar
- log4j-x.x.x.jar : log4j實(shí)現(xiàn)日志規(guī)范的jar
-
在src目錄下編寫log4j.properties配置文件
##設(shè)置日志記錄到控制臺(tái)的方式 log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.err log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n ##設(shè)置日志記錄到文件的方式 log4j.appender.file=org.apache.log4j.FileAppender log4j.appender.file.File=c\:mylog.log log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n ##日志輸出的級(jí)別,以及配置記錄方案 log4j.rootLogger=info, stdout, file
-
代碼中調(diào)用Log4j
-
初始化(引入的包為slf4j的,使用規(guī)范接口編程)
Logger logger = LoggerFactory.getLogger(Clazz);
-
調(diào)用
logger.trace(); logger.debug(); logger.info(); logger.warn(); logger.error();
-
日志級(jí)別:
trance
debug
info
warn
error
fatal
Log4j日志配置規(guī)則介紹【參考log4j介紹】:
日志記錄器:rootLogger
日志輸出源:appender
日志布局器:layout
真實(shí)使用導(dǎo)入jar包,配好log4j.properties就可以使用c3p0連接池了.