13 hibernate核心java
表和表的關係:mysql
常見有7中關係:sql
單項關係一下四種 數據庫
1-1 外鍵1-1,主鍵1-1的關係緩存
1-n服務器
n-1session
n-noracle
多項關係:互相使用;框架
1-1eclipse
1-n(n-1)
n-n
如下有兩個表,user_info、和login連個表。表和字段以下;
User_info
Uid truename phone sex
Longin
Lid longinname password uid
這裏創建了user類和longin類,同事new了user
User表中不含login字段,可是longin表中有user_info字段,可是在login的類中加入了user應用;
注:a在單項外鍵1-1中第一個表的主鍵是另一個表的外鍵,因此在另一個表裏,這個外鍵不受約束能夠隨便寫。爲了達到主外鍵一一對應就用到unique寫法以下
<many-to-one name="user" column="uid" not-null="true" class="User" unique="true" cascade="all">
</many-to-one>當把配置文件和類寫好就能夠自動生成數據庫鏈接表了;
保存的時候:這裏先將user先存入進去,由於只有主鍵先得到持久化才能跟其餘表有關係;注意外鍵配置時候必須不能爲空;也就是說user_info是父表,另外的表longin爲子表,但查詢的時候必須先查詢子表,也就是login表,由於user_info表中沒有login表中的屬性,但login表中有user_info的應用:
//這裏只保存了一個關聯表被關聯的不保存通常會報錯,可是有這樣的配置就會保存一個表:級聯(如:兩表經過 id字段創建一對一關係,同時選項上了「實施參照完整性」「級聯更新相關字段」「級聯刪除相關記錄」,目的是實現,當在employee創建新用戶時,同時自動在user_right表中給其創建相應的權力記錄,但我發現如在employee中新增一個用戶時,user_right並無同步增長一條記錄,可是在employee中刪除一個用戶時,user_right中卻會同步更新!):cascade(級聯)="all"它將配置的關聯和被關聯的對象共存亡;
多項外鍵1-1:其它不變就是對象的模型變了,在user表中加入(表名)longin對象字段,也就是雙向包含,因此在user配置中加入了<one-to-one name="login"class="Login"property-ref(表示關聯對方的屬性)="user"></one-to-one>這樣保存數據順序和上一致,可是查詢能夠是反向和正向,有利於查詢
b共享主鍵關聯:能夠是主鍵名不同,但主鍵值必須同樣,也就是關係模型有變化,對象模型則不會變化;
1-1的單項共享主鍵關聯:主鍵在longin中,因此先建立longin在建立user
1-1的雙項共享主鍵關聯:保存的時候以login的主鍵爲主,因此先保存login:查詢則無所謂;
單項n-1:先保存有主鍵的對象在保存無主見的對象;<many - to-one></many-to-one>,連個表字段:
T_room user
Id idname 1— ---- n id username rooomid
雙項n-1:數據庫不變,只是變對象用到private Set<User> users;,一個循環語句for(User user:users)
單項1-n:主控權放在1的上面,而n-1主控權在n的一方,因此在1的一方加上引用
room 1-------- n user
雙項1-n:就是在在n的一方加上引用,在user方加上<many -to-one>
注:在1掌控的時候,會發送多餘的sql語句(update),因此效率就降低了,因此能夠在配置文件中加入inverse=true反轉(就是將主控權交給多的一方,false的話就是本身掌控),這時候注意的是操做數據只能從n的一方去操做;而有n掌控時候就不會發多餘的;
n-n的關係:實現的時候須要一箇中間表,中間表中有連個字段,它們就是聯合主鍵(聯合主鍵就是這個表裏字段值不能同樣的,兩個字段加起來作一個主鍵),保存的時候先保存無set的那個對象;映射是<many -to- many>.
在雙項多對多中要從兩個對象中分別查詢的話配置xml文件是同樣的;(也就是<set>配置)
集合映射:中的例子映射,通常用set設置的值不會有順序的。而用list設置的值就會有順序的(這裏的list是個接口,不能是arrylist,可是new的時候就得是arrylist),一樣的也要修改配置文件
繼承映射:將對象的映射關係在表裏面體現出來
(1)每一個類分層結構一張表:一個父類無論他有多少子類都將他們與父類數據放入一張表中;
也就是整個樹一張表,subclass表明子類它的名字與類名綁定的,discriminator是個鑑別器這裏的type就是鑑別器,是用來識別數據類型的一個字段,
例子以下:父類是persion,兩個子類是student和work
Id name age school factory type
1 aaa 55 qinghua s
2 bbb 22 shuoshuodian w
有這張表體能夠看出只有學校和工廠才能分清楚他們是什麼人,在配置文件中不能加不能爲空的判斷,這樣也有問題,應爲的字段能夠空,就沒有意義
(2)每一個子類一張表,對象模型不變,也就是類代碼不變,只需修改配置文件(數據模型)
和以上的類同樣因此就作三張表,
T_person
Id name age sex
T_student
Id school pid
T_work
Id factory pid
說明:這裏的pid是外鍵就是person的id字段不一樣但值相同(也能夠去掉pid用共享主鍵來達到要求)這裏所用就是共享主鍵,從建表看,生成了第三個表達到結果:能夠加不能爲空的配置
(3)每一個具體的類一張表;對象模型仍是不變,變的仍是數據庫
例子以下:創建三張表
T_pserson
T_studnet
Id name age school
T_factory
Id name age factory
說明:這倆個子表的id不能相同 ,用到聯合子類,這裏產生了person表,可是是空的爲了 不讓這個表產生能夠用abstract =true;這裏假如加了不能爲空的話,就不能手動的向表中插入數據了;
-----------------------------------------------------------------------------------------------------------------
HQL講解:
語法:1.實體查詢
String hql = " from TUser";
執行這條語句會返回TUser以及TUser子類的紀錄。
注: 若是 TUser 類具備外鍵, 查詢會報錯!
解決方法: select 別名。屬性 from 類 as 別名。 沒有別名。屬性仍然報錯!
hql = "from java.lang.Object"
會返回數據庫中全部庫表的紀錄。
where 語句
hql = "from TUser as user where user.name='yyy'";
其中,as能夠省略也同樣
hql = "from TUser user where user.name='yyy'";
where子句中,咱們能夠經過比較運算符設定條件,如:=, <>, >, <, >=, <=, between, not between, in, not in, is,like等。
2.屬性查詢
List list = session.createQuery("select user.name, user.age from TUser as user").list();
還能夠在HQL中動態構造對象實例的方法,將數據封裝。
List list = session.createQuery("select new TUser(user.name, user.age) from TUser as user").list();
Iterator it = list.iterator();
while(it.hasNext() ) {
TUser user = (TUser)it.next();
System.out.println(user.getName());
}
可是要注意這裏的TUser對象只是對name和age屬性的封裝,其餘狀態均未賦值,因此不能用它來進行更新操做。
也能夠在HQL的Select子句中使用統計函數
"select count(*) ,min(user.age) from TUser as user"
也可使用distinct關鍵字來刪除重複紀錄。
select distinct user.name from TUser as user;
3.實體的更新與刪除
hibernate 2中須要先查詢出實體,設置屬性後再保存。
hibernate 3中,提供了更靈活的方式(bulk delete/update)
更新:
Query query = session.createQuery("update TUser set age=18 where id=1");
query.executeUpdate();
刪除:
session.createQuery("delete TUser where age>=18");
query.executeUpdate();
4.分組與排序
Order by子句:
from TUser user order by user.name, user.age desc
Group by子句和Having子句
"select count(user), user.age from TUser user group by user.age having count(user)>10"
5.參數綁定
經過順序佔位符?來填充參數:
1)hibernate 2 中經過session.find方法來填充
session.find("from TUser user where user.name=?", "Erica", Hibernate.STRING);
多個參數的狀況:
Object[] args = new Object[] {"Erica", new Integer(20)};
Type[] types = new Type{Hibernate.STRING, Hibernate.INTEGER};
session.find("from TUser user where user.name=? and user.age=?", args, types);
2)經過Query接口進行參數填充:
Query query = session.createQuery("from TUser user where user.name=? and user.age>?");
query.setString(0,"Erica");
query.setInteger(1, 20);
經過引用佔位符來填充參數:
String hql = "from TUser where name=:name";
Query query = session.createQuery(hql);
query.setParameter("name","Erica");
甚至能夠將查詢條件封裝爲一個
class UserQuery {
private String name;
private Integer age;
//getter and setter
}
String hql = "from TUser where name=:name and age=:age";
Query query = session.createQuery(hql);
UserQuery uq = new UserQuery();
uq.setName("Erica");
uq.setAge(new Integer(20));
query.setProperties(uq); //會調用裏面的getter?
query.iterate();
6.聯合查詢
也可使用 inner join,left outer join, right out join, full join
排列組合:form TUser, TAddress
事實上sql和hql除了語法上類似外,差異很大,徹底不是一個概念.這裏所操做的都是對象的屬性;sql是關係數據庫查詢語言,面對的數據庫;而hql是Hibernate這樣的數據庫持久化框架提供的內置查詢語言,雖然他們的目的都是爲了從數據庫查詢須要的數據,但sql操做的是數據庫表和字段,而做爲面向對象的hql操做的則是持久化類及其屬性。hql語句執行後的結果都是對象;
以oracle的案例數據庫來說解;分別有三個腳本語句文件,將三個腳本文件打開粘貼到oracle中,在dos下按命令User\sqlplus scott to tiger 接着把sql腳本拷貝運行,也就是案 例數據庫,分別是建立數據、添加數據、刪除冗餘數據。
1 Hibernian中的column屬性:們聲明從JavaBean的id屬性到表的id列的映射. property和Hibernate column屬性都有相同的值,咱們原本能夠忽略Hibernate column屬性,可是爲了清晰起見,咱們仍是把column列出來. 是個特殊的標 籤.它被用來聲明表的主鍵
2在myclipse中能夠自動的生成Hibernian配置文件可是手動導包的時候他不會把log4j property文件導入,須要咱們本身去導入,還要在myeclipse中手動導入junit組件
3這種寫法:也能夠是一種循環for(Object obj:list): 這是一種新的循環遍歷集合的方式,冒號前邊定義變量,表明集合中當前操做的元素,它的類型是集合中元素的類型,在循環體中直接用。
冒號後邊就是一個集合。這種寫法比較簡單,易於理解。
4當現有表後又文件的時候hql讀取表的時候出現的CGLIB錯誤說明數據表中的字段爲空了,必須賦值
5寫Hql語句的時候可使用myclipse中的HQL編輯器他能夠將hql語句自動翻譯爲sql語句,可是有時候這個編輯器會報錯打不開,就要看看工做路徑下…data文件的配置,看的是configfile的配置路徑和是否可以找到session工廠,還有就是映射文件不能錯;
6 hql支持查詢對象的別名打點,就能夠實現多表查詢,還支持左右連接和內聯。
7數據表達連接方式:左外連接,右外鏈接,內鏈接,全鏈接
左外連接:把左邊的那個表中不符合條件的字段查出來,右外鏈接同樣
內鏈接:發送等值連接條件
全鏈接:左右都不符合條件的值都顯示出來
這裏的簡寫id就是對象中的持久化標識,就是配置文件中<id>標籤中name的值
With能夠在join後面設置條件,createQuery發出的是hql語句,
支持:子查詢+彙集函數,分組查詢(分組查詢用having加條件:)
8 ROWNUM 是sql中的函數:限制返回數據的條數(相似遊標工做)系統任務這樣的函數起始值是1
因此rownum>某個數字或rownum = 非數字都是 不合法的:可是 能夠用rownum<=某個數字
HQL中有這個函數可是沒有此功能。用這個也就是查詢最大的幾個數據,因此也叫TOP n 方法
Hibernate中的緩存 一級緩存:session(進程)級別(list和ireator查詢緩存都在)不關閉session的話一直都存在
二級緩存:sessionfactory應用中,是服務器級別的 ,只要網站不關閉就一直存在,通常會在裏面放一些不重要的東西
用cout(*)的時候在hibernate中返回的必定是integer和long版本不一樣也會不一樣的
原生SQL(netive SQL):
就是像mysql 、oracle等本身的一些特性就稱做原生sql
二級緩存: 只須要查一次數據庫,在次操做數據不用去查詢了,它會首先找緩存,看看有沒有,若是有就直接用,沒有的時候在去查!
在hibernate中用的都是EHCache,不支持集羣,Hibernate的二級緩存是應用服務器級別的,他的最大的好處就是跨session的,把一些不時經常使用不到的數據放到session中
還有一些如SwarmCache和JBoss TreeCache都是企業級的分佈式的
配置二級緩存:1首先在hibernate.cfg.xml中的配置
<property name="cache.use_second_level_cache">true</property> //開啓緩存
<propertyname="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>//緩存提供商
2上述就配置提供了緩存,還要在相應的表中配置緩存
<cache usage="read-only"/>
3.當這裏啓用了EHcache的時候就要導入ehcache.xml文件(在hibernate-3.2\etc的包中)這樣就不會報錯,裏面有相應的配置
4 解釋:當查詢的時候先從一級緩存中查,而後從二級緩存中查詢,若是都查不到的話就會發sql繼續查詢