Hibernate持久層框架學習筆記

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的區別:

  1. from=select * from
  2. select new 對象(),
  3. select new map(),
  4. left join ...fetch...不能與map同時出現
  5. 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" />
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章