Hibernate學習筆記


[1]創建數據庫

運行-->cmd

c:> mysql -uroot -p123456 //登陸到mysql

mysql> create datavase soldier default charater set utf8

mysql> create table s_user (id int ptimary key auto_increment , name varchar(20))

mysql> insert int s_user (name) values('京溪')
mysql> show create table s_user //查看方言


[3].添加jar包
新建Java工程,並添加如下jar包:
1.{hibernate_home}/ hibernate3.jar
2.{hibernate_home}/lib/required/*.jar
3.{hibernate_home}/lib/jpa/hibernate-jpa-2.0-api-1.0.0.Final.jar
4.數據庫對應的JDBC驅動(例如mysql-connector-java-5.1.5-bin.jar)

[4].配置 hibernate.cfg.xml
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory name="foo">
<!-- 配置數據庫信息 -->
<property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
<property name="connection.url">
<![CDATA[jdbc:mysql://localhost:3306/soldier?useUnicode=true&characterEncoding=utf8]]>
</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.username">root</property>
<property name="connection.password">123456</property>
<!--顯示執行的SQL語句 -->
<property name="show_sql">true</property>
<property name="hbm2ddl.auto">update</property>
<!-- 導入映射文件 -->
<mapping resource="cn/soldoer/domain/User.hbm.xml" />
</session-factory>
</hibernate-configuration>

[5].配置 User.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 package="cn.soldoer.domain">
<class name="User" table="s_user">
<id name="id" type="int" column="id">
<generator class="native" />
</id>
<property name="name" type="string" column="name" />
</class>
</hibernate-mapping>

[6].User.java
public class User {
private int id;

private String name;

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 String toString(){
return "[User : id="+id +", name="+name+"]";
}
}

[7].UserDao.java
package cn.soldoer.domain;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.Transaction;

public class UserDao {

public void add(User user) {
//添加事務
Transaction tx = null;
Session session = HibernateUtils.openSession();
try {
tx = session.beginTransaction();//開始事務
session.save(user);
tx.commit();//提交事務
} catch (Exception e) {
tx.rollback();//回滾事務
throw e;
} finally {
session.close();//關閉session
}
}

public void update(User user) {
Session session = HibernateUtils.openSession();
try {
session.beginTransaction();
session.update(user);
session.getTransaction().commit();

} catch (Exception e) {
session.getTransaction().rollback();
throw e;
} finally {
session.close();
}

}

public void delete(int id) {

Transaction tx = null;
Session session = HibernateUtils.openSession();
try {
tx = session.beginTransaction();
session.delete(getById(id));
tx.commit();

} catch (Exception e) {
tx.rollback();
throw e;
} finally {
session.close();
}
}

public User getById(int id) {

Transaction tx = null;
Session session = HibernateUtils.openSession();
try {
tx = session.beginTransaction();
User user = (User) session.get(User.class, id);
tx.commit();
return user;

} catch (Exception e) {
tx.rollback();
throw e;
} finally {
session.close();
}

}

@SuppressWarnings("unchecked")
public List<User> findAll() {
List<User> list = null;

Transaction tx = null;
Session session = HibernateUtils.openSession();
try {
tx = session.beginTransaction();

list = session.createQuery(//
"FROM User")//
.list();

tx.commit();
return list;

} catch (Exception e) {
tx.rollback();
throw e;
} finally {
session.close();
}

}

@SuppressWarnings("unchecked")
public List<User> findAll(int firstResult, int maxResult) {
List<User> list = null;

Transaction tx = null;
Session session = HibernateUtils.openSession();
try {
tx = session.beginTransaction();

list = session.createQuery(//
"FROM User")//
.setFirstResult(firstResult)//
.setMaxResults(maxResult)//
.list();
tx.commit();

} catch (Exception e) {
tx.rollback();
throw e;
} finally {
session.close();
}
return list; }

}

[8].HibernateUtils.java
package cn.soldoer.domain;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtils {

// SessionFactory 全局只有一個就可以了
private static SessionFactory sessionFactory;

static {
sessionFactory = new Configuration()//
.configure()//
.buildSessionFactory();
}

public static SessionFactory getSessionFactory() {
return sessionFactory;
}

public static Session openSession() {
return sessionFactory.openSession();
}
}

[9] ---API
Configuration 配置
configure()
configure(String resourse)
addClass(Class clazz)
addResource(String resourse)
buliSessionFactory()
SessionFactory Session工廠
openSession()
getCurrentSession()
colse()
Session
操作對象的方法
save(Object)
update(Object)
delete(Object)
查詢的方法
createQuery(String)
createCriteria(class)
管理事務的方法
beginTransaction()
getTransaction()
其他的方法
...
工具類
Configuration cfg = new Configuration().configure();
SchemaExprot se = new SchemaExprot(cfg);
se.create(true,true)
Transaction 事務
commit()
rollback()
Query 查詢
list()
uniqueResult()
Criteriar 查詢
-----------------------------------
[10].Hibernate主配置文件
1.配置的key前面hibernate.前綴可以有也可以沒有。
如:hibernate.dialect和dialect是一樣的

2.按作用可分三類:
a.配置數據庫信息:
<property ...>
方言 Jdbcurl 驅動類 用戶名 密碼
b.導入映射文件
<mapping ...>
c.其他配置
<property ...>
show_sql true false 顯示生成的SQL語句
format_sql true false 格式化生成的SQL語句
hbm2dll.auto
|--create //先刪除再創建
|--create-drop//啟動時創建,關閉時刪除
|--update//表不存在創建,表不一樣就更新,一樣什么也不做
|--validate//驗證表結構是否一致,如果不一致拋異常
...
[11]xxx.hbm.xml映射文件配置
對持久化對象的要求:
a.提供一個無參構造器
b.提供一個標識屬性
c.提供持久化對象字段屬性
d.使用非final //懶加載支持
e.重寫eqauls()和hashCode() //Set支持
OID - 對象唯一標識符

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--package 包名-->
<hibernate-mapping package="cn.soldoer.domain">

<!-- name:哪個類
table:哪個表
-->
<class name="User" table="s_user">
<!--主鍵:推薦實體使用Integer類型
子元素:generator是用於指定主鍵生成策略的
identity:使用數據庫自己的主鍵生成策略,oracle不支持
sequence:使用序列作為主鍵生成策略的,Oracle數據庫
hiol:使用高低位算法生成主鍵
<genrator class="hilo">
<param name="table">hi_value</param>
<param name="column">next_value</param>
<param name="max_lo">100</param>
</genrator>
native:根據底層數據庫的能力選擇使用 idemtity、sequence、hiol中的一個。
uuid:由Hibernate自動生成uuid並指定為主鍵值。
increment:不推薦使用,會出現線程安全問題,因為是由Hibermate維護的自動增長。
-->
<id name="id" type="int" column="id">
<generator class="native" />
</id>
<!--property普通 的屬性(數據庫中的值類型,字符串,日期,數字等)
name:實體名,必須
type:類型,可以寫實體類型,也可以寫在數據庫中的類型 data time timestamp binary text
column:數據庫中的字段名
length:長度
not-null:非空約束,默認為false
-->
<property name="name" type="string" column="name" / >
</class>
</hibernate-mapping>

 

[12] 獲取Set
user.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 package="cn.soldier.set">
<class name="User" table="s_user">
<id name="id" type="int" column="id">
<generator class="native" />
</id>
<property name="name" type="string" column="name" />
<!-- <set name="使用字段" table="集合表名"><key column="集合外鍵"></key> <element type="集合元素類型"
column="集合元素列名"></element> </set> -->
<!-- addressSet屬性,Set集合 -->
<set name="addressSet" table="user_addressSet">
<key column="userId"></key>
<element type="string" column="address"></element>
</set>
<!-- addressList屬性,list集合 table:集合表的名稱 key: 集合外鍵的列名 list-index:存放集合索引列
element:存放集合元素的列的信息 -->
<list name="addressList" table="user_addressList">
<key column="userid"></key>
<list-index column="idx"></list-index>
<element type="string" column="address"></element>
</list>
<!-- addressArray屬性,數組 table:集合表的名稱 key: 集合外鍵的列名 list-index:存放集合索引列 element:存放集合元素的列的信息 -->
<array name="addressArray" table="user_addressArray">
<key column="userid"></key>
<list-index column="idx"></list-index>
<element type="string" column="address"></element>
</array>
<map name="addressMap" table="user_addressMap">
<key column="userid"></key>
<map-key type="string" column="key_"></map-key>
<element type="string" column="address"></element>
</map>
<!-- addressBag屬性,Bag結合:無序可重復 與set集合基本一致 -->
<bag name="addressBag" table="user_addressBag">
<key column="userid"></key>
<element type="string" column="address"></element>
</bag>
</class>
</hibernate-mapping>

user.java
package cn.soldier.set;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class User {
private Integer id;

private String name;

private Set<String> addressSet = new HashSet<String>();// set集合

private List<String> addressList = new ArrayList<String>();// list集合

private String[] addressArray;// 數組

private Map<String, String> addressMap = new HashMap<String, String>();// map

private List<String> addressBag = new ArrayList<String>();

/*
* 使用集合屬性是,一定要使用接口,而不能聲明為具體的實現類, 因為經過Session操作后,集合就變成了Hibernate自己的集合實現類
*/

