標籤:des http java 使用 os 檔案 io 資料
可以建立自己的user Library。(第二集)
加入mysql的驅動mysql-connector
在資料庫中建立相應的內容:
create database hibernate;
use hibernate;
create table student(id int primary key, name varchar(20),age int);
建立student類:
建立hibernate設定檔,hibernate.cfg.xml:
<?xml version=‘1.0‘ encoding=‘utf-8‘?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Database connection settings (hibernate自動幫你連結了資料庫,填入相關資訊) -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost/hibernate</property>
<property name="connection.username">root</property>
<property name="connection.password">abc123</property>
<!-- JDBC connection pool (use the built-in) (hibernate的串連池) -->
<!-- <property name="connection.pool_size">1</property> -->
<!-- SQL dialect (hibernate方言,hibernate統一了sql語言,將統一語言翻譯成下面填寫的相應的資料庫語言) -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- Enable Hibernate‘s automatic session context management -->
<property name="current_session_context_class">thread</property>
<!-- Disable the second-level cache (將二級緩衝disable掉) -->
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<!-- Echo all executed SQL to stdout (將產生的sql語句列印出來) -->
<property name="show_sql">true</property>
<!-- Drop and re-create the database schema on startup (是否讓hibernate自動產生ddl(建表語句)) -->
<!-- <property name="hbm2ddl.auto">update</property> -->
<mapping resource="com/bjsxt/hibernate/model/Student.hbm.xml"/>
</session-factory>
</hibernate-configuration>
還要指明object與表欄位的對應關係。建立對應檔,Studnet.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="com.bjsxt.hibernate.model">
<class name="Student">//找到對應的類
<id name="id" column="id" />//id表示為主鍵
<property name="name" />//property表示一般欄位
<property name="age" />
</class>
</hibernate-mapping>
寫測試類別:
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import com.bjsxt.hibernate.model.Student;
public class StudentTest {
public static void main(String args[]){
Student s = new Student();
s.setId(1);
s.setName("s1");
s.setAge(1);
Configuration cfg = new Configuration();
SessionFactory sf = cfg.configure().buildSessionFactory();//SessionFactory產生connecyion的工廠
Session session = sf.openSession();
session.beginTransaction();
session.save(s);//將對象s插入資料庫
session.getTransaction().commit();
session.close();
sf.close();
}
}
annotation(利用annotation註解就可以不用*.hbm.xml檔案):
建立新表:
create table teacher (id int primary key,name varchar(10),title varchar(20));
建立對象Teacher並加入註解annotation:
package com.bjsxt.hibernate.model;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity//表示實體類,對應於資料庫表中的一個表
public class Teacher {//利用annotation註解就可以不用*.hbm.xml檔案
private int id;
private String name;
private String title;
@Id//表示主鍵
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 getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
JDBC操作資料庫很繁瑣
sql語句是面向關係而不是物件導向
可以再對象和關係表之間建立關係來簡化變成
o/r mapping跨越資料庫平台
表名與類名不同的時候,對錶名進行配置
Annotation:@Table
xml:...
欄位名與屬性相同的時候:預設為@Basic;xml中不寫column
欄位名與屬性名稱不同的時候:
Annotation:@Column
xml:...
不需要psersitence(持久化,存入資料庫)的欄位:
Annotation:@Transient
xml:直接不寫
映射日期與時間類型,指定時間精度:
Annotation:@Temporal
xml:制定property標籤的type屬性
枚舉類型的映射:
Annotation:@Enumerated
xml:...
註解的位置:
可以放在field(成員變數)上面,
也可以放在getxxx方法上面。
Junit4有BUG:第19個視頻
ID建置原則:對應項目hibernate_0400_ID
注意:
我們觀察hibernate產生表的結構並不是為了將來就用他產生(也可能還有自己的擴充,比如index),而是為了明白我們應該儘力什麼樣的表和實體類映射。
xml產生id:
使用generator
常用的有四個:native identity sequence uuid
annotation產生id:
@GeneratedValue
有四種取值方式:auto identity sequence(@SequenseGenrator) table(@TableGenerator)
聯合主鍵:
xml:composite-id(要實現serializable和重寫equals和hashcode)
annotation:
將類註解為@IdClass,並將該類實體中的所有屬於主鍵的屬性都註解為@Id
將組件類註解為@Embeddable.並將組件的屬性註解為@Id
將組建的屬性註解為@Embeddable
Hibernate的核心開發介面:
sessionFactory有兩個方法得到Session:
1.openSession:每次都開啟一個新的Session,用完要關閉
2.getCurrentSession:拿到當前上下文(可以在設定檔中設定current-context-class,主要有jta和thread)已有的Session或者開啟一個新的Session(前一個Session被commit之後),用完不用關閉,commit()之後自動關閉。
Session是個介面,這兩種方法得到的具體類可能不一樣,所以不能混用
兩種方法的區別很重要
區別在第26集。
JPA界定事物邊界,例如資料存入和日誌記錄需要在同一個事物之內完成。
還有一種事物JTA,分散式資料庫。
對象的三種狀態:
怎麼區分:
1.對象有沒有ID
2.ID在資料庫中有沒有
3.在記憶體(session緩衝)中有沒有ID
1.transient:記憶體中一個對象,沒ID,緩衝中也沒有ID
2.persistent:記憶體中有ID,緩衝中有ID,資料庫有ID
3.detached:記憶體有ID,緩衝沒有ID,資料庫有ID
delete方法:
只要有ID就可以調用delete方法
get和load的區別:
get會馬上執行sql語句得到對象
load會產生並返回一個代理對象,直到你取該對象的屬性,這個代理才會執行sql語句得到對象
不存在對應記錄的時候有區別。
update:
用來跟新detached對象,更新完成後可以轉化為persistent狀態
更新transient會報錯
跟新自己設定ID的transient對象可以(前提是資料庫有對應記錄)
當一個persistent對象的欄位被改變的時候,commit會檢查修改,且更改全部欄位。
下面的方法只讓他修改相應的修改了的欄位:第32個視頻。
clear:
無論是load還是get,都會先尋找緩衝,如果沒有,才會去資料庫尋找,調用用clear方法可以強制清除Session緩衝。
flush:
可以強制進行從記憶體到資料庫的同步,commit時就執行一次flush。
關係映射:
對象之間的關係:
一對一:
單向:
每個Husband對應一個Wife,Wife中沒有對應的Husbus,則此為單向關聯
在資料庫有中用外部索引鍵關聯
@OneToOne @JoinColumn(name="wifeId")
雙向:
每個Husband對應一個Wife,Wife中也對應一個Husbus,則此為雙向關聯
@OneToOne(mappedBy)
聯合主鍵:
@JoinColums
一對多(多對一):
設局庫表設計:在多的一方加外鍵。
多對多:
單向關聯:
老師和學生的關係,老師需要知道自己教了哪些學生。
雙向關聯:
老師知道自己教了哪些學生,學生也知道教自己的有哪些老師。
此外還可以根據單向還是雙向可以非為7種。
Ctrl+Alt+下複製這一行到下一行
Alt+下移動這一行到下一行
powerdesigner可以用於分析代碼,產生表的關係圖。
關聯關係中的CRUD:
設定cascade可以設定在持久化時對於對象的操作。
C--create
R--retrieve(取出load get)
U--update
D--delete
Cascade屬性致命做什麼操作的時候關聯對象是綁在一起的
Merge=save+update
refresh=A裡面需要讀B改過之後的資料
鐵律:雙向關係在程式中要設定雙向關係,雙向關係設定mappedBy(在一的那一方設定)
fetch:
雙向不要兩邊設定Eager(會有多餘的查詢語句發出)
對多的乙方設定fetch的時候要謹慎,結合具體情況,一幫使用Lazy不使用eager(特別情況:多方的數量不是很多的時候可以考慮,提高效率的時候可以考慮)。
O/RMapping編程模型:
1.映射模型
jap annotation
hibernate annotation extension
hibernate xml
jap xml
2.編程介面
jap
hibernate
3.資料查詢:
hql
ejbql(jpql)
要刪除或者更新的時候,先load,除了精確知道ID號之外。
如果要消除關聯關係,先設定為NULL,在刪除記錄,如果不刪除記錄,該記錄就會變成垃圾資料。第51集。
如果指定@OneToOne的屬性fetch為FetchType.LAZY,會延遲對於關聯對象的載入,不論使用的是load還是get。
關係映射總結:什麼樣的關係,設計什麼樣的表,進行什麼樣的映射。
繼承映射:
1.一張表single_table
2.每個類分別一張表table_pre_class
3.每個子類一張表joined
樹狀結構的設計(至關重要):
在用一個類中使用one2many和many2one。
Hibernate查詢(query language)
HQL&EJBQL
1.NativeSQL
2.HQL(Hibernate ql)
3.EJBql(JPql 1.0)--可認為是hql的子集
4.qbc
5.qbe
效能最佳化:
注意session.clear()的使用,尤其在不斷分頁迴圈的時候,否則會造成記憶體流失。
JAVA有記憶體泄露嗎?
在文法層級上沒有,但是在實際上可能會間接造成,如果他調用用了C,在調用OS,而C需要手動控制記憶體。
1+N問題(很重要):
第64集
解決方案:
1.設定LAZY
2.BatchSize
3.join fetch
用得最多的是1 3。
list和Iterate的區別:
1.list取所有
2.iterate先去ID,等用到的時候再根據ID來去對象
3.session中list第二次發出,仍會到資料庫查詢
4.iterate第二次發出,則會先找session緩衝
hiberbate中有三種緩衝:
1.一級緩衝(Session級)
2.二級緩衝(SessionFactory級)
可以跨Session存在
以下情況使用二級緩衝:
1.經常被訪問
2.不會經常改動
3.數量有限
如:使用者權限、組織機構
hibernate.cfg.xml設定:
<property name="cache.use_second_level_cache">true</property>//開啟二級緩衝
<property name="cache.provider_class">org.hibernate.cache.EnCacheProvider</property>//指明使用哪種二級緩衝
添加註解:
@Cache
load預設使用二級緩衝,iterate預設使用二級緩衝
list預設往二級緩衝加資料,但是查詢的時候預設不使用
3.查詢快取
只有在查詢語句完全一樣才有效。查詢快取依賴於二級緩衝,所以必須同時開啟二級緩衝。
調用Query的setCachable(true)方法指明使用二級緩衝。
緩衝演算法:(當緩衝滿了之後怎麼辦)
1.LRU:Least Recently Used(最近最少被使用的被清除)
2.LFU:Least Frequently Used(使用頻率最少的被清除)
3.FIFO:First In First Out(先來的先被清除)
可以在ehcache中設定使用哪一種:
memoryStoreEvictionPolicy="LRU"
事物並發處理:
事物的特性:ACID
Atomic(原子性) Consistency(獨立性) Itegrity(一致性) Durability(持久性)
事物經常出現的問題:
髒讀 不可重複讀取 幻讀
資料庫的事物的隔離機制:
1:read-uncommitted
2:read-committed
4:repeatable read
8:serilizable
只要資料庫支援事物,就不可能出現第一類丟失跟新。
read-uncommitted會出現dirty read,phanton-read,non repeatable read問題。
read-committed不會出現dirty read,因為只有另一個事物提交才會讀出來結果,但仍然會出現phanton-read,non repeatable read.
repeatable read。
serial解決一切問題。
設定hibernate的事物隔離等級:
一般設定hibernate.connection.isolation=2//考慮效率
用悲觀素解決repeatable read的問題(依賴於資料庫的鎖)