Hibernate的優勢html
1.對象/關係數據庫映射(ORM)算法
它使用時只須要操做對象,使開發更對象化,拋棄了數據庫中心的思想,徹底的面對對象思想數據庫
2.透明持久化(persistent)編程
帶有持久化狀態、具備業務邏輯的單線程對象,此對象生存期很短。 這些對象多是普通的JavaBeans/POJO,這個對象沒有實現第三方框架或者接口,惟一特殊的是他們正在與(僅僅一個)Session相關聯。一旦這個Session被關閉,這些對象就會脫離持久化狀態,這樣就能夠被應用程序的任何層自由使用。(列如,用做跟表示層交互數據和傳輸對象)。數組
3.事務Transaction(org.hibernate.Transaction)緩存
應用程序用來指定原子操做的單元範圍的對象,它是單線程的,生命週期很短。他經過抽象將應用從底層具體的JDBC、JTA以及CORBA事務隔離開。某些狀況下,一個Session安全
以內可能包含多個Transaction對象。儘管是否使用該對象是可選的,但不管是使用底層的API仍是使用Transaction對象,事務邊界的開啓與關閉是必不可少的。
(4) 它沒有侵入性,即所謂的輕量級框架
(5) 移植性會很好
(6) 緩存機制,提供一級緩存和二級緩存
(7) 簡潔的HQL編程
2. Hibernate缺點
(1) Hibernate在批量數據處理時有弱勢
(2) 針對單一對象簡單的增刪查改,適合於Hibernate,而對於批量的修改,刪除,不適合用Hibernate,這也是OR框架的弱點;要使用數據庫的特定優化機制的時候,不適合用Hibernate多線程
Struts2的工做流程app
請求在Struts2框架中的處理大概分爲如下幾個步驟: 1 客戶端初始化一個指向Servlet容器的請求; 2 這個請求通過一系列的過濾器(Filter)(這些過濾器中有一個叫作ActionContextCleanUp的可選過濾器,這個過濾器對於Struts2和其餘框架的集成頗有幫助,例如:SiteMesh Plugin) 3 接着FilterDispatcher被調用,FilterDispatcher詢問ActionMapper來決定這個請是否須要調用某個Action 4 若是ActionMapper決定須要調用某個Action,FilterDispatcher把請求的處理交給ActionProxy 5 ActionProxy經過Configuration Manager詢問框架的配置文件,找到須要調用的Action類 6 ActionProxy建立一個ActionInvocation的實例。 7 ActionInvocation實例使用命名模式來調用,在調用Action的過程先後,涉及到相關攔截器(Intercepter)的調用。 8 一旦Action執行完畢,ActionInvocation負責根據struts.xml中的配置找到對應的返回結果。返回結果一般是(但不老是,也可 能是另外的一個Action鏈)一個須要被表示的JSP或者FreeMarker的模版。在表示的過程當中可使用Struts2 框架中繼承的標籤。在這個過程當中須要涉及到ActionMapper框架
延遲加載,也較延遲實例化,延遲初始化等,主要表達的思想就是,把對象的建立延遲到使用的時候建立,而不是對象實例化的時候建立。這種方式避免了性能的浪費。
當建立一個對象的子對象開銷比較大時,並且有可能在程序中用不到這個子對象,那麼久能夠考慮用延遲加載的方式來建立子對象。另外就是當一個程序啓動時,須要建立多個對象,但僅有幾個對象須要當即使用,那麼能夠將一些沒必要要的初始化工做延遲到使用的時候。這樣能夠提升程序的啓動速度。
FramWork4.0中提供了一個包裝類Lazy<T>,能夠輕鬆實現延遲加載。
今天就先從延遲加載開始學起。
1、延遲加載
一、Class Singleton
{
private static Singleton instance;
private Singleton()
{ }
public static Singleton getInstance()
{
If(instance==null)
{
Instance=new Singleton();
}
Return instance;
}
}
構造函數私有,方法靜態。
問題:沒法保證線程安全,當有多個線程同時訪問getInstance的時候,此時若對象爲空,就會出現會多個線程同時產生多個Singleton對象。
此時咱們能夠修改一下上面的代碼,以下
上述代碼使用了雙重鎖方式較好地解決了多線程下的單例模式實現。先看內層的if語句塊,使用這個語句塊時,先進行加鎖操做,保證只有一個線程能夠訪問該語句塊,進而保證只建立了一個實例。再看外層的if語句塊,這使得每一個線程欲獲取實例時沒必要每次都得加鎖,由於只有實例爲空時(即須要建立一個實例),才需加鎖建立,若果已存在一個實例,就直接返回該實例,節省了性能開銷。
二、若是使用以下的單例模式
class Singleton
{
private static Singleton instance = new Singleton();
private Singleton()
{
//
}
public static Singleton getInstance()
{
return instance;
}
}
這個方法保證了在第一次加載的時候實例被初始化,且保證了線程安全。可是爲進一步要求,咱們想要在使用的時候才才初始化Singleton對象,及延遲加載。那麼可使用以下方法。
三、延遲加載
public class Singleton {
private Singleton(){
}
private static class SingletonHolder
{
static Singleton instance = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.instance;
}
public static void main(String [] args)
{
Singleton.getInstance();
}
}
方法中Singleton 有一個靜態內部類SingletonHolder,內部類在外部加載的時候並不會加載,在有在調用getInstance纔回加載。另外SingletonHolder類使用Private修飾以確保外部類不能訪問。
2、下面再看一個實例
namespace WebApplication2
{
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
// 從數據庫中取出數據,獲得一個DateRow或者DateRader之類的東東而後初始化一個文章實體類對象
Model_Article at = 。。。。;//at=getobject();
// 建立文章分類數據訪問對象
DAO_ArticleCategory articleCategory = new DAO_ArticleCategory();
subArticle sarticle = new subArticle();
sarticle.CategoryLazyLoader = articleCategory.GetArticleCategoryById;
sarticle.CategoryLazyLoader(1);
Model_ArticleCategory acc = at.Category;
//
}
}
// 文章分類實體類
public class Model_ArticleCategory
{
public int CategoryID { get; set; }
public string CategoryName { get; set; }
}
public class DAO_ArticleCategory
{
public Model_ArticleCategory GetArticleCategoryById(int i)
{
return new Model_ArticleCategory();
}
}
// 文章實體類
public class Model_Article
{
public int ArticleID { get; set; }
public string Title { get; set; }
public string Cotnent{ get; set; }
public DateTime CreateTime { get; set; }
public int CategoryID { get; set; }
// 文章所屬分類
protected Model_ArticleCategory _category;
public virtual Model_ArticleCategory Category //聲明爲虛屬性
{
get
{
GetCategoryRecord += "獲取分類;";
return _category;
}
}
public string GetCategoryRecord { get; set; }
}
//繼承父類,把原來父類中得邏輯放到子類中來實現,保證了父類所處Model層沒有引用其餘業務層,保證了框架的規則
public class subArticle : Model_Article
{
public override Model_ArticleCategory Category
{
get
{
if (base._category == null)
{
if (CategoryLazyLoader != null)
{
_category = CategoryLazyLoader(CategoryID);
}
else
{
_category = null;
}
}
return base.Category;
}
}
// 文章分類延時加載器(委託)
public Func<int, Model_ArticleCategory> CategoryLazyLoader { get; set; }
}
}
基類的Category屬性經過返回_category字段的方式返回值,也就是說數據是存在_category字段而不是屬性中,可是_category字段怎麼纔會有值呢,那就是在子類裏面經過調用委託拿來的,而這個屬性在子類裏面不是直接返回的,而是調用基類來返回,這樣一來,調用到子類的Category屬性的get訪問器的時候,先對基類的_categoty字段賦值,而後調用基類的Category屬性執行了一些邏輯代碼,最後成功地把(已經被賦值的)基類的_categoty字段給返回去。而這一切都是在前面咱們實現好的延遲加載的基礎上完成的。總結成幾個字就是:子類負責延時加載,基類賦值數據存儲和返回!
關閉原則的理解
開-閉原則:一個軟件實體應該對擴展開放,對修改關閉。
知足開閉原則的模塊符合下面兩個標準:
這兩個標準看似相互矛盾的,那麼咱們怎麼實現他們呢?
怎樣實現開閉原則?
考慮下面某個類的方法:
上面函數的功能是計算給定的零件數組中全部零件價格的總和,若是Part是一個基類或者接口,那咱們就能夠利用多態的特性,當有新的零件被添加進來時不須要修改該函數的代碼。這樣它就能夠知足開閉原則。
可是若是咱們的會計部門規定當計算主板和內存的價格時,須要添加一些額外的費用,請看下面的代碼:
如今它還符合開閉原則嗎?不!每次會計部門發佈一個新的價格政策時,咱們都須要修改totalPrice()方法!它對修改不是關閉的,顯然,價格政策的改變意味着咱們必須修改某處的代碼,那麼咱們應該怎麼作呢?爲了使用咱們第一個版本的totalPrice()方法,咱們須要把Part的getPrice()方法的價格政策包含進來。
下面是Part和ConcretePrat類:
可是,如今若是價格政策改變,咱們必須修改Part的子類,一個更好的方法是創建一個PricePolicy類,它能夠爲咱們提供不一樣的價格政策:
使用這種方法,咱們能夠在運行時動態的設置Part對象所引用的PricePoilcy對象,在實際的程序中,零件的價格和相關的PricePolicy能夠從數據庫中獲取。