省略getter,setter
}

app.java
package cn.soldier.set;

import java.util.Arrays;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;
import org.junit.Test;

public class App {

private static SessionFactory sessionFactroy = null;
static {

sessionFactroy = new Configuration().configure().addClass(User.class)
.buildSessionFactory();
}

@Test
public void testSave() {
Session session = sessionFactroy.openSession();
session.beginTransaction();
//
User user = new User();
user.setName("京溪");
user.getAddressSet().add("天河區");
user.getAddressSet().add("白雲區");
//
user.getAddressList().add("你妹");
user.getAddressList().add("你妹妹");
user.getAddressList().add("你妹");
//
user.setAddressArray(new String[]{"呵呵","呵呵"});
//
user.getAddressMap().put("1","你妹");
user.getAddressMap().put("2","你妹妹");
//
user.getAddressBag().add("你妹");
user.getAddressBag().add("你妹");
user.getAddressBag().add("你妹111");
//
session.save(user);
//
session.getTransaction().commit();
session.close();
}

@Test
public void testGet() {
Session session = sessionFactroy.openSession();
session.beginTransaction();
//
User user = (User) session.get(User.class,5);
System.out.println("App.testGet():set"+user.getAddressSet() );
//
System.out.println("App.testGet():list"+user.getAddressList());
//
System.out.println("App.testGet():string[]"+Arrays.toString(user.getAddressArray()));
//
System.out.println("App.testGet():map"+user.getAddressMap());
//
System.out.println("App.testGet():bag"+user.getAddressBag());

session.getTransaction().commit();
session.close();
}
}


