Proxy代理模式是一種結構型設計模式,主要解決的問題是:在直接訪問對象時帶來的問題,比如說:要訪問的對象在遠程的機器上。在面向對象系統中,有些對象由于某些原因(比如對象創建開銷很大,或者某些操作需要安全控制,或者需要進程外的訪問),直接訪問會給使用者或者系統結構帶來很多麻煩,我們可以在訪問此對象時加上一個對此對象的訪問層。如下圖:
比如說C和A不在一個服務器上,A要頻繁的調用C,我們可以在A上做一個代理類Proxy,把訪問C的工作交給Proxy,這樣對于A來說,就好像在直接訪問C的對象。在對A的開發中我們可以把注意力完全放在業務的實現上。
GoF《設計模式》中說道:為其他對象提供一種代理以控制這個對象的訪問。
Proxy模式的結構:
下面通過一個場景來看看Proxy的實現,我們要使用代理類型ProxyClass的對象調用遠程機器上的一個類型LongDistanceClass的對象。
首先我們先模擬一個遠程的類型:為了保持對被代理對象使用的透明性,我們使代理類型和被代理類型同時繼承同一個接口IProxy
接口實現:
interface IProxy
{
string Function1();
string Function2();
}
遠程對象實現:
/// <summary>
/// 模擬的遠程對象
/// </summary>
public class LongDistanceClass:IProxy
{
#region IProxy 成員
public string Function1()
{
//do someting
return "LongDistanceClass.Function1";
}
public string Function2()
{
//do someting
return "LongDistanceClass.Function2";
}
#endregion
}
接下來就要實現代理類型,使用代理對象訪問模擬的遠程對象,代理類型實現如下:
public class ProxyClass:IProxy
{
#region IProxy 成員
public string Function1()
{
//to access LongDistanceClass.Function1
LongDistanceClass obj = new LongDistanceClass();
return obj.Function1();
}
public string Function2()
{
//to access LongDistanceClass.Function2
LongDistanceClass obj = new LongDistanceClass();
return obj.Function2();
}
#endregion
}
最后實現客戶端代碼:
class Class1
{
[STAThread]
static void Main(string[] args)
{
IProxy pro = new ProxyClass();
Console.WriteLine(pro.Function1());
Console.WriteLine(pro.Function2());
Console.Read();
}
}
運行結果如下:
LongDistanceClass.Function1
LongDistanceClass.Function2
Proxy模式的要點:
1、“增加一層間接層”是軟件系統中對許多負責問題的一種常見解決方法。在面向對象系統中,直接使用某些對象會帶來很多問題,作為間接層的proxy對象便是解決這一問題的常用手段。
在我們日常的工作中也常常用到代理模式,比如對于三層結構或者N- tiers結構中DAL數據訪問層,它把對數據庫的訪問進行封裝。BLL業務層的開發者只是調用DAL中的方法來獲得數據。
在比如前一段時間看了看AOP和Remoting方面的資料,對于跨越應用程序域的訪問,要為客戶應用程序提供一個TransparentProxy(透明代理),客戶程序實際上是通過訪問這個代理來訪問實際的類型對象。
2、具體proxy設計模式的實現方法、實現粒度都相差很大,有些可能對單個對象作細粒度的控制,有些可能對組件模塊提供抽象代理層,在架構層次對對象作proxy。
3、proxy并不一定要求保持接口的一致性,只要能夠實現間接控制,有時候損及一些透明性是可以接受的。例如上面的那個例子,代理類型ProxyClass和被代理類型LongDistanceClass可以不用繼承自同一個接口,正像GoF《設計模式》中說的:為其他對象提供一種代理以控制這個對象的訪問。代理類型從某種角度上講也可以起到控制被代理類型的訪問的作用。
posted @
2009-08-04 14:44 xiaoxinchen 閱讀(149) |
評論 (0) |
編輯 收藏
策略模式
是對算法的包裝,是把使用算法的責任和算法本身分割開來,委派給不同的對象管理。
策略模式通常把一個系列的算法包裝到一系列的策略類里面,作為一個抽象策略類的子類。
一句話來形容:準備一組算法,并將每一個算法封裝起來,使得他們可以互換
策略模式的結構
策略模式涉及到三個角色:
- 環境角色:持有一個Strategy類(策略類)的引用
- 抽象策略角色:策略類,通常由一個接口或者抽象類實現
- 具體策略角色:包裝了相關的算法和行為
《三國演義》中的故事
諸葛亮的精囊妙計?三條妙計
走喬國老的后門,求孫國太放人,請孫夫人退兵
趙云?按計行事
環境角色:趙云?由他來決定選擇策略
抽象策略角色:(接口)精囊妙計?按計行事(抽象方法)
具體策略角色:三條妙計(單獨使用的)
例子:一個策略模式的加減乘除
抽象策略角色: (精囊妙計)? Operation抽象類(oper抽象方法)
具體策略角色: (三條妙計)? 計算乘積,計算除法,計算加法,計算減法
環境角色: (趙云)? 有一個策略類( Operation )的引用
策略模式的優缺點:
優點:
1.提供了管理相關的算法族的辦法。
2.提供了可以替換繼承關系的辦法。
3.避免使用多重條件轉移語句
缺點:
1.客戶端必須知道所有的策略類,并自行決定使用哪一個策略類。
2.造成很多的策略類。
posted @
2009-08-04 12:21 xiaoxinchen 閱讀(236) |
評論 (0) |
編輯 收藏
原則內容:OCP原則就是"開-閉原則",一個軟件應該對擴展開放,對修改關閉。
解釋 :在設計一個模塊的時候,應當使得這個模塊可以在不被修改的前提下面被擴展。換言之,應該可以在不必修改源代碼的情況下改變這個
模塊的行為。這個原則有2點要求:
×:擴展開放
×:關閉修改
滿足OCP原則系統的優點:
×:通過擴展已有的軟件系統,提供新的行為,可以使得軟件系統滿足新需求
×:已有的軟件模塊,特別是重要的抽象層模塊不能做變更,這使得變化中的軟件系統有一定的穩定性和延續性。
如何實現OCP原則:
1、抽象是關鍵。
對需要設計的系統進行抽象,在此前提下面,讓抽象的實現機制千變萬化。這個抽象層必須預見到所有的可能的擴展,任何實現的改變都不會改變該抽象結構。這樣使得系統的抽象層無需修改,從而滿足OCP原則的第二條-關閉修改。
2、對可變性的封裝原則
OCP從另一個角度來說,就是EVP(principle of Encapsulation Variation)原則。即找到系統的可變因素,將之封裝起來。這個原則意味著2點:
×:一種可變性不應當散落在代碼的很多角落里,而應當被封裝到一個對象里面。繼承應當被看 做是封裝變化的方法,而不應當被認為是從一般的對象生成特殊的對象方法。
×:一種可變性不應當與另一種可變性混合在一起。所有的類圖的繼承結構一般不會超過兩層,不然就意味著將兩種不同的可變性混合在一起。
與其他設計原則的關系
LSP原則:這個原則是說任何基類出現的地方,子類一定可以出現。
這個原則是對OCP原則的補充,基類和子類的關系就是抽象化的具體體現,所以LSP原則是對實現抽象化的具體步驟的規范。一般來說,違背了LSP原則,一定違反了OCP原則,反之不一定成立。
CARP原則:這個原則講的是要盡可能的多用合成/聚合,而不是繼承關系達到復用的目的。
CARP原則和LSP原則相輔相成。二者都是對實現OCP原則的具體步驟的規范。前者要求設計師首先考慮合成/聚合關系;后者要求在使用繼承關系的時候,
必須確定這個關系是符合一定條件的。CARP原則是OCP原則的必要條件,違反了這個原則,就無法使系統實現OCP原則這個目標。
DIP原則:這個原則是說要依賴于抽象,不要依賴于實現。
DIP原則和OCP原則是目標和手段的關系。OCP是目標,DIP是手段。要想實現OCP原則,必須堅持DIP原則。違反了DIP原則,則不可能達到OCP原則要求。
LoD原則:這個原則講的是一個軟件實體應該盡可能少的和其他實體發生作用。
當一個system面臨功能擴展的時候,其中會有一些模塊,他們需要修改的壓力比其他的模塊要大一些,如果這些模塊是相對孤立的,那么他們就不會將修改的
壓力傳遞給其他模塊。根據LoD原則設計的系統,在功能需要擴展的時候,會相對容易的做到對修改的關閉。LoD原則是一條通向OCP原則的道路。
ISP原則:這個原則是說,應當為客戶端提供盡可能小的單獨接口,而不要提供大的總接口。ISP原則和LoD原則講的都是一個軟件實體與另一個軟件實體的通訊限制。廣義的LoD原則要求盡可能限制通訊的寬度和深度,ISP原則所限制的是通信寬度。
一個重構方法的討論
“將條件轉移語句改寫成為多態性”是一條廣為流傳的代碼重構做法。
這一做法本身并不能保證“開-閉”原則,應當以“開-閉”原則判斷是否需要改寫成多態。條件轉移并不是錯誤,如果需要,完全可以選擇使用條件轉移。
如果一個條件轉移語句確實封裝了某種商務邏輯的可變性,那么將此種可變性封裝起來就符合“開-閉”原則設計思想了。如果一個條件轉移語句沒有涉及重
要的商務邏輯,或者不會隨著時間的變化而變化,也不意味著任何的可擴展性,那么它就沒有涉及任何有意義的可變性。這時候將這個條件轉移語句改寫成多態性就
是一種沒有意義的浪費。
抽象類應當擁有盡可能多的共同代碼
在一個繼承的等級結構中,共同的代碼應當盡量向等級結構的上方移動。把重復的代碼從子類里面移動到超類里面,可以提高代碼的復用率。在代碼發生改變時,設計師之需要修改一個地方。
抽象類應當擁有盡可能少的數據
與代碼的移動方向相反,數據的移動方向是從抽象類到具體類,向等級結構的下方移動。一個對象的數據不論是否使用都會占用資源,所以應當放到等級結構的低端。
什么時候才應當使用繼承復用
1.子類是超類的一個特殊種類,而不是超類的一個角色,Is-A才符合繼承關系。
2.永遠不會出現需要將子類換成另一個類的子類的情況。
3.子類具有擴展超類的責任,而不是具有置換掉(Override)和注銷掉(Nullify)超類的責任。
4.只有在分類學角度上有意義時,才可以使用繼承,不要從工具類繼承。
posted @
2009-08-03 23:15 xiaoxinchen 閱讀(975) |
評論 (0) |
編輯 收藏
什么是內聚?什么是耦合?
內聚是從功能角度來度量模塊內的聯系,一個好的內聚模塊應當恰好做一件事。它描述
的是模塊內的功能聯系; 耦合是軟件結構中各模塊之間相互連接的一種度量,耦合強弱取決
于模塊間接口的復雜程度、進入或訪問一個模塊的點以及通過接口的數據。
耦合性也稱塊間聯系。指軟件系統結構中各模塊間相互聯系緊密程度的一種度量。模塊之間聯系越緊密,其耦合性就越強,模塊的獨立性則越差。模塊間耦合高低取決于模塊間接口的復雜性、調用的方式及傳遞的信息。
2. 內聚分為哪幾類?耦合分為哪幾類?
內聚有如下的種類,它們之間的內聚度由弱到強排列如下:
(1) 偶然內聚。模塊中的代碼無法定義其不同功能的調用。但它使該模塊能執行不同
的功能,這種模塊稱為巧合強度模塊。
(2) 邏輯內聚。這種模塊把幾種相關的功能組合在一起, 每次被調用時,由傳送給模
塊參數來確定該模塊應完成哪一種功能
(3) 時間內聚:把需要同時執行的動作組合在一起形成的模塊為時間內聚模塊。
(4) 過程內聚:構件或者操作的組合方式是,允許在調用前面的構件或操作之后,馬上調用后面的構件或操作,即使兩者之間沒有數據進行傳遞。
(5) 通信內聚:指模塊內所有處理元素都在同一個數據結構上操作(有時稱之為信息內聚),或者指各處理使用相同的輸入數據或者產生相同的輸出數據。
(6) 順序內聚:指一個模塊中各個處理元素都密切相關于同一功能且必須順序執行,前一功能元素輸出就是下一功能元素的輸入。
(7) 功能內聚:這是最強的內聚,指模塊內所有元素共同完成一個功能,缺一不可。
耦合可以分為以下幾種,它們之間的耦合度由高到低排列如下:
(1) 內容耦合:如果發生下列情形,兩個模塊之間就發生了內容耦合
一個模塊直接訪問另一個模塊的內部數據
一個模塊不通過正常入口轉到另一模塊內部;
兩個模塊有一部分程序代碼重疊(只可能出現在匯編語言中);
一個模塊有多個入口。
(2) 公共耦合:若一組模塊都訪問同一個公共數據環境,則它們之間的耦合就稱為公共耦合。公共的數據環境可以是全局數據結構、共享的通信區、內存的公共覆蓋區等。
(3) 外部耦合:一組模塊都訪問同一全局簡單變量而不是同一全局數據結構,而且不是通過參數表傳遞該全局變量的信息,則稱之為外部耦合。
(4) 控制耦合:如果一個模塊通過傳送開關、標志、名字等控制信息,明顯地控制選擇另一模塊的功能,就是控制耦合
(5) 標記耦合:一組模塊通過參數表傳遞記錄信息,就是標記耦合。這個記錄是某一數據結構的子結構,而不是簡單變量。其實傳遞的是這個數據結構的地址;也就是地址傳遞。
(6) 數據耦合:指兩個模塊之間有調用關系,傳遞的是簡單的數據值,一個模塊訪問另一個模塊時,彼此之間是通過簡單數據參數 (不是控制參數、公共數據結構或外部變量) 來交換輸入、輸出信息的,相當于高級語言的值傳遞。
(7) 非直接耦合:兩個模塊之間沒有直接關系,它們之間的聯系完全是通過主模塊的控制和調用來實現的。
耦合強度,依賴于以下幾個因素:
(1)一個模塊對另一個模塊的調用;
(2)一個模塊向另一個模塊傳遞的數據量;
(3)一個模塊施加到另一個模塊的控制的多少;
(4)模塊之間接口的復雜程度。
參考資料:
http://baike.baidu.com/view/156245.html
http://www.cnblogs.com/dqshll/articles/1116799.html
http://blog.zol.com.cn/858/article_857495.html
posted @
2009-08-03 23:06 xiaoxinchen 閱讀(1602) |
評論 (0) |
編輯 收藏
用 jQuery 的都知道,jQuery 的 get 和 post 方法有三個參數:地址,數據
和回調函數,但我們知道地址也可以跟隨數據的(形如:get_data.php?v1=1&v2=2),而且第二個參數可以省略,即第二個參數可
以直接寫回調函數,那么數據寫在地址后面和寫在 data 參數里有什么區別呢?
剛剛做了幾個實驗,看看下面的代碼就清楚了:
以下內容需要回復才能看到
jquery_data.php
echo "post: ";
print_r($_POST);
echo "get: ";
print_r($_GET);
?>
jquery_test.html
實驗1:
$(function()
{
// post 方法,兩處都有數據
$.post('jquery_data.php?v1=1', {v2: 2}, function(data)
{
$('
').append(data).appendTo('body');
});
});
返回結果:
post: Array
(
[v2] => 2
)
get: Array
(
[v1] => 1
)
實驗2:
$(function()
{
// post 方法,數據在地址后面, 第二個參數為回調函數
$.post('jquery_data.php?v1=1', function(data)
{
$('<pre/>').append(data).appendTo('body');
});
});
返回結果,數據在 get 中:
post: Array
(
)
get: Array
(
[v1] => 1
)
實驗3:
$(function()
{
// get 方法,用 data 參數傳值
$.get('jquery_data.php', {v2: 2}, function(data)
{
$('<pre/>').append(data).appendTo('body');
});
});
返回結果,數據在 get 中:
post: Array
(
)
get: Array
(
[v2] => 2
)
實驗4:
$(function()
{
// get 方法,兩處都有數據
$.get('jquery_data.php?v1=1', {v2: 2}, function(data)
{
$('<pre/>').append(data).appendTo('body');
});
});
返回結果,兩處數據被合并了,都在 get 中:
post: Array
(
)
get: Array
(
[v1] => 1
[v2] => 2
)
實驗5:
$(function()
{
// get 方法,兩處都有數據,且變量名相同
$.get('jquery_data.php?v2=1', {v2: 2}, function(data)
{
$('<pre/>').append(data).appendTo('body');
});
});
返回結果,數據在 get 中,且 data 參數中的數據覆蓋了地址后面的數據:
post: Array
(
)
get: Array
(
[v2] => 2
)
通過這幾個簡單的小例子不難看出,地址后面的數據永遠是以 get 形式傳遞的,無論使用的是 get 方法還是 post 方法;而 data 參數中的數據是根據方法決定傳遞方式的。
因此,為了避免混淆,建議大家盡量不要把數據寫在地址后面,而是統一放在 data 參數中。
當然,如果你想在用 post 方法時,同時利用 get 傳值,那么就可以把要以 get 方式傳遞的數據寫在地址后面,把要以 post 方式傳遞的數據寫在 data 參數中。
總之方法是死的,人是活的,怎么用還要看實際情況。子曾經曰過:實踐是檢驗真理的唯一標準。沒事做做實驗,掌握知識更牢固。
posted @
2009-07-29 19:22 xiaoxinchen 閱讀(914) |
評論 (1) |
編輯 收藏
(zz from http://blog.csdn.net/heiyeshuwu)
Web
Service就是為了異構系統的通信而產生的,它基本的思想就是使用基于XML的HTTP的遠程調用提供一種標準的機制,而省去建立一種新協議的需求。
目前進行Web
Service通信有兩種協議標準,一種是XML-RPC,另外一種是SOAP。XML-RPC比較簡單,出現時間比較早,SOAP比較復雜,主要是一些
需要穩定、健壯、安全并且復雜交互的時候使用。
Web Service介紹¶
Web
Service就是為了異構系統的通信而產生的,它基本的思想就是使用基于XML的HTTP的遠程調用提供一種標準的機制,而省去建立一種新協議的需求。
目前進行Web
Service通信有兩種協議標準,一種是XML-RPC,另外一種是SOAP。XML-RPC比較簡單,出現時間比較早,SOAP比較復雜,主要是一些
需要穩定、健壯、安全并且復雜交互的時候使用。
PHP中集成了XML-RPC和SOAP兩種協議的訪問,都是集中在xmlrpc擴
展當中。另外,在PHP的PEAR中,不管是PHP 4還是PHP
5,都已經默認集成了XML-RPC擴展,而且該擴展跟xmlrpc擴展無關,能夠獨立實現XML-RPC的協議交互,如果沒有xmlrpc擴展,建議使
用PEAR::XML-RPC擴展。
我們這里主要是以XML-RPC來簡單描述Web Service的交互過程,部分內容來自PHP手冊,更詳細內容,建議參考手冊。
安裝xmlrpc擴展¶
如果你的系統中沒有安裝xmlrpc的php擴展,那么請正確安裝。
在
Windows平臺下,首先把PHP安裝目錄下的擴展php_xmlrpc.dll放到C:\Windows或者C:\Winnt目錄下,
(PHP4的擴展在C:\php\extensions目錄中,PHP5的擴展在C:\php\ext目錄中),同時在C:\Windows
\php.ini或者C:\Winnt\php.ini中把extension=php_xmlrpc.dll前面的分號";"去掉,然后重啟Web服務
器后查看phpinfo()有沒有XML-RPC項目就能夠確定是否已經正確安裝xmlrpc擴展。
在Unix/Linux平臺下,如果沒有安裝xmlrpc擴展,請在重新編譯PHP,在configure的時候請加入 --with-xmlrpc 選項,然后查看phpinfo()看是否正常安裝xmlrpc。
(注意:以下操作都是建立在xmlrpc擴張正常安裝前提下,請務必正確安裝。)
XML-RPC工作原理¶
XML-RPC大致就是整個過程就是使用XML來進行通信。首先構造一個RPC 服務器端用來出來從RPC客戶端傳遞過來的使用XML封裝的請求,并且把處理結果通過XML的形式返回給RPC客戶端,客戶端就去分析XML獲取自己需要的數據。
XML-RPC的服務器端必須有現成的函數提供給客戶端調用,并且客戶端提交的請求中的函數和方法必須和服務器端的一致,否則將無法獲取所需要的結果。
下面我進行簡單的代碼來描述整個過程。
XML-RPC實踐¶
服務器端使用xmlrpc_server_create函數產生一個服務器端,然后把需要需要暴露的RPC調用接口進行注冊,接受RPC客戶端POST過來的XML數據,然后進行處理,處理結果通過XML的形式顯示給客戶端。
代碼如下: rpc_server.php
<?php
/**
* 函數:提供給RPC客戶端調用的函數
* 參數:
* $method 客戶端需要調用的函數
* $params 客戶端需要調用的函數的參數數組
* 返回:返回指定調用結果
*/
function rpc_server_func($method, $params) {
$parameter = $params[0];
if ($parameter == "get")
{
$return = 'This data by get method';
}
else
{
$return = 'Not specify method or params';
}
return $return;
}
//產生一個XML-RPC的服務器端
$xmlrpc_server = xmlrpc_server_create();
//注冊一個服務器端調用的方法rpc_server,實際指向的是rpc_server_func函數
xmlrpc_server_register_method($xmlrpc_server, "rpc_server", "rpc_server_func");
//接受客戶端POST過來的XML數據
$request = $HTTP_RAW_POST_DATA;
//執行調用客戶端的XML請求后獲取執行結果
$xmlrpc_response = xmlrpc_server_call_method($xmlrpc_server, $request, null);
//把函數處理后的結果XML進行輸出
header('Content-Type: text/xml');
echo $xmlrpc_response;
//銷毀XML-RPC服務器端資源
xmlrpc_server_destroy($xmlrpc_server);
?>
服務器端構造好了,那么再構造我們的RPC客戶端。客戶端大致通過Socket訪問XML-RPC服務器端的80端口,然后把需要調用的RPC接口封裝到XML里,通過POST請求提交給RPC服務器端,最后獲取服務器端返回結果。
代碼如下:rpc_client.php
<?php
/**
* 函數:提供給客戶端進行連接XML-RPC服務器端的函數
* 參數:
* $host 需要連接的主機
* $port 連接主機的端口
* $rpc_server XML-RPC服務器端文件
* $request 封裝的XML請求信息
* 返回:連接成功成功返回由服務器端返回的XML信息,失敗返回false
*/
function rpc_client_call($host, $port, $rpc_server, $request) {
//打開指定的服務器端
$fp = fsockopen($host, $port);
//構造需要進行通信的XML-RPC服務器端的查詢POST請求信息
$query = "POST $rpc_server HTTP/1.0\nUser_Agent: XML-RPC Client\nHost: ".$host."\nContent-Type: text/xml\nContent-Length: ".strlen($request)."\n\n".$request."\n";
//把構造好的HTTP協議發送給服務器,失敗返回false
if (!fputs($fp, $query, strlen($query)))
{
$errstr = "Write error";
return false;
}
//獲取從服務器端返回的所有信息,包括HTTP頭和XML信息
$contents = '';
while (!feof($fp))
{
$contents .= fgets($fp);
}
//關閉連接資源后返回獲取的內容
fclose($fp);
return $contents;
}
//構造連接RPC服務器端的信息
$host = 'localhost';
$port = 80;
$rpc_server = '/~heiyeluren/rpc_server.php';
//把需要發送的XML請求進行編碼成XML,需要調用的方法是rpc_server,參數是get
$request = xmlrpc_encode_request('rpc_server', 'get');
//調用rpc_client_call函數把所有請求發送給XML-RPC服務器端后獲取信息
$response = rpc_client_call($host, $port, $rpc_server, $request);
//分析從服務器端返回的XML,去掉HTTP頭信息,并且把XML轉為PHP能識別的字符串
$split = '<?xml version="1.0" encoding="iso-8859-1"?>';
$xml = explode($split, $response);
$xml = $split . array_pop($xml);
$response = xmlrpc_decode($xml);
//輸出從RPC服務器端獲取的信息
print_r($response);
?>
大致我們上面的例子就是提交一個叫做rpc_server的方法過去,參數是get,然后獲取服務器端的返回,服務器端返回的XML數據是:
<?xml version="1.0" encoding="iso-8859-1"?>
<methodResponse>
<params>
<param>
<value>
<string>This data by get method</string>
</value>
</param>
</params>
</methodResponse>
那么我們再通過xmlrpc_decode函數把這個XML編碼為PHP的字符串,我們就能夠隨意處理了,整個Web Service交互完成。
結束語¶
不
管是XML-RPC也好,SOAP也罷,只要能夠讓我們穩定、安全的進行遠程過程的調用,完成我們的項目,那么就算整個Web
Service就是成功的。另外,如果可以的話,也可以嘗試使用PEAR中的XML-RPC來實現上面類似的操作,說不定會更簡單,更適合你使用。
http://phpxmlrpc.sourceforge.net/
posted @
2009-07-02 09:42 xiaoxinchen 閱讀(231) |
評論 (0) |
編輯 收藏
JPA常用標記說明¶
Table¶
Table用來定義entity主表的name,catalog,schema等屬性。
元數據屬性說明:
- name: 表名
- catalog: 對應關系數據庫中的catalog
- schema:對應關系數據庫中的schema
- UniqueConstraints:定義一個UniqueConstraint數組,指定需要建唯一約束的列
@Entity
@Table(name="CUST")
public class Customer { ... }
SecondaryTable¶
一個entity class可以映射到多表,SecondaryTable用來定義單個從表的名字,主鍵名字等屬性。
元數據屬性說明:
- name: 表名
- catalog: 對應關系數據庫中的catalog
- schema:對應關系數據庫中的schema
- pkJoin: 定義一個PrimaryKeyJoinColumn數組,指定從表的主鍵列
- UniqueConstraints:定義一個UniqueConstraint數組,指定需要建唯一約束的列
下面的代碼說明Customer類映射到兩個表,主表名是CUSTOMER,從表名是CUST_DETAIL,從表的主鍵列和主表的主鍵列類型相同,列名為CUST_ID。
@Entity
@Table(name="CUSTOMER")
@SecondaryTable(name="CUST_DETAIL",pkJoin=@PrimaryKeyJoinColumn(name="CUST_ID"))
public class Customer { ... }
SecondaryTables¶
當一個entity class映射到一個主表和多個從表時,用SecondaryTables來定義各個從表的屬性。
元數據屬性說明:
- value: 定義一個SecondaryTable數組,指定每個從表的屬性。
@Table(name = "CUSTOMER")
@SecondaryTables( value = {
@SecondaryTable(name = "CUST_NAME", pkJoin = { @PrimaryKeyJoinColumn(name = "STMO_ID", referencedColumnName = "id") }),
@SecondaryTable(name = "CUST_ADDRESS", pkJoin = { @PrimaryKeyJoinColumn(name = "STMO_ID", referencedColumnName = "id") }) })
public class Customer {}
UniqueConstraint¶
UniqueConstraint定義在Table或SecondaryTable元數據里,用來指定建表時需要建唯一約束的列。
元數據屬性說明:
- columnNames:定義一個字符串數組,指定要建唯一約束的列名。
@Entity
@Table(name="EMPLOYEE", uniqueConstraints={@UniqueConstraint(columnNames={"EMP_ID", "EMP_NAME"})})
public class Employee { ... }
Column¶
Column元數據定義了映射到數據庫的列的所有屬性:列名,是否唯一,是否允許為空,是否允許更新等。
元數據屬性說明:
- name:列名。
- unique: 是否唯一
- nullable: 是否允許為空
- insertable: 是否允許插入
- updatable: 是否允許更新
- columnDefinition: 定義建表時創建此列的DDL
- secondaryTable: 從表名。如果此列不建在主表上(默認建在主表),該屬性定義該列所在從表的名字。
public class Person {
@Column(name = "PERSONNAME", unique = true, nullable = false, updatable = true)
private String name;
@Column(name = "PHOTO", columnDefinition = "BLOB NOT NULL", secondaryTable="PER_PHOTO")
private byte[] picture;
...
JoinColumn¶
如果在entity class的field上定義了關系(one2one或one2many等),我們通過JoinColumn來定義關系的屬性。JoinColumn的大部分屬性和Column類似。
元數據屬性說明:
- name:列名。
- referencedColumnName:該列指向列的列名(建表時該列作為外鍵列指向關系另一端的指定列)
- unique: 是否唯一
- nullable: 是否允許為空
- insertable: 是否允許插入
- updatable: 是否允許更新
- columnDefinition: 定義建表時創建此列的DDL
- secondaryTable: 從表名。如果此列不建在主表上(默認建在主表),該屬性定義該列所在從表的名字。
下面的代碼說明Custom和Order是一對一關系。在Order對應的映射表建一個名為CUST_ID的列,該列作為外鍵指向Custom對應表中名為ID的列。
public class Custom {
@OneToOne
@JoinColumn(name="CUST_ID", referencedColumnName="ID", unique=true, nullable=true, updatable=true)
public Order getOrder() {
return order;
}
JoinColumns¶
如果在entity class的field上定義了關系(one2one或one2many等),并且關系存在多個JoinColumn,用JoinColumns定義多個JoinColumn的屬性。
元數據屬性說明:
- value: 定義JoinColumn數組,指定每個JoinColumn的屬性。
下面的代碼說明Custom和Order是一對一關系。在Order對應的映射表建兩列,一列名為CUST_ID,該列作為外鍵指向Custom對應表中名為ID的列,另一列名為CUST_NAME,該列作為外鍵指向Custom對應表中名為NAME的列。
public class Custom {
@OneToOne
@JoinColumns({
@JoinColumn(name="CUST_ID", referencedColumnName="ID"),
@JoinColumn(name="CUST_NAME", referencedColumnName="NAME")
})
public Order getOrder() {
return order;
}
聲
明當前field為映射表中的主鍵列。id值的獲取方式有五種:TABLE, SEQUENCE, IDENTITY, AUTO,
NONE。Oracle和DB2支持SEQUENCE,SQL
Server和Sybase支持IDENTITY,mysql支持AUTO。所有的數據庫都可以指定為AUTO,我們會根據不同數據庫做轉換。 NONE需要用戶自己指定Id的值。元數據屬性說明:
- generate():主鍵值的獲取類型
- generator():TableGenerator的名字(當generate=GeneratorType.TABLE才需要指定該屬性)
下面的代碼聲明Task的主鍵列id是自動增長的。(Oracle和DB2從默認的SEQUENCE取值,SQL Server和Sybase該列建成IDENTITY,mysql該列建成auto increment。)
@Entity
@Table(name = "OTASK")
public class Task {
@Id(generate = GeneratorType.AUTO)
public Integer getId() {
return id;
}
}
IdClass¶
當entity
class使用復合主鍵時,需要定義一個類作為id class。id
class必須符合以下要求:類必須聲明為public,并提供一個聲明為public的空構造函數。必須實現Serializable接,覆寫
equals()和hashCode()方法。entity class的所有id field在id class都要定義,且類型一樣。
元數據屬性說明:
public class EmployeePK implements java.io.Serializable{
String empName;
Integer empAge;
public EmployeePK(){}
public boolean equals(Object obj){ ......}
public int hashCode(){......}
}
@IdClass(value=com.acme.EmployeePK.class)
@Entity(access=FIELD)
public class Employee {
@Id String empName;
@Id Integer empAge;
}
MapKey¶
在一對多,多對多關系中,我們可以用Map來保存集合對象。默認用主鍵值做key,如果使用復合主鍵,則用id class的實例做key,如果指定了name屬性,就用指定的field的值做key。
元數據屬性說明:
下面的代碼說明Person和Book之間是一對多關系。Person的books字段是Map類型,用Book的isbn字段的值作為Map的key。
@Table(name = "PERSON")
public class Person {
@OneToMany(targetEntity = Book.class, cascade = CascadeType.ALL, mappedBy = "person")
@MapKey(name = "isbn")
private Map books = new HashMap();
}
OrderBy¶
在一對多,多對多關系中,有時我們希望從數據庫加載出來的集合對象是按一定方式排序的,這可以通過OrderBy來實現,默認是按對象的主鍵升序排列。
元數據屬性說明:
- value: 字符串類型,指定排序方式。格式為"fieldName1 [ASC|DESC],fieldName2 [ASC|DESC],......",排序類型可以不指定,默認是ASC。
下面的代碼說明Person和Book之間是一對多關系。集合books按照Book的isbn升序,name降序排列。
@Table(name = "MAPKEY_PERSON")
public class Person {
@OneToMany(targetEntity = Book.class, cascade = CascadeType.ALL, mappedBy = "person")
@OrderBy(name = "isbn ASC, name DESC")
private List books = new ArrayList();
}
PrimaryKeyJoinColumn¶
在三種情況下會用到PrimaryKeyJoinColumn。
- 繼承。
- entity class映射到一個或多個從表。從表根據主表的主鍵列(列名為referencedColumnName值的列),建立一個類型一樣的主鍵列,列名由name屬性定義。
- one2one關系,關系維護端的主鍵作為外鍵指向關系被維護端的主鍵,不再新建一個外鍵列。
元數據屬性說明:
- name:列名。
- referencedColumnName:該列引用列的列名
- columnDefinition: 定義建表時創建此列的DDL
下面的代碼說明Customer映射到兩個表,主表CUSTOMER,從表CUST_DETAIL,從表需要建立主鍵列CUST_ID,該列和主表的主鍵列id除了列名不同,其他定義一樣。
@Entity
@Table(name="CUSTOMER")
@SecondaryTable(name="CUST_DETAIL",pkJoin=@PrimaryKeyJoinColumn(name="CUST_ID",referencedColumnName="id"))
public class Customer {
@Id(generate = GeneratorType.AUTO)
public Integer getId() {
return id;
}
}
下面的代碼說明Employee和EmployeeInfo是一對一關系,Employee的主鍵列id作為外鍵指向EmployeeInfo的主鍵列INFO_ID。
@Table(name = "Employee")
public class Employee {
@OneToOne
@PrimaryKeyJoinColumn(name = "id", referencedColumnName="INFO_ID")
EmployeeInfo info;
}
PrimaryKeyJoinColumns¶
如果entity class使用了復合主鍵,指定單個PrimaryKeyJoinColumn不能滿足要求時,可以用PrimaryKeyJoinColumns來定義多個PrimaryKeyJoinColumn。
元數據屬性說明:
- value: 一個PrimaryKeyJoinColumn數組,包含所有PrimaryKeyJoinColumn。
下面的代碼說明了Employee和EmployeeInfo是一對一關系。他們都使用復合主鍵,建表時需要在Employee表建立一個外鍵,從Employee的主鍵列id,name指向EmployeeInfo的主鍵列INFO_ID和INFO_NAME.
@Entity
@IdClass(EmpPK.class)
@Table(name = "EMPLOYEE")
public class Employee {
private int id;
private String name;
private String address;
@OneToOne(cascade = CascadeType.ALL)
@PrimaryKeyJoinColumns({
@PrimaryKeyJoinColumn(name="id", referencedColumnName="INFO_ID"),
@PrimaryKeyJoinColumn(name="name" , referencedColumnName="INFO_NAME")})
EmployeeInfo info;
}
@Entity
@IdClass(EmpPK.class)
@Table(name = "EMPLOYEE_INFO")
public class EmployeeInfo {
@Id
@Column(name = "INFO_ID")
private int id;
@Id
@Column(name = "INFO_NAME")
private String name;
}
Transient¶
Transient用來注釋entity的屬性,指定的這些屬性不會被持久化,也不會為這些屬性建表。
@Transient
private String name;
Version¶
Version指定實體類在樂觀事務中的version屬性。在實體類重新由EntityManager管理并且加入到樂觀事務中時,保證完整性。每一個類只能有一個屬性被指定為version,version屬性應該映射到實體類的主表上。
下面的代碼說明versionNum屬性作為這個類的version,映射到數據庫中主表的列名是OPTLOCK。
@Version
@Column("OPTLOCK")
protected int getVersionNum() { return versionNum; }
Lob¶
Lob指定一個屬性作為數據庫支持的大對象類型在數據庫中存儲。使用LobType這個枚舉來定義Lob是二進制類型還是字符類型。
LobType枚舉類型說明:
- BLOB 二進制大對象,Byte[]或者Serializable的類型可以指定為BLOB。
- CLOB 字符型大對象,char[]、Character[]或String類型可以指定為CLOB。
元數據屬性說明:
- fetch: 定義這個字段是lazy loaded還是eagerly fetched。數據類型是FetchType枚舉,默認為LAZY,即lazy loaded.
- type: 定義這個字段在數據庫中的JDBC數據類型。數據類型是LobType枚舉,默認為BLOB。
下面的代碼定義了一個BLOB類型的屬性和一個CLOB類型的屬性。
@Lob
@Column(name="PHOTO" columnDefinition="BLOB NOT NULL")
protected JPEGImage picture;
@Lob(fetch=EAGER, type=CLOB)
@Column(name="REPORT")
protected String report;
JoinTable¶
JoinTable在many-to-many關系的所有者一邊定義。如果沒有定義JoinTable,使用JoinTable的默認值。
元數據屬性說明:
- table:這個join table的Table定義。
- joinColumns:定義指向所有者主表的外鍵列,數據類型是JoinColumn數組。
- inverseJoinColumns:定義指向非所有者主表的外鍵列,數據類型是JoinColumn數組。
下面的代碼定義了一個連接表CUST和PHONE的join table。join table的表名是CUST_PHONE,包含兩個外鍵,一個外鍵是CUST_ID,指向表CUST的主鍵ID,另一個外鍵是PHONE_ID,指向表PHONE的主鍵ID。
@JoinTable(
table=@Table(name=CUST_PHONE),
joinColumns=@JoinColumn(name="CUST_ID", referencedColumnName="ID"),
inverseJoinColumns=@JoinColumn(name="PHONE_ID", referencedColumnName="ID")
)
TableGenerator¶
TableGenerator定義一個主鍵值生成器,在Id這個元數據的generate=TABLE時,generator屬性中可以使用生成器的名字。生成器可以在類、方法或者屬性上定義。
生成器是為多個實體類提供連續的ID值的表,每一行為一個類提供ID值,ID值通常是整數。
元數據屬性說明:
- name:生成器的唯一名字,可以被Id元數據使用。
- table:生成器用來存儲id值的Table定義。
- pkColumnName:生成器表的主鍵名稱。
- valueColumnName:生成器表的ID值的列名稱。
- pkColumnValue:生成器表中的一行數據的主鍵值。
- initialValue:id值的初始值。
- allocationSize:id值的增量。
下面的代碼定義了兩個生成器empGen和addressGen,生成器的表是ID_GEN。
@Entity
public class Employee {
...
@TableGenerator(
name="empGen",
table=@Table(name="ID_GEN"),
pkColumnName="GEN_KEY",
valueColumnName="GEN_VALUE",
pkColumnValue="EMP_ID",
allocationSize=1
)
@Id(generate=TABLE, generator="empGen")
public int id;
...
}
@Entity
public class Address {
...
@TableGenerator(
name="addressGen",
table=@Table(name="ID_GEN"),
pkColumnValue="ADDR_ID"
)
@Id(generate=TABLE, generator="addressGen")
public int id;
...
}
SequenceGenerator¶
SequenceGenerator定義一個主鍵值生成器,在Id這個元數據的generator屬性中可以使用生成器的名字。生成器可以在類、方法或者屬性上定義。生成器是數據庫支持的sequence對象。
元數據屬性說明:
- name:生成器的唯一名字,可以被Id元數據使用。
- sequenceName:數據庫中,sequence對象的名稱。如果不指定,會使用提供商指定的默認名稱。
- initialValue:id值的初始值。
- allocationSize:id值的增量。
下面的代碼定義了一個使用提供商默認名稱的sequence生成器。
@SequenceGenerator(name="EMP_SEQ", allocationSize=25)
DiscriminatorColumn¶
DiscriminatorColumn定義在使用SINGLE_TABLE或JOINED繼承策略的表中區別不繼承層次的列。
元數據屬性說明:
- name:column的名字。默認值為TYPE。
- columnDefinition:生成DDL的sql片斷。
- length:String類型的column的長度,其他類型使用默認值10。
下面的代碼定義了一個列名為DISC,長度為20的String類型的區別列。
@Entity
@Table(name="CUST")
@Inheritance(strategy=SINGLE_TABLE, discriminatorType=STRING, discriminatorValue="CUSTOMER")
@DiscriminatorColumn(name="DISC", length=20)
public class Customer { ... }
posted @
2009-07-02 09:41 xiaoxinchen 閱讀(176) |
評論 (0) |
編輯 收藏
web.xml的配置¶
在web.xml中添加
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:/applicationContext-resources.xml
classpath:/applicationContext-dao.xml
classpath:/applicationContext-service.xml
classpath*:/applicationContext.xml
/WEB-INF/applicationContext*.xml
/WEB-INF/security.xml
/WEB-INF/dealer-security.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
事務的配置¶
<aop:config>
<aop:advisor id="managerTx" advice-ref="txAdvice" pointcut="execution(* *..service.*Manager.*(..))" order="0" />
</aop:config>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="find*" read-only="true"/>
<tx:method name="search*" read-only="true"/>
<tx:method name="get*" read-only="true"/>
<tx:method name="*" rollback-for="Throwable"/>
</tx:attributes>
</tx:advice>
ApplicationContext.xml的配置(spring bean 的配置)¶
<!--ProductManager-START-->
<bean id="productManager" class="com.eryiju.service.product.impl.ProductManagerImpl">
<constructor-arg ref="productDao" />
<property name="brandDao" ref="brandDao"></property>
</bean>
<!--ProductManager-END-->
<bean id="productDao" class="com.eryiju.dao.product.impl.ProductDaoHibernate">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<bean id="brandDao" class="com.eryiju.dao.product.impl.BrandDaoHibernate">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
常見問題¶
如何與hibernate整合¶
<!-- Hibernate SessionFactory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:hibernate.cfg.xml" />
<property name="hibernateProperties">
<value>
hibernate.dialect=${hibernate.dialect}
hibernate.query.substitutions=true 'Y', false 'N'
hibernate.cache.use_second_level_cache=true
hibernate.cache.use_query_cache=true
hibernate.cache.provider_class=com.eryiju.util.cache.EhCacheProvider
hibernate.show_sql=false
hibernate.connection.release_mode=after_statement
hibernate.cglib.use_reflection_optimizer=false
hibernate.search.default.directory_provider=org.hibernate.search.store.FSDirectoryProvider
hibernate.search.default.indexBase=/opt/dev/static/index
hibernate.jdbc.batch_size=50
hibernate.jdbc.fetch_size=50
</value>
<!-- Turn batching off for better error messages under PostgreSQL -->
</property>
</bean>
h2. (1)使用spring過濾器解決中文問題
在web.xml中添加:
<filter>
<filter-name>Spring character encoding filter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>GBK</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Spring character encoding filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
h2. (2)將applicationContext.xml分解成多個文件
applicationContext-common.xml
"dataSource"
"sessionFactory"
事務相關
applicationContext-dao.xml
UserDAO
applicationContext-biz.xml
UserManager
applicationContext-action.xml
Action
struts-config.xml中要作修改:
<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation" value="/WEB-INF/classes/applicationContext-*.xml" />
</plug-in>
h2. Spring2.0中的注解實現事務管理
第一步:引入<tx:>命名空間 ,在spring的配置文件中修改, beans根元素里多了三行,如下
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:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
第二步:在spring的配置文件中修改,將所有具有@Transactional 注解的bean自動配置為聲明式事務支持
Java代碼
<!--JDBC事務管理器,根據你的情況使用不同的事務管理器,如果工程中有Hibernate,就用Hibernate的事務管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource">
<ref local="dataSource"/>
</property>
</bean>
<!-- 用注解來實現事務管理 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
第三步: 在接口或類的聲明處 ,寫一個@Transactional. 要是只的接口上寫, 接口的實現類就會繼承下來.
接口的實現類的具體方法,還可以覆蓋類聲明處的設置.
Java代碼
@Transactional
public class TestPOAOImpl extends POAOBase implements TestPOAO
{
@Transactional(isolation = Isolation.READ_COMMITTED)
public void test1()
{
String sql = "INSERT INTO sy_test (NAME,AGE) VALUES('注解趙云',30)";
execute(sql);
sql = "INSERT INTO sy_test (NAME,AGE) VALUES('注解張飛',26)";
execute(sql);
int a = 9 / 0; //異常
sql = "INSERT INTO sy_test (NAME,AGE) VALUES('注解關羽',33)";
execute(sql);
System.out.println("走完了");
}
//execute() 方法略...
}
注意的幾點:
1 @Transactional 只能被應用到public方法上, 對于其它非public的方法,如果標記了@Transactional也不會報錯,但方法沒有事務功能.
2 默認情況下,一個有事務方法, 遇到RuntiomeException 時會回滾 . 遇到 受檢查的異常 是不會回滾 的. 要想所有異常都回滾,要加上 @Transactional( rollbackFor={Exception.class,其它異常}) .
posted @
2009-07-02 09:40 xiaoxinchen 閱讀(185) |
評論 (0) |
編輯 收藏
摘要: 概述
Maven的目標
對Maven的錯誤理解
Maven的版本
Maven的安裝
Windows 2000/xp下的安裝
基于Unxi-based的操作系統(Linux,Solaris and Mac OS X)
查看依賴庫的位置
http://mvnrepository.com/
Maven主要功能
...
閱讀全文
posted @
2009-07-02 09:39 xiaoxinchen 閱讀(533) |
評論 (0) |
編輯 收藏
sudo apt-get install mysql
命令行操作¶
mysql -u用戶名 -p密碼 -h數據庫地址(ip) 數據庫名稱
注意:盡量不要在-p后直接跟密碼,否則其他人很容易通過查閱命令行歷史記錄(比如,history命令)看到你的密碼。
SQL參考¶
MySQL參考¶
常見數據類型¶
integer(11) 11位字節的整數
tinyint(1)
bigint(20)
decimal(10,2) 小數
varchar(20) 最長為20位字節的可變字符串
char(20) 最長為20位字節的定長字符串(定長指的是存儲空間定長)
text 文本,用于存大量不固定長度的文本信息
blob 二級制信息
常見函數¶
length(str) 字符串的長度
trim(str) 去掉字符串前后的空格
substring(str,1) 獲取子串
convert(str using gbk) 將字符串轉化為gbk編碼
reverse(str) 倒序
增刪改查¶
insert into product (sku,name) values ('123456','productname')
向表中添加sku=123456,name='productname' 的數據
update product set name='updated product name' where sku='123456'
將表product中的sku為'123456'的數據的name字段的值設置為'updated product name'
select sku,name from product where sku='123456'
從表product 中查詢 sku為'123456'的數據
delete from product where sku='123456'
其他操作實例¶
多表查詢¶
select p.sku,b.name from product p,brand b where p.brand_id=b.id and p.sku='123456'
子查詢¶
select p.sku,p.name from product p where p.brand_id in (select id from brand where id=123)
左連接¶
select p.sku,p.name,b.name from product p left join brand b on p.brand_id=b.id
從一個表導入數據到另一個表¶
insert into product1 (sku,name,brand_id) (select sku,name,brand_id from product2)
查找不同的數據¶
select distinct p.sku from product p
查詢時按照某個字段排序(asc升序,desc降序)¶
select * from product order by name desc
常見問題¶
如何創建表¶
CREATE TABLE product (
`sku` char(6) NOT NULL COMMENT '商品的唯一標識\n',
`brand_id` int(11) default NULL,
`name` varchar(50) default NULL,
PRIMARY KEY (`sku`),
CONSTRAINT `brand_fk_constraint` FOREIGN KEY (`brand_id`) REFERENCES `brand` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
如何創建外鍵¶
alter table product add CONSTRAINT `brand_fk_constraint` FOREIGN KEY (`brand_id`) REFERENCES `brand` (`id`)
如何修改表中的字段¶
alter table product modify name varchar(200)
如何向表中添加字段¶
alter table product add comment varchar(200)
如何刪除表中字段¶
alter table product drop name
存儲過程和觸發器¶
h3.mysql創建表
drop table if exists news;
/*==========================*/
/* Table: 消息表 */
/*==========================*/
create table news
(
NewsId bigint(20) not null unsigned primary key auto_increment,
NewsContext varchar(50) not null,
NewsType varchar(50) not null,
UsersId int(11) not null
);
alter table news add constraint FK_Id foreign key (NewsId)
references users (UsersId);
官方參考:http://dev.mysql.com/doc/
posted @
2009-07-02 09:38 xiaoxinchen 閱讀(118) |
評論 (0) |
編輯 收藏