所假设背景: 一开始数据操作和业务逻辑混在一起 ----->用dao模式把数据访问和业务逻辑进行分离---->进一解耦业务逻辑代码和数据访问类(具体的数据访问实现类),便引进了Factory模式------>为了使实现类具备可配置性也就是说当我需要哪个实现类时我只需要在xml里配下就可以了,而不同去改Factory的代码,那么就可以利用反射机制在运行时动态创建,其思想还是使用DAO和工厂模式来实现,这其实有点IOC的味道.
#1)DAO模式包括data accessor 和active domain Object, data accessor对数据操作进行了抽象,而domain object对数据进行了封装,这样可以方便地把数据逻辑从业务逻辑代码中分离出来,在XCS系统的support中曾经做过这种工作。------>Hibernate实际使用了这两个模式,使把数据访问从业务逻辑中分离出来成为了可能。这就是Hibernate在解耦合方面的帮助。===>这里所谓的数据访问是指类如查询,update等操作。而domain boject就类如formbean那样对resultset得到的数据进行封装。
#2)对于XCS,它只是给马客户用的专门定制系统,它只有一个特定的环境,但有很多系统需要在不同的客户环境中安装,这就需要考虑不同客户有不同的运行环境了,特别是有不同的数据库环境,所以如果有使用了Hibernate作为持久化层,那么你的系统便可以跨数据库,移植性较好.
#3)现在假设不同的客户使用不同的数据库环境,A用mysql,B用oracle,C用sqlserver,我们的系统为了能满足部署在这三种不同的环境中,那么我们的数据访问类就要实现不同数据库的data accessor。这时我们可以考虑使用一个接口,然后针对这个接口实现不同的数据访问,而我的客户端程序只需要面向该接口就可以了。
为了进一步解耦合以及集中地管理及创建各种不同实现类的实例,我们可以引进Factory模式,Factory模式在这里起到连接接口和实现的桥梁作用,通过Factory模式,我们可以根据具体需要加载相应的实现,并将此实现作为所对应接口的一个实例提供给业务层使用。如果在进一步,将实现类不是显式在Factory里创建实例,而是将其配制在xml里面,再运行时通过放射机制来创建,那么就有点IOC的味道。===>其实IOC就是利用这个原理来实现的,所有配置的bean也就是实现类最后会在一个factory里统一创建(待证)。
#如果每个操作都独立获取一个数据库连接进行操作,那么会由于频繁的数据连接释放等操作带来很大的性能消耗,从而降低系统的性能。可以使用连接池来解决这个问题。我可以自己写一个连接池,如XCS,但最好是使用应用服务器内置的连接池机制,往往我们在使用datasource时便使用了该应用服务器的连接池机制。DBCP/Proxool
#Hibernate是一种封装jdbc技术的框架,它提供性能优化机制:内置的数据库连接池支持? PreparedSatement缓存? 数据缓存?(待证)
#通过观察源代码发现,new configuration时便new了setting的factory对象,调用configure()方法时便读到hibernate的配置文件,then 便是buildSessionFactory,此法方法会首先执行buildsetting的方法,在buildsetting方法中主要根据Eviroment中的constant value作为key去获取hibernate配置文件的属性值,然后set到setting对象里。setting就是一个带有getter和setter的bean。最后以mapping,setting等对象为参数创建sessionFactory对象。接下来便是用session的工厂类对象sessionfactory来创建色素sion对象,一般使用opensession,opensession主要是利用之前set在setting对象里面的属性值(实际值来自配置文件)来给sessionImpl的相关属性进行赋值,这样我在配置文件里配置的属性便可以顺利到达session对象了,在赋值之后,在需要使用的地方便可以通过session的属性来描述特性的行为规定了。这些属性大概描述了在这种配置下的一个session大概是什么样子。比如它是使用默认的jdbc transaction还是用户自己提供的transaction 类。这一路下来从读文件到解析文件到set到set到像setting,mapping 这一类对象,最终到达像session这样的对象之后,基本的前提环境(大概背景)便建立了。接下来用session对数据库进行的增删查改的操作都是在这种前提环境下工作的,简单一点就是你要什么样的工作环境,便可以在hibernate配置文件中设置,那么最终你的session便会在那种环境下工作了,接下来便可以调用session里面的load,get ,save,delete等方法进行操作数据库。
###其实hibernate里任何方法的操作比如session.save 等,都只是给hibernate传递了一个indicator,并没有真正地执行了save数据到数据库的动作,它只是告诉hibernate说我有save这个动作,hibernate在经过判读处理后将该对象设置一个标记是save还是update还是其他,等到flush或commit时才执行相对相应的sql来操作数据库
###Collection在判断两个对象是否相等的时候,会首先调用对象的hashCode方法,如果hashCode相同的话,随即调用其equals方法,如果两次判断均为真,则认为对比的两个对象相等.
###缓存是什么?
其实缓存是为了在用户重复使用数据时能到减少对数据库的连接等操作的开销 而在内存中维持一块临时容器来保存数据。不过在使用缓存时有一定的策略,比如可以把缓存应用于事务级,那么在同一个事务中的应用便可共享该数据。如果选择使用应用级别的事务,那么在该应用下的多个事务便可共享该数据。如果使用分布式策略,那么不同的jvm之间的应用便可共享该数据。所以在对某些数据进行使用缓存时,必须要考虑缓存策略。对于hibernate来说,它依靠session,实现了事务级别的缓存,也就是在session内维持一个数据缓存,实际上是一些hashmap维持了session对象及各个实体对象的缓存关系,一般叫一级缓存。另外,Hibernate也在SessionFactory的层次实现了应用级别的缓存策略,它可以通过配置文件由developer指定具体的缓存实现,但通过使用二级缓存,各个事务便可共享维持在该缓存里面的数据,一般称为二级缓存。在Hibernate里叫多个session可以共享该数据是因为hibernate的事务是基于session来实现的,他们具有相同的生命周期。
###对于什么数据使用二级缓存?
由于缓存的目的是为了在user再次使用数据时不用去操作数据库进而减少连接数据库次数等开销,所以该数据必须是user需要重复引用的,由于数据维持在缓存中实际就是一些hashmap中,如果数据太大,会占据很多的内存,就会影响性能所以这些数据的大小必须是可以接受的。另外,由于该数据维持在缓存中供user不同时候重复使用,如果该数据被更新了或被第三方修改了,那么该数据维持在缓存中的值就没什么意义了,所以放在缓存中的数据就要尽可能不要去更新它,也就是更新频率要低。另外数据不应会被第三方数据修改。最后,如果该数据很关键,你放它放在缓存里,容易造成脏数据或搞错数据,所以太重要太关键的数据也不要放到二级缓存中。
###在使用session的各个方法进行查询操作时,首先在自身内部的一级缓存中进行查找,如果一级缓存未能命中,则在二级缓存中查询。也就是说首先在它所在的事务中的所维持的事务级别缓存中进行查找,如果找不到,便会到跟高一层的应用级别的事务的所维持的共享数据中查找(自己的找不到,看其它人共享的找不找的到),如果命中,则返回。
###第三方的缓存产品可以使用EHCache.通过hibernat预留的接口在 配置文件中配置便可使用。
###当我们决定对某些数据比如某个实体使用二级缓存时,必须为该实体类指定相应的缓存同步策略,这样便可以使用正确的隔离机制。
###