<!-- addressSet屬性,Set集合 sort="unsorted|natural|comparatorClass" 由Hibernate在內存當中排序,一般不使用 -->
<set name="addressSet" table="user_addressSet" sort="natural">
<key column="userId"></key>
<element type="string" column="address"></element>
</set>


[13] 維護關聯關系
對於一對多關系,就是設置外鍵列的值。
對於多對多關系,就是插入或刪除中間表中的記錄
cascade 級聯

單向關聯
單向多對一
單向一對多
單向多對多
單向一對一(只能做從有外鍵方到無外鍵方的單向關聯)
雙向關聯

[14] 操縱持久化對象的狀態
1.臨時狀態
與數據庫沒有對應,跟session沒有關聯
一般是新new出的對象,
2.持久化狀態
對象在session的管理之中,最終會有對應的數據庫記錄
特點:
1.有OID
2.對對象的修改會同步到數據庫中。
3.游離狀態
數據庫中有對應記錄,但對象不再session管理之中是。
修改次狀態對象是,數據庫不會有變化。
4.刪除狀態
執行了session.delete()后的對

[15]session中的方法

一、操作實體對象的
sava()
update()
savaOrUpdae()

二、操作緩存的
clear()
evict()
flush()//默認(如:update delete)是在事務提交時執行 save是立刻執行

三、查詢實體對象的

 

get()
load()
createQuery()
createCriteria()
加載方式 返回值 如果數據不存在
----------------------------------------------------------
get() 立即加載 返回真實對象或null 返回null
load() 延遲加載 返回代理對象 拋異常


[16] 操作大批量,要防止session中對象過多而內存溢出
java.lang.OutOfMemoryError: Java heap space

[17] Hibernate檢索方式說明
1.導航對象圖檢索方式:根據已加載的對象導航到其他對象//eg.employee.getdepartment().getName();
2.OID檢索方式:按照對象的OID來檢索對象 //eg. session.get(clzz,id) session.load()
3.HQL檢索方式:使用面向對象的HQL查詢語言 //eg. session.createQuery();
4.QBC檢索方式:使用QBC(Query By Criterie) API 來檢索對象,這種API封裝了基於字符串形式的查詢語句,提供了更加面向對象的查詢接口
5.本地sQL檢索方式:使用本地數據庫的SQL查詢語句


[17]懶加載
也叫延遲加載,不是在執行獲取操作是拿上生成sql。而是在第一次使用時生成sQL。
分成兩種:
類級別的:
<class ... lazy="true/false">
屬性級別的:
<set/list/map/bag ... lazy=""...>
<many-to-one ...>
<one-to-one> ... lazy="..."
使用懶加載特性時,可能會有LazyInitizlizationException異常:
原因:
真正的獲取數據時,Session已經沒有了。
解決辦法:
方式一:讓session在真正加載后再關閉,
方式二:讓Session關閉前執行(Hibernate.initialize()) eg.Hibernate.initialize(department.getEmployees());

