Hibernate持久層框架
orm映射框架 orm映射器模式,由一系列的java類和配置文件形成。
hiberanate下對象的三種形態
-
瞬態:對象由new操作符創建,且尚未與Hibernate Session關聯的對象,被認爲處於瞬態。瞬態對象不會被持久化到數據庫中,也不會被賦予持久化標示,如果程序中失去了瞬態對象的引用,瞬態對象將被垃圾回收機制銷燬。使用Hibernate session可以讓其變爲持久化狀態。
-
持久化:持久化實例在數據庫中有對應的記錄,並擁有一個持久化標識(identifier),持久化的實例可以是剛保存的。也可以是剛被加載的。無論那種,持久化對象都必須與指定的Hibernate Session關聯。Hibernate會檢測到處於持久化狀態對象的改動,在當前操作執行完成時將對象數據寫回數據庫。開發者不需要手動執行UPDATE。
-
遊離:某個實例曾經處於持久化狀態,但隨着與之關聯的session被關閉,該對象就變成遊離狀態了。遊離對象的引用依舊有效,對象可以繼續被修改,只是不會同步到數據庫中。如果重新讓遊離對象與某個session關聯,該對象會重新轉換爲持久化狀態。
UserBean.hbm.xml,對bean類的屬性映射
//一個簡單對象的orm映射
<class name="路徑" catalog="hibernate" table="long">
<id name="id" column="id" type="">
//hibernate框架中。常見的id生成方案有:
identity 自增長(數據庫),程序和框架不負責Id的產生
increment 自增長(框架),先查max(id),然後再+1,作爲自增長的id
assigned 程序負責id的生成,調用對象的.setId()去生成id。框架與數據庫不負責此時id的生成
uuid.hex 將ip地址,mac地址,時間搓等一系列不容易重複的元素按照一定的算法生成一個32爲不重複的字符串()
foreign 外來的,通常適用於主鍵一對一模式(比如兩張表的id是一樣的)
<generator class="identity"></generator>
</id>
<property nam e="userName" column="user_name" type="string" length="20"></property>
<property name="password" column="password" type="string" length="32"></property>
<property name="loginName" column="login_name" type="string" length="32"></property>
<property name="age" column="age" type="int"></property>
<property name="birthday" column="birthday" type="java.util.Date"></property>
hibernate.cfg.xml,hibernate的配置文件
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<!-- 配置Hibernate的SessionFactory -->
<session-factory>
<!-- 定義hibnerate操作數據庫的方言 -->
<property name="dialect">
org.hibernate.dialect.MySQLDialect
<!-- org.hibernate.dialect.OracleDialect -->
<!-- org.hibernate.dialect.SQLServerDialect -->
</property>
<!-- 定義JDBC連接數據庫,最基本的4大元素 -->
<property name="connection.driver_class">org.gjt.mm.mysql.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/hibernate?characterEncoding=UTF-8</property>
<property name="connection.username">root</property>
<property name="connection.password">lovo</property>
<!-- 上述4個元素可以讓JDBC,獲取mysql數據庫連接,但是連接取回來之後,需要放置在C3P0連接池 -->
<property name="hibernate.connection.provider_class">org.hibernate.c3p0.internal.C3P0ConnectionProvider</property>
<property name="hibernate.c3p0.max_size">50</property><!-- 最大連接數定義爲:50 -->
<property name="hibernate.c3p0.min_size">5</property><!-- 最小連接數定義爲:50 -->
<property name="hibernate.c3p0.timeout">10000</property><!-- 配置連接超時時間,單位:毫秒 -->
<property name="hibernate.c3p0.max_statements">200</property><!-- 連接池中可以緩存的最大預編譯對象的個數爲200 -->
<property name="hibernate.c3p0.acquire_increment">5</property><!-- 當連接池中,連接不夠時,需要再次獲取的連接數量 -->
<!-- 配置hibernate關於顯示SQL的相關配置 -->
<property name="show_sql">true</property>
<!-- 按SQL規範來顯示SQL語句 -->
<property name="format_sql">true</property>
<!-- 告知XXX.hbm.xml配置文件 -->
<mapping resource="org/framestudy/hibernatexmls/xmls/UserBean.hbm.xml"/>
</session-factory>
</hibernate-configuration>
applicationContext.xml的配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
//main裏所有的包文件
<context:component-scan base-package="org.framestudy.hibernatexmls"/>
<aop:aspectj-autoproxy/>
</beans>
get和load方法:
-
get和load都是hibernate提供的根據id查詢對象的方案,但是有所區別,它們的查詢順序不一致,
- get先查一級緩存再查二級緩存最後沒有的話查數據庫,get方法返回的是真實對象。
- load先查一級緩存再查二級緩存,如果二級沒有則不會查詢數據庫,而是默認數據庫中一定存在這條數據,所以返回了一個動態代理對象(只有返回了動態代理對象纔會去查詢真實對象),但使用這個動態代理對象時,將會去查詢數據庫。
-
get方法較爲常見一些。對象與session關聯時,一定會在session對應的緩存空間裏,session提交或關閉時會把裏面的內容清理掉。
例子
在庫裏面有二這條數據,即使數據庫刪除了這條數據,只要不打印這個方法,load依然默認這個數據在。
在hibernate直接寫from等同於select * from
hql===hibernate query language是一種面向對像的查詢語句
在hibernate中如果以問號來傳值我們稱之爲:位置設值方案(起始位置爲0);還有一種參數設值方案,或者叫做參數別名設值方案
String hql="from......like concat(?,‘%’)" //:位置設值方案
String hql="from like concat(:username,'%')" //參數別名設值方案
//第一個創建一個Query接口實例,第二個就是將上述的HQL轉換成SQL,並且對SQL進行預編譯。
Query query=session.createQuery(hql);
//在jdbc中第一個問號起始值爲1,但是在hibernate中起始位置爲0,給0號位置設置具體的值。
query.setString(0,userName)
query.setString(“username”,userName)//參數別名設值方案
//sql的代碼操作
String sql="select * from.....like concat(?,'%')";
//是將sql查詢出來的結果向對象進行轉換。
SQLQuery query=session.createQuery(sql);
query.setString(0,userName)
query.addEntity(UserBean.class);
return query.list();返回的是個對象,例如List<?>
可以通過new構造的方式,實現想查幾列數據就查幾列數據
String hql="select new Map(列名,列名) from 表名 where...."
如果傳多個參數或一個bean對象
使用setProperties()方法 兩種傳值方式:
多參數在批量設值的情況下,封裝成對象,要求對像的屬性名與參數名保持一致
多參數在批量設值的情況下,封裝成map集合,要求map的鍵名與參數名保持一致
Criteria 該接口與Query接口一樣,主要用條件查詢
條件查詢的例子
單參數查詢
public List<?> findUsersByUserName(String userName) {
// TODO Auto-generated method stub
/*
//在Hibernate中,如果以?來傳值,我們稱之爲:位置設值方案(起始位置是0)
//hql === hibernate query language (一種面向對象的查詢語句)
//在Hibernate中,直接寫From === select * from
String hql = "From UserBean as u where u.userName like CONCAT(?,'%')";
//這句話的作用:第一個創建一個Query接口實例,第二個就是將上述的HQL轉換成SQL,並且對SQL進行預編譯
Query query = session.createQuery(hql);
//在JDBC中,第一個?起始值爲1,但是在hibernate中,起始位置爲0
query.setString(0, userName);*/
/* //在Hibernate中,除了可以使用?傳值方案以外,還有一種:參數別名設值方案
String hql = "From UserBean as u where u.userName like CONCAT(:userName,'%')";
Query query = session.createQuery(hql);
query.setString("userName", userName);*/
/* String sql = "select * from t_user where user_name like CONCAT (?,'%')";
SQLQuery query = session.createSQLQuery(sql);
query.setString(0, userName);
query.addEntity(UserBean.class);//是將通過SQL查詢出來的結果,向對象進行轉換
return query.list();*/
/*
* 可以通過new 構造的方式,實現想查什麼就查什麼,但是可能會導致構造非常複雜
*
* String hql = "select new UserBean(u.loginName,u.password) "
+"from UserBean as u where u.userName like CONCAT(?,'%')";
Query query = session.createQuery(hql);
query.setString(0, userName);
return query.list();*/
String hql = "select new map(u.loginName as loginName,u.password as password) "
+" from UserBean as u where u.userName like CONCAT(?,'%')";
Query query = session.createQuery(hql);
query.setString(0, userName);
return query.list();
}
多參數查詢(參數是一個類對象)
/**
* 多參數在批量設值的情況下,要求對象的屬性名與參數別名保持一致
*/
@Override
public List<?> findUsersByUser(User user) {
// TODO Auto-generated method stub
String hql = "from UserBean as u "
+" where u.userName like CONCAT(:userName,'%') and u.age = :age and u.password = :password";
Query query = session.createQuery(hql);
query.setProperties(user);
return query.list();
}
多參數查詢(參數是一個Map集合)
/**
* 多參數在批量設值的情況下,要求Map鍵值對中的鍵與參數別名保持一致
*/
@Override
public List<?> findUsersByMap(Map params) {
// TODO Auto-generated method stub
String hql = "from UserBean as u "
+" where u.userName like CONCAT(:userName,'%') and u.age = :age and u.password = :password";
Query query = session.createQuery(hql);
query.setProperties(params);
return query.list();
}
(參數是一個Map集合)分頁查詢(參數是一個Map集合和一個類)
public PageBean findUsersByMap2PageBean(PageBean pager, Map params) {
// TODO Auto-generated method stub
//Criteria 該接口與Query接口一樣,同樣可以用作條件查詢,但是它沒有Query接口靈活
//主要存在的問題:HQL的結構不清晰,不可以實現 “按需查詢(想查什麼, 就查什麼)”
//所以推薦大家,多條件查詢時,還是用結構比較清晰的Query接口
/*//第一個步驟(查詢滿足條件的總的條數)
Criteria criteria = session.createCriteria(UserBean.class);// === From UserBean
// === userName like CONCAT(params.get("userName").toString(),'%')
criteria.add(Restrictions.like("userName", params.get("userName").toString(), MatchMode.START));
criteria.add(Restrictions.eq("age", params.get("age")));
// === password = params.get("password")
criteria.add(Restrictions.eq("password", params.get("password")));
// === id >= 20 注意:屬性是什麼類型,那麼你在傳值的時候,就傳遞什麼類型
criteria.add(Restrictions.ge("id", 20l));
criteria.setProjection(Projections.count("id"));//在From UserBean 前方 添加select count(id)
long totalRows = (long) criteria.uniqueResult();
pager.setTotalRows(totalRows);
//第二個步驟(查詢具體的數據)
criteria.setProjection(null);//取消HQL投影(幹掉我們自己HQL語句前面添加的max,min,count……數據庫方法)
criteria.setFirstResult(pager.getIndex());
criteria.setMaxResults(pager.getRows());
List<?> datas = criteria.list();
pager.setDatas(datas);
return pager;*/
//第一個步驟(查詢滿足條件的總的條數)
String hql = "select count(u.id)
from UserBean as u
where u.userName like CONCAT(:userName,'%') and u.age = :age and u.password = :password";
Query query = session.createQuery(hql);
query.setProperties(params);
long totalRows = (long) query.uniqueResult();
pager.setTotalRows(totalRows);//設置總條數
//第二個步驟(查詢具體的數據)
hql = "select new map(u.loginName as loginName,u.password as password)
from UserBean as u
where u.userName like CONCAT(:userName,'%') and u.age = :age and u.password = :password";
query = session.createQuery(hql);
query.setProperties(params);
query.setFirstResult(pager.getIndex());//在設置index
query.setMaxResults(pager.getRows());//在設置rows
List<?> datas = query.list();
pager.setDatas(datas);
return pager;
}
爲什麼要用緩存
mysql的數據性能不高,主要體現在連接(不能支持過多的連接,當數據量的數據過多,查詢的列上沒有添加索引,查詢數據是非常慢的)
1.本地緩存:和應用程序耦合在同一臺機器的緩存技術。缺陷是會和應用程序爭搶內存空間。如果緩存過大會拋出緩存不足的內存異常。任何一個持久層框架的一級和二級都是本地緩存。本地緩存讀寫比例比較高,不會經常更改,併發修改的機會不能過多,不能緩存大容量數據。 緩存過多會和應用程序爭搶應用空間。
又稱事務級緩存,由hibernate的session提供, 緩存空間的生命週期同session保存一致。
2.分佈式緩存: 和應用程序處於不同區域上的緩存技術。分佈式緩存那些集羣的服務器與服務器之間不會做數據同步。 分佈式緩存可以存儲大容量數據。絕大多數的系統80%以上的操作都是針對的20%的核心數據。符合讀寫比例高的數據纔有必要緩存起來。
又被稱爲應用級緩存,由sessionFacotory提供。
由同一個sessionFacotory創建的session的實例共享緩存空間。 需要手動開啓。session刷新(提交和關閉時)時把數據刷新到二級緩存中。hibernate一般不用二級緩存,一般sessionfacotry的職責是創建session,又分配給他緩存職責的讓它去維護session對象的話會影響它的性能。
二級緩存分爲對象緩存和查詢緩存:按照對象和id的存儲方式的緩存;query的緩存,編譯後的sql語句和結果集。
本地緩存不使用這個方法,分佈式緩存用
ehcache.xml關於二級緩存文件的配置
<ehcache>
<!-- <diskStore path="java.io.tmpdir"/> 是指數據放置在內存的臨時目錄中,
如果內存空間過小,我們還可以將數據存入到硬盤上,例如:<diskStore path="d:/cache"/> -->
<diskStore path="java.io.tmpdir"/>
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
memoryStoreEvictionPolicy="LRU"
/>
<!-- maxElementsInMemory="10000" 緩存中,允許放置的最大緩存對象的個數-->
<!-- eternal="false" 表示緩存的對象,是否需要持久化到硬盤中 -->
<!-- timeToIdleSeconds="120" 表示空閒的緩存對象,在緩存空間中,可以存活的時間,單位是S -->
<!-- timeToLiveSeconds="120" 表示緩存對象的鈍化時間,設置使用過的緩存對象,重新給它設置一個復活時間 -->
<!-- overflowToDisk="true" 當內存空間不足時,是否將數據保存到硬盤中去 -->
<!-- memoryStoreEvictionPolicy="LRU" 當緩存空間不足時,可以採用以下算法來爲新的緩存數據,清理緩存空間:
FIFO first in first out 先進先出
LRU Least Recently Used 最近最少時間
LFU Less Frequently Used 最少使用(從緩存建立起來開始算,最少使用,就優先清理掉)
-->
</ehcache>
在hibernate.cfg.xml文件中加入如下代碼配置二級緩存
<!-- 手動開啓二級緩存功能 -->
<property name="cache.use_second_level_cache">true</property>
<property name="cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
<property name="hibernate.cache.use_query_cache">true</property>
對某個bean文件orm映射時創建的xml文件內容(以addressBean爲例)
//非註解版
<?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">
//catalog是指數據庫名
<hibernate-mapping>
<class name="org.framestudy.hibernatexmls.beans.AddressBean" catalog="hibernate" table="t_address">
<id name="id" column="id" type="long">
<generator class="identity"></generator>
</id>
<property name="address" column="address" type="string" length="120"></property>
</class>
</hibernate-mapping>
非註解版一對多
classBean的配置
<?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">
<hibernate-mapping>
<class name="org.framestudy.hibernatexmls.beans.StudentBean"
catalog="hibernate" table="t_stus">
<id name="id" column="id" type="long">
<generator class="identity"></generator>
</id>
<property name="studentName" column="stu_name" type="string" length="20"></property>
<many-to-one name="cls"
class="org.framestudy.hibernatexmls.beans.ClassBean"
cascade="all"
fetch="select"
lazy="proxy"
column="fk_class_id"
></many-to-one>
</class>
</hibernate-mapping>
studentBean的配置
<?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">
<hibernate-mapping>
<class name="org.framestudy.hibernatexmls.beans.StudentBean"
catalog="hibernate" table="t_stus">
<id name="id" column="id" type="long">
<generator class="identity"></generator>
</id>
<property name="studentName" column="stu_name" type="string" length="20"></property>
<many-to-one name="cls"
class="org.framestudy.hibernatexmls.beans.ClassBean"
cascade="all"
fetch="select"
lazy="proxy"
column="fk_class_id"
></many-to-one>
</class>
</hibernate-mapping>
personBean類相關屬性
private Long id;
private String personName;
private String password;
private PersonInfoBean personInfo;
private Set<AddressBean> adds;
personBean的配置文件
<?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">
<hibernate-mapping>
<class name="org.framestudy.hibernatexmls.beans.PersonBean" catalog="hibernate" table="t_person">
<id name="id" column="id" type="long">
<generator class="identity"></generator>
</id>
<property name="personName" column="person_name" type="string" length="20"></property>
<property name="password" column="password" type="string" length="32"></property>
<!-- 擁有外鍵單向1對1,需要使用many-to-one來完成映射,1對1,同樣我們可以看成是1對多 關係的一個特例,
唯一的區別是,我們需要將多的一方唯一化,此用unique="true"將1-多關係唯一化。
fetch="select" 關聯對象在查詢時,採用即時加載方式(多條select語句查詢) fetch="join"
關聯對象在查詢時,採用預加載查詢方式(left join),將會導致懶加載失效 lazy="proxy" 表示將即時加載修改爲懶加載,
關聯對象不查詢,直接返回動態代理對象,直到程序使用該代理對象時,纔去真正的查詢數據庫,
通常和fetch="select" 成對出現。 column="fk_info_id" 表示關聯外鍵
cascade 表示級聯,與數據庫的級聯概念是一致的。
cascade="all" 表示針對“對象”做任何事情,其關聯對象,都會跟着同步
cascade="save-update" 表示針對“對象”做新增或者修改的時候,其關聯對象,也會跟着同步
cascade="persist" 表示針對“對象”做新增的時候,其關聯對象,也會跟着同步
cascade="delete" 表示針對“對象”做刪除的時候,其關聯對象,也會跟着刪除
-->
<many-to-one name="personInfo"
class="org.framestudy.hibernatexmls.beans.PersonInfoBean"
unique="true"
fetch="select"
lazy="proxy"
column="fk_info_id"
cascade="all">
</many-to-one>
<!-- 單向的1對多的配置 -->
<!-- fetch="select" lazy="true" 針對集合,一定需要配置延遲加載 -->
<!-- <key column="fk_person_id"></key> 兩表之間的關聯鍵-->
<set name="adds" fetch="select" lazy="true" cascade="all">
<key column="fk_person_id"></key>
<one-to-many class="org.framestudy.hibernatexmls.beans.AddressBean"/>
</set>
</class>
</hibernate-mapping>
非註解版一對一
wifeBean.class配置文件
<?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">
<hibernate-mapping>
<class name="org.framestudy.hibernatexmls.beans.WifeBean" catalog="hibernate" table="t_wife">
<id name="id" column="id" type="long">
<generator class="identity"></generator>
</id>
<property name="wifeName" column="wife_name" type="string" length="20"></property>
<!-- property-ref="wife" 用於指定某一個屬性,與有關聯的例外一個屬性是誰 -->
<one-to-one name="hus"
class="org.framestudy.hibernatexmls.beans.HusbandBean"
cascade="all"
fetch="select"
lazy="proxy"
property-ref="wife"
></one-to-one>
</class>
</hibernate-mapping>
HusbandBean.class配置文件
<?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">
<hibernate-mapping>
<class name="org.framestudy.hibernatexmls.beans.HusbandBean" catalog="hibernate" table="t_hus">
<id name="id" column="id" type="long">
<generator class="identity"></generator>
</id>
<property name="husName" column="hus_name" type="string" length="20"></property>
<many-to-one name="wife"
class="org.framestudy.hibernatexmls.beans.WifeBean"
column="fk_wife_id"
unique="true"
cascade="all"
fetch="select"
lazy="proxy"></many-to-one>
</class>
</hibernate-mapping>
但需要對某一個查詢語句設置緩存時
Query query = session.createQuery(hql).setCacheable(true);
fetch:關聯對象抓取方式,如果放置在left join 與inner join或者full join之後。表示將右側的關聯對象的數據向左側的主對象進行賦值合併,然後取消掉自己關聯對象的顯示。如果需要使用關聯對象,那麼可直接採用:對象.get關聯對象()來獲取。new map()與fetch不能同時出現,
hql和fetch的區別:
- from=select * from
- select new 對象(),
- select new map(),
- left join ...fetch...不能與map同時出現
- left join p.關聯對象
例子:用於關聯表的查詢
@Override
public List<?> findClassBeanByStudentName(String stuName) {
// TODO Auto-generated method stub
String hql = "From ClassBean as c left join fetch c.stus as s
where s.studentName like CONCAT(?,'%')";
Query query = session.createQuery(hql);
query.setString(0, stuName);
return query.list();
}
fetch和map的區別:
@Override
public List<?> findPersonsByAddress(String address) {
// TODO Auto-generated method stub
/*fetch 關聯對象抓取方式,如果放置在left join 與inner join 或值full join 之後,表示
將右側的關聯對象的數據,向左側的主對象進行賦值合併, 然後取消掉自己關聯對象的顯示,
合併之後,如果需要使用關聯對象,那麼則可以直接採用:對象.get關聯對象() 來獲取*/
// String hql = "From PersonBean as p left join fetch p.personInfo as pf left join fetch p.adds as pa
where pa.address like CONCAT(?,'%')";
/* new map() 與fetch 不能同時出現,
*/
String hql = "select new map (p.personName as personName,pf.infomation as information,pa.address as address)
From PersonBean as p left join p.personInfo as pf left join p.adds as pa
where pa.address like CONCAT(?,'%')";
Query query = session.createQuery(hql);
query.setString(0, address);
return query.list();
}
調用一對多方法時的處理方式
@Test
public void testSaveStudentBean() {
//先查詢一個班級
ClassBean cls = classDaoImpl.getClassBeanById(1l);
System.out.println(cls.getStus());
//然後創建學生
StudentBean stu = new StudentBean();
stu.setStudentName("翠花");
//讓學生知道班級(學生擁有關係維護的控制權,所以學生需要知道班級,而班級不需要知道學生)
stu.setCls(cls);
studentDaoImpl.saveStudentBean(stu);
}
@Test
public void testSaveClassBean() {
ClassBean clas = new ClassBean();
clas.setClassName("J148");
//班級已經將 關係維護的控制權, 交給學生了,那麼此處就不能級聯刷新學生了
classDaoImpl.saveClassBean(clas);
}
調用一對一方法時的處理方式
@Test
public void testSaveHusbandBean() {
HusbandBean hus = new HusbandBean();
hus.setHusName("老王");
WifeBean wife = new WifeBean();
wife.setWifeName("老馬");
//讓老馬知道老王,讓老王知道老馬
hus.setWife(wife);
wife.setHus(hus);
husbandDaoImpl.saveHusbandBean(hus);
}
註解版hibernate的配置
一對一的配置
丈夫表
package org.framestudy.hibernatexmls.beans;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.annotations.GenericGenerator;
@Entity
@Table(name="t_hus")
public class HusbandBean implements Serializable {
/**
*
*/
private static final long serialVersionUID = -6779123693334806307L;
@Id
@Column(name="id")
@GenericGenerator(name="hibernate.strategy", strategy="identity")
@GeneratedValue(generator="hibernate.strategy")
private Long id;
@Column(name="hus_name",length=20)
private String husName;
@OneToOne(fetch=FetchType.LAZY)
@Cascade(value= {CascadeType.ALL})
@JoinColumn(name="fk_wife_id")
private WifeBean wife;
public HusbandBean() {
super();
// TODO Auto-generated constructor stub
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getHusName() {
return husName;
}
public void setHusName(String husName) {
this.husName = husName;
}
public WifeBean getWife() {
return wife;
}
public void setWife(WifeBean wife) {
this.wife = wife;
}
@Override
public String toString() {
return "HusbandBean [id=" + id + ", husName=" + husName + ", wife=" + wife + "]";
}
}
妻子表一方
package org.framestudy.hibernatexmls.beans;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.annotations.GenericGenerator;
@Entity
@Table(name="t_wife")
public class WifeBean implements Serializable {
/**
*
*/
private static final long serialVersionUID = -5135580484824506395L;
@Id
@Column(name="id")
@GenericGenerator(name="hibernate.strategy", strategy="identity")
@GeneratedValue(generator="hibernate.strategy")
private Long id;
@Column(name="wife_name",length=20)
private String wifeName;
//mappedBy="wife" 替代 xml中 property-ref="wife"
@OneToOne(fetch=FetchType.LAZY,mappedBy="wife")
@Cascade(value= {CascadeType.ALL})
private HusbandBean hus;
public WifeBean() {
super();
// TODO Auto-generated constructor stub
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getWifeName() {
return wifeName;
}
public void setWifeName(String wifeName) {
this.wifeName = wifeName;
}
public HusbandBean getHus() {
return hus;
}
public void setHus(HusbandBean hus) {
this.hus = hus;
}
@Override
public String toString() {
return "WifeBean [id=" + id + ", wifeName=" + wifeName + "]";
}
}
一對多的配置
學生表(多的一方):
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.annotations.GenericGenerator;
@Entity
@Table(name="t_stus")
public class StudentBean implements Serializable {
/**
*
*/
private static final long serialVersionUID = 5982604360916683581L;
@Id
@Column(name="id")
@GenericGenerator(name="id.strategy", strategy="identity")
@GeneratedValue(generator="id.strategy")
private Long id;
@Column(name="stu_name",length=20)
private String studentName;
@ManyToOne(fetch=FetchType.LAZY)
@Cascade(value= {CascadeType.ALL})
@JoinColumn(name="fk_class_id")
private ClassBean cls;
public StudentBean() {
super();
// TODO Auto-generated constructor stub
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
public ClassBean getCls() {
return cls;
}
public void setCls(ClassBean cls) {
this.cls = cls;
}
@Override
public String toString() {
return "StudentBean [id=" + id + ", studentName=" + studentName + ", cls=" + cls + "]";
}
}
班級表(少的一方):
import java.io.Serializable;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.annotations.GenericGenerator;
@Entity
@Table(name="t_class")
public class ClassBean implements Serializable {
/**
*
*/
private static final long serialVersionUID = 6007243270055543649L;
@Id
@Column(name="id")
@GenericGenerator(name="id.strategy", strategy="identity")
@GeneratedValue(generator="id.strategy")
private Long id;
@Column(name="class_name",length=20)
private String className;
@OneToMany(fetch=FetchType.LAZY,mappedBy="cls")
@Cascade(value= {CascadeType.ALL})
private Set<StudentBean> stus;
public ClassBean() {
super();
// TODO Auto-generated constructor stub
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public Set<StudentBean> getStus() {
return stus;
}
public void setStus(Set<StudentBean> stus) {
this.stus = stus;
}
@Override
public String toString() {
return "ClassBean [id=" + id + ", className=" + className + "]";
}
}
多對多的配置
選手錶一方
package org.framestudy.hibernatexmls.beans;
import java.io.Serializable;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.annotations.GenericGenerator;
@Entity
@Table(name="t_players")
public class PlayerBean implements Serializable {
/**
*
*/
private static final long serialVersionUID = 2446659919914354468L;
@Id
@Column(name="id")
@GenericGenerator(name="hibernate.strategy", strategy="uuid.hex")
@GeneratedValue(generator="hibernate.strategy")
private String id;
@Column(name="player_name",length=20)
private String playerName;
@ManyToMany(fetch=FetchType.LAZY)
@Cascade(value= {CascadeType.ALL})
@JoinTable(name="t_player_games",joinColumns= {@JoinColumn(name="fk_player_id")},
inverseJoinColumns= {@JoinColumn(name="fk_games_id")})
private Set<GamesBean> games;
public PlayerBean() {
super();
// TODO Auto-generated constructor stub
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPlayerName() {
return playerName;
}
public void setPlayerName(String playerName) {
this.playerName = playerName;
}
public Set<GamesBean> getGames() {
return games;
}
public void setGames(Set<GamesBean> games) {
this.games = games;
}
@Override
public String toString() {
return "PlayerBean [id=" + id + ", playerName=" + playerName + ", games=" + games + "]";
}
}
遊戲表一方
package org.framestudy.hibernatexmls.beans;
import java.io.Serializable;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.annotations.GenericGenerator;
@Entity
@Table(name="t_games")
public class GamesBean implements Serializable {
/**
*
*/
private static final long serialVersionUID = 3932895055029411781L;
@Id
@Column(name="id")
@GenericGenerator(name="hibernate.strategy", strategy="uuid.hex")
@GeneratedValue(generator="hibernate.strategy")
private String id;
@Column(name="game_name",length=20)
private String gamesName;
//mappedBy="games" 含有交出控制權的意思
@ManyToMany(fetch=FetchType.LAZY,mappedBy="games")
@Cascade(value= {CascadeType.ALL})
private Set<PlayerBean> players;
public GamesBean() {
super();
// TODO Auto-generated constructor stub
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getGamesName() {
return gamesName;
}
public void setGamesName(String gamesName) {
this.gamesName = gamesName;
}
public Set<PlayerBean> getPlayers() {
return players;
}
public void setPlayers(Set<PlayerBean> players) {
this.players = players;
}
@Override
public String toString() {
return "GamesBean [id=" + id + ", gamesName=" + gamesName + "]";
}
}
關於多對多一方的選擇測試
@Test
public void testPlayerChoiceGames() {
PlayerBean player = playerDaoImpl.getPlayerById("402884c86078137b016078137f080000");
List<?> datas = gameDaoImpl.findAllGames();
if (player.getGames() == null) {
Set<GamesBean> games = new HashSet<GamesBean>();
for (Object obj : datas) {
GamesBean game = (GamesBean) obj;
games.add(game);
}
player.setGames(games);
} else {
for (Object obj : datas) {
GamesBean game = (GamesBean) obj;
player.getGames().add(game);
}
}
playerDaoImpl.playerChoiceGames(player);
}
當一個類中即存在類變量和集合時
package org.framestudy.hibernatexmls.beans;
import java.io.Serializable;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.annotations.GenericGenerator;
/**
* 單向的O2O,O2M
* @author pu
*
*/
@Entity
@Table(name="t_person")
public class PersonBean implements Serializable {
/**
*
*/
private static final long serialVersionUID = 7956578179466276687L;
@Id
@Column(name="id")
@GenericGenerator(name="hibernate.strategy", strategy="identity")
@GeneratedValue(generator="hibernate.strategy")
private Long id;
@Column(name="person_name",length=20)
private String personName;
@Column(length=32)
private String password;
@OneToOne(fetch=FetchType.LAZY)
@Cascade(value= {CascadeType.ALL})
@JoinColumn(name="fk_info_id")
private PersonInfoBean personInfo;
@OneToMany(fetch=FetchType.LAZY)
@Cascade(value= {CascadeType.ALL})
@JoinColumn(name="fk_person_id")
private Set<AddressBean> adds;
public PersonBean() {
super();
// TODO Auto-generated constructor stub
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getPersonName() {
return personName;
}
public void setPersonName(String personName) {
this.personName = personName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public PersonInfoBean getPersonInfo() {
return personInfo;
}
public void setPersonInfo(PersonInfoBean personInfo) {
this.personInfo = personInfo;
}
public Set<AddressBean> getAdds() {
return adds;
}
public void setAdds(Set<AddressBean> adds) {
this.adds = adds;
}
@Override
public String toString() {
return "PersonBean [id=" + id + ", personName=" + personName + ", password=" + password + ", personInfo="
+ personInfo + ", adds=" + adds + "]";
}
}
配置文件中配置
<!-- 告知XXX.hbm.xml配置文件 -->
<mapping class="org.framestudy.hibernatexmls.beans.UserBean" />