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能够从数据库中获取。