[18].使用c3p0數據庫連接池

hibernate.connection.provider_class: 該類用來向 Hibernate 提供JDBC連接
hibernate.c3p0.max_size: 數據庫連接池的最大連接數
hibernate.c3p0.min_size: 數據庫連接池的最小連接數
hibernate.c3p0.timeout: 數據庫連接池中連接對象在多長時間沒有使用過后,就應該被銷毀
hibernate.c3p0.max_statements: 緩存 Statement 對象的數量
hibernate.c3p0.idle_test_period: 表示連接池檢測線程多長時間檢測一次池內的所有鏈接對象是否超時. 連接池本身不會把自己從連接池中移除,而是專門有一個線程按照一定的時間間隔來做這件事,這個線程通過比較連接對象最后一次被使用時間和當前時間的時間差來和 timeout 做對比,進而決定是否銷毀這個連接對象。
hibernate.c3p0.acquire_increment: 當數據庫連接池中的連接耗盡時, 同一時刻獲取多少個數據庫連接
hibernate.c3p0.validate: 是否每次連接都驗證連接是否可用

#hibernate.c3p0.max_size 2
#hibernate.c3p0.min_size 2
#hibernate.c3p0.timeout 5000
#hibernate.c3p0.max_statements 100
#hibernate.c3p0.idle_test_period 3000
#hibernate.c3p0.acquire_increment 2
#hibernate.c3p0.validate false

[19]. 二級緩存
Hibernate中提供了兩個級別的緩存
第一級別的緩存是 Session 級別的緩存,它是屬於事務范圍的緩存。
這一級別的緩存由 hibernate 管理的,一般情況下無需進行干預
第二級別的緩存是 SessionFactory 級別的緩存,它是屬於進程范圍的緩存
SessionFactory 的緩存可以分為兩類:
內置緩存: Hibernate 自帶的, 不可卸載. 通常在 Hibernate 的初始化階段,
Hibernate 會把映射元數據和預定義的 SQL 語句放到 SessionFactory 的緩存中,
映射元數據是映射文件中數據的復制, 而預定義 SQL 語句時 Hibernate 根據映射元數據推到出來的. 該內置緩存是只讀的.
外置緩存(二級緩存): 一個可配置的緩存插件. 在默認情況下, SessionFactory 不會啟用這個緩存插件.
外置緩存中的數據是數據庫數據的復制, 外置緩存的物理介質可以是內存或硬盤


配置步驟
1拷貝ehcache-1.5.0.jar到當前工程的lib目錄下
2開啟二級緩存
<property name="hibernate.cache.use_second_level_cache">true</property>
3指定緩存的供應商
<property name="hibernate.cache.provider_class">
org.hibernate.cache.EhCacheProvider
</property>
4指定使用二級緩存的類
方法一 在使用類的*.hbm.xml配置
<class>元素的 cache 子元素表明 Hibernate 會緩存對象的簡單屬性,
但不會緩存集合屬性, 若希望緩存集合屬性中的元素,
必須在 <set> 元素中加入 <cache> 子元素

方法二 在hibernate.cfg.xml文件中配置(建議)
<!-- 指定使用二級緩存的類 放在maping下面 -->
<!-- 配置類級別的二級緩存 -->
<class-cache class="cn.itcast.c3p0.Customer" usage="read-write"/>
<class-cache class="cn.itcast.c3p0.Order" usage="read-write"/>
<!-- 配置集合級別的二級緩存 -->
<collection-cache collection="cn.itcast.c3p0.Customer.orders" usage="read-write"/>

不管是一級緩存,還是二級緩存,都是子啊使用OID的獲取對象是才有效。
get(),load()
對於Query.list()默認不會使用緩存,哪怕寫成where id-=1 也不會使用換緩存


使用查詢緩存的步驟
配置二級緩存, 因為查詢緩存依賴於二級緩存
在 hibernate 配置文件中啟用查詢緩存
<property name="cache.use_query_cache">true</property>
對於希望啟用查詢緩存的查詢語句, 調用 Query 的 setCacheable(true) 方法


Update \_____不會通知session緩存
Delete / 會把對應的二級緩存移除


綁定參數的形式,按參數名稱綁定
hql 查詢:
Query query = session.createQuery("from Customer c where " +
" c.name=:custname and c.age=:custage");
//第一個參數代表名字,第二個參數代表值
query.setString("custname", "Tom");
query.setInteger("custage", 21);
List list = query.list();


綁定參數的形式,按參數位置綁定
Query query = session.createQuery("from Customer c where c.name=? and c.age=?");
query.setString(0,"Tom");
query.setInteger(1, 21);
query.list();


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM