Java知识整理(下)

数据库

NOSQL

CAP理论

在理论计算机科学中,CAP定理(CAP theorem)指出对于一个分布式计算系统来讲,不可能同时知足如下三点:前端

  • 一致性(Consistency):同一个数据在集群中的全部节点,同一时刻是否都是一样的值。
  • 可用性(Availability):集群中一部分节点故障后,集群总体是否还能处理客户端的更新请求。
  • 分区容忍性(Partition tolerance):是否容许数据的分区,分区的意思是指是否容许集群中的节点之间没法通讯。

但实际上用户关心的是,只要写入数据成功了,那我下次读取该数据时,老是能读取到最新写入的数据。因此,只要咱们的数据库作到了这一点,那数据库里的数据对于用户而言,就是具备一致性的。 NRW算法java

假设总共有五个节点(N),咱们只要保证写入数据的节点数(W)+ 读取数据的节点数(R)大于总节点数便可。即保证W+R>N,那就能保证对客户端而言,老是能读取到它最新写入的数据。好比,总节点数为5,写入节点数为3,读取节点数为3,那咱们就能保证客户端老是能读取到它最新写入的数据。有了这样的数据公式的做为理论保证。咱们就能够根据状况灵活选择W,R了。因为咱们不须要保证5台机器所有都写入成功,只须要保证3台写入成功便可。这就意味着,咱们容许5台机器中的2台出现问题,也就是提升了系统的可用性。这样的设计,虽然集群节点之间,也许有些节点的数据不是最新的,也就是没有作到CAP中的C,但对用户来讲,数据老是一致的。web

有了NRW算法,咱们就能作到,在知足AP的前提下,咱们彻底还能够作到对用户而言的数据一致性,因此大多数NOSQL数据库选择了A(可用性)与P(分区可容忍性)。算法

MongoDB

MongoDB 是一个可扩展的高性能,开源,模式自由,面向文档的分布式文件存储数据库。模式自由,高性能,易扩展,灵活查询,弱事物。spring

  • 面向集合的存储:适合存储对象及JSON形式的数据。
  • 动态查询:Mongo 支持丰富的查询方式,查询指令使用 JSON 形式的标记,可轻易查询文档中内嵌的对象及数组。
  • 完整的索引支持:包括文档内嵌对象及数组。Mongo 的查询优化器会分析查询表达式,并生成一个高效的查询计划。
  • 查询监视:Mongo包含一个监控工具用于分析数据库操做性能。
  • 复制及自动故障转移:Mongo 数据库支持服务器之间的数据复制,支持主-从模式及服务器之间的相互复制。复制的主要目的是提供冗余及自动故障转移。
  • 高效的传统存储方式:支持二进制数据及大型对象(如:照片或图片)。
  • 自动分片以支持云级别的伸缩性:自动分片功能支持水平的数据库集群,可动态添加额外的机器。

适用场景sql

  • 实时数据:Mongo 很是适合实时的插入,更新与查询,并具有网站实时数据存储所需的复制及高度伸缩性。
  • 缓存:因为性能很高,Mongo 也适合做为信息基础设施的缓存层。在系统重启以后,由 Mongo 搭建的持久化缓存能够避免下层的数据源过载。
  • 日志数据:适合存储大量的非结构化的低价值数据。
  • 高伸缩性:Mongo很是适合由数十或数百台服务器组成的数据库
  • 结构松散:用于对象及JSON数据的存储:Mongo的BSON数据格式很是适合文档格式化的存储及查询
  • 大型文件存储:分布式的文件存储
  • 地理位置:基于地理位置,物理空间的搜索

不适合的场景数据库

  • 高度事务性的系统:例如银行或会计系统。传统的关系型数据库目前仍是更适用于须要大量原子性复制事物的应用程序。
  • 传统的商业智能应用:针对特定问题的 BI 数据库会对产生高度优化的查询方式。对于此类应用,数据仓库可能时更适合的选择(如Hadoop套件中的Hive)。
  • 须要SQL的问题。

MongoDB高可用集群

  1. Master-Slave主从结构 enter description here 主从架构通常用于备份或者作读写分离。通常有一主一从设计和一主多从设计。由两种角色构成: (1)主(Master) 可读可写,当数据有修改的时候,会将oplog同步到全部链接的salve上去。 (2)从(Slave) 只读不可写,自动从Master同步数据。 特别的,对于Mongodb来讲,并不推荐使用Master-Slave架构,由于Master-Slave其中Master宕机后不能自动恢复,推荐使用Replica Set。编程

  2. Relica Set副本集 enter description here Mongodb的Replica Set即副本集方式主要有两个目的,一个是数据冗余作故障恢复使用,当发生硬件故障或者其它缘由形成的宕机时,可使用副本进行恢复。另外一个是作读写分离,读的请求分流到副本上,减轻主(Primary)的读压力。 (1)主节点(Primary) 接收全部的写请求,而后把修改同步到全部Secondary。一个Replica Set只能有一个Primary节点,当Primary挂掉后,其余Secondary或者Arbiter节点会从新选举出来一个主节点。默认读请求也是发到Primary节点处理的,须要转发到Secondary须要客户端修改一下链接配置。 (2)副本节点(Secondary) 与主节点保持一样的数据集。当主节点挂掉的时候,参与选主。 (3)仲裁者(Arbiter) 不保有数据,不参与选主,只进行选主投票。使用Arbiter能够减轻数据存储的硬件需求,Arbiter跑起来几乎没什么大的硬件资源需求数组

  3. Sharding分片技术 enter description here MongoDB分片技术相似MySQL的水平切分和垂直切分,数据库主要由两种方式作Sharding:垂直扩展和横向切分。垂直扩展的方式就是进行集群扩展,添加更多的CPU,内存,磁盘空间等。横向切分则是经过数据分片的方式,经过集群统一提供服务: A.数据分片(Shards) 用来保存数据,保证数据的高可用性和一致性。能够是一个单独的mongod实例,也能够是一个副本集。在生产环境下Shard通常是一个Replica Set,以防止该数据片的单点故障。全部Shard中有一个PrimaryShard,里面包含未进行划分的数据集合: B.查询路由(Query Routers) 路由就是mongos的实例,客户端直接链接mongos,由mongos把读写请求路由到指定的Shard上去。一个Sharding集群,能够有一个mongos,也能够有多mongos以减轻客户端请求的压力。 C.配置服务器(Config servers) 保存集群的元数据(metadata),包含各个Shard的路由规则。浏览器

  4. 总结 自动分片是一个很是理想的选择,但自动分片在真实的应用场景中仍是会有不少的坑,除非咱们在这条路上不断踩坑并不断填坑,拥有足够的实力、足够的经验,掌控好其每一个细节,那咱们不妨能够选择自动分片。但不少公司仍是避开这条路,选择手动分片方式,其最大缘由就是手动分片可控能力强。

数据安全机制

对于数据安全,MongoDB2.6+ 就有了很是完善的机制,并且还很灵活。从不返回结果、确认主服务器写内存、确认主服务器写journal日志、确认同步到大多数服务器到强制写入磁盘,MongoDB数据安全级别逐渐提升。开发者能够根据不一样的应用场景选择适合的安全级别,在数据安全和写操做的性能之间找到平衡。 根据以往踩过的坑和同行经验,总结出如下几点建议。

最低WriterConcern.SAFE:若是没有特殊要求,最低级别也要使用WriterConcern.SAFE,即w=1。对于不重要的数据,好比log日志,可使用WriterConcern.NONE或者WriterConcern.NORMAL,即w=-1或者w=0,省去等待网络的时间。

集群WriterConcern.MAJORITY:通常来讲,在集群中使用WriterConcern.MAJORITY设置。在一个集群是健壮的部署的状况下(足够网络带宽,机器没有满负荷),这个能够知足绝大部分数据安全的要求。由于MongoDB的复制在正常状况下是毫秒级别的,每每在Journal刷盘以前已经复制到从节点了。若是你追求完美,那么能够再进一步使用 {w: “majority”,j:1} 。

批量操做,一次getLastError:对大量的不连续的数据写入,若是每次写入都调用getLastError会下降性能,由于等待网络的时间太长,这种状况下,能够每过N次调用一下getLastError。可是在Shard结构上,这种方式不必定确保以前的写入是成功的。对连续的批量写入(batchs of write),要在批量写入结束的时候调用getlastError,这不只能确保最后一次写入正确,并且也能确保全部的写入都能到达服务器。若是连续写入上万条记录而不调用getlastError,那么不能确保在同一个TCP socket里全部的写入都成功。这在并发的状况下可能就会有问题。避免这个并发问题,能够参考如何在一个连接(请求)里完成批量操做,MongoDB Java Driver并发。 保证安全:对数据安全要求很是高的的配置:j=true,w="majority",db.runCommand({getlasterror:1,j:true,w:'majority',wtimeout:10000}) 灵活设置:大多数语言的驱动程序均可以在MongoOption中设置,MongoOption中的这些设置是全局的,对于单独的一个链接或一次操做,还能够分别设置。

Oracle

特性

功能丰富、稳定性、安全性、易管理、高性能、复琐事务、分布式、跨平台,还有商业支持 缺点是收费高、不开源。

索引

Oracle中常见的索引分类有B树索引和位图索引。

  1. B树索引(默认索引,保存讲过排序过的索引列和对应的rowid值) enter description here oracle中最经常使用的索引;B树索引就是一颗二叉树;叶子节点(双向链表)包含索引列和指向表中每一个匹配行的ROWID值 全部叶子节点具备相同的深度,于是无论查询条件怎样,查询速度基本相同 可以适应精确查询、模糊查询和比较查询 分类: UNIQUE,NON-UNIQUE(默认),REVERSE KEY(数据列中的数据是反向存储的) 建立例子 craete index index_sno on student('sno'); 适合使用场景:列基数(列不重复值的个数)大时适合使用B数索引

  2. 位图索引 建立位图索引时,oracle会扫描整张表,并为索引列的每一个取值创建一个位图(位图中,对表中每一行使用一位(bit,0或者1)来标识该行是否包含该位图的索引列的取值,若是为1,表示对应的rowid所在的记录包含该位图索引列值),最后经过位图索引中的映射函数完成位到行的ROWID的转换 建立例子 create bitmap index index_sno on student(sno); 适合场景:对于基数小的列适合简历位图索引(例如性别等)

  3. 单列索引和复合索引(基于多个列建立) 注意:即若是索引创建在多个列上,只有它的第一个列被where子句引用时,优化器才会使用该索引,即至少要包含组合索引的第一列

  4. 函数索引 说明: 当常常要访问一些函数或者表达式时,能够将其存储在索引中,这样下次访问时,该值已经计算出来了,能够加快查询速度。 函数索引既可使用B数索引,也可使用位图索引;当函数结果不肯定时采用B树索引,结果是固定的某几个值时使用位图索引。 函数索引中能够水泥用len、trim、substr、upper(每行返回独立结果),不能使用如sum、max、min、avg等。

原则

  1. 若是有两个或者以上的索引,其中有一个惟一性索引,而其余是非惟一,这种状况下oracle将使用惟一性索引而彻底忽略非惟一性索引
  2. 至少要包含组合索引的第一列(即若是索引创建在多个列上,只有它的第一个列被where子句引用时,优化器才会使用该索引)
  3. 小表不要简历索引,值不够分散适合使用位图索引
  4. 对于基数大的列适合创建B树索引,对于基数小的列适合简历位图索引
  5. 列中有不少空值,但常常查询该列上非空记录时应该创建索引
  6. 常常进行链接查询的列应该建立索引
  7. 使用create index时要将最常查询的列放在最前面
  8. LONG(可变长字符串数据,最长2G)和LONG RAW(可变长二进制数据,最长2G)列不能建立索引 9.限制表中索引的数量(建立索引耗费时间,而且随数据量的增大而增大;索引会占用物理空间;当对表中的数据进行增长、删除和修改的时候,索引也要动态的维护,下降了数据的维护速度)

设立封锁机制主要是为了对并发操做进行控制,对干扰进行封锁,保证数据的一致性和准确性。Oracle数据库封锁方式有三种:共享锁,独占锁,共享更新锁 内部级封锁 内部级封锁是用于保护ORACLE内部结构,由系统内部实现,用户不能访问,所以咱们没必要对此作过多的了解。 DDL级封锁(字典/语法分析封锁) DDL级封锁也是由ORACLE RDBMS来控制,它用于保护数据字典和数据定义改变时的一致性和完整性。它是系统在对SQL定义语句做语法分析时自动地加锁,无需用户干予。字典/语法分析封锁共分三类: (1)、字典操做锁:用于对字典操做时,锁住数据字典,此封锁是独占的,从而保护任何一个时刻仅能对一个字典操做。 (2)、字典定义锁:用于防止在进行字典操做时又进行语法分析,这样能够避免在查询字典的同时改动某个表的结构。 (3)、表定义锁:用于 一个SQL语句正当访问某个表时,防止字典中与该表有关的项目被修改。 DML级封锁 DML级封锁用于控制并发事务中的数据操纵,保证数据的一致性和完整性,其封锁对象能够是表或行。 对用户的数据操纵,Oracle能够自动为操纵的数据进行封锁,但若是有操纵受权,则为知足并发操纵的须要另外实施封锁。DML封锁可由一个用户进程以显式的方式加锁,也可经过某些SQL语句隐含方式实现。 DML锁有以下三种封锁方式: (1)、共享封锁方式(SHARE) (2)、独占封锁方式(EXCLUSIVE) (3)、共享更新封锁(SHARE UPDATE)

  1. 共享方式的表封锁 共享方式的表封锁是对表中的全部数据进行封锁防止其它用户对已封锁的表进行更更新。共享该表的全部用户只能查询表中的数据,但不能更新。共享方式的表封锁只能由用户用SQL语句来设置: LOCK TABLE <表名>[,<表名>]... IN SHARE MODE [NOWAIT] 执行该语句,对一个或多个表施加共享方式的表封锁。当指定了选择项NOWAIT,若该封锁暂时不能施加成功,则返回并由用户决定是进行等待,仍是先去执行别的语句。 持有共享锁的事务,在出现以下之一的条件时,便释放其共享锁: A、执行COMMIT或ROLLBACK语句。 B、退出数据库(LOG OFF)。 C、程序中止运行。 共享方式表封锁经常使用于一致性查询过程,即在查询数据期间表中的数据不发生改变。
  2. 独占方式表封锁 独占方式表封锁是用于封锁表中的全部数据,拥有该独占方式表封锁的用户,便可以查询该表,又能够更新该表,其它的用户不能再对该表施加任何封锁(包括共享、独占或共享更新封锁),但能够查询该表。 独占方式的表封锁可经过以下的SQL语句来显示地得到: LOCK TABLE <表名>[,<表名>].... IN EXCLUSIVE MODE [NOWAIT] 独占方式的表封锁也能够在用户执行DML语句INSERT、UPDATE、DELETE时隐含得到。拥有独占方式表封锁的事务。 独占方式封锁一般用于更新数据,当某个更新事务涉及多个表时,可减小发生死锁。
  3. 共享更新封锁方式 共享更新封锁是对一个表的一行或多行进行封锁,于是也称做行级封锁。表级封锁虽然保证了数据的一致性,但却减弱了操做数据的并行性。行级封锁确保在用户取得被更新的行到该行进行更新这段时间内不被其它用户所修改。于是行级锁便可保证数据的一致性又能提升数据操做的迸发性。 可经过以下的两种方式来得到行级封锁: (1)、执行以下的SQL封锁语句,以显示的方式得到: LOCK TABLE <表名>[,<表名>].... IN SHARE UPDATE MODE [NOWAIT] (2)、用以下的SELECT ...FOR UPDATE语句得到: SELECT <列名>[,<列名>]... FROM <表名> WHERE <条件> FOR UPDATE OF <列名>[,<列名>].....[NOWAIT] 一旦用户对某个行施加了行级封锁,则该用户能够查询也能够更新被封锁的数据行,其它用户只能查询但不能更新被封锁的数据行。真正对表进行更新时,是以独占方式封锁表,一直到提交或复原该事务为止。行锁永远是独占方式锁。

事务隔离

事务隔离级别:一个事务对数据库的修改与并行的另外一个事务的隔离程度。两个并发事务同时访问数据库表相同的行时,可能存在如下三个问题:

一、幻想读:事务T1读取一条指定where条件的语句,返回结果集。此时事务T2插入一行新记录,刚好知足T1的where条件。而后T1使用相同的条件再次查询,结果集中能够看到T2插入的记录,这条新纪录就是幻想。 二、不可重复读取:事务T1读取一行记录,紧接着事务T2修改了T1刚刚读取的记录,而后T1再次查询,发现与第一次读取的记录不一样,这称为不可重复读。 三、脏读:事务T1更新了一行记录,还未提交所作的修改,这个T2读取了更新后的数据,而后T1执行回滚操做,取消刚才的修改,因此T2所读取的行就无效,也就是脏数据。

为了处理这些问题,SQL标准定义了如下几种事务隔离级别

READ UNCOMMITTED 幻想读、不可重复读和脏读都容许。 READ COMMITTED 容许幻想读、不可重复读,不容许脏读 REPEATABLE READ 容许幻想读,不容许不可重复读和脏读 SERIALIZABLE 幻想读、不可重复读和脏读都不容许

Oracle数据库支持READ COMMITTED 和 SERIALIZABLE这两种事务隔离级别。

  • READ COMMITTED 这是ORACLE缺省的事务隔离级别。 事务中的每一条语句都听从语句级的读一致性。 保证不会脏读;但可能出现非重复读和幻像。
  • SERIALIZABLE 简单地说,serializable就是使事务看起来象是一个接着一个地顺序地执行。仅仅能看见在本事务开始前由其它事务提交的更改和在本事务中所作的更改(也就是说其它事务在本事务开始后所作的修改,即便提交了,本事务也看不到)保证不会出现非重复读和幻像。 Serializable隔离级别提供了read-only事务所提供的读一致性(事务级的读一致性),同时又容许DML操做。
  • Read Only 听从事务级的读一致性,仅仅能看见在本事务开始前由其它事务提交的更改。不容许在本事务中进行DML操做。 read only是serializable的子集。它们都避免了非重复读和幻像。Read only和Serializable相似,惟一不一样的是它不容许在本事务中进行DML操做。

UNDO/REDO

Undo日志记录某数据被修改前的值,能够用来在事务失败时进行rollback;Redo日志记录某数据块被修改后的值,能够用来恢复未写入data file的已成功事务更新的数据。

例如某一事务的事务序号为T1,其对数据X进行修改,设X的原值是5,修改后的值为15,那么Undo日志为<T1, X, 5>,Redo日志为<T1, X, 15>。

  1. UNDO
  1. UNDO表空间用于存放UNDO数据。当执行DML操做时,Oracle会将这些操做的旧数据写入UNDO段。管理UNDO数据不只可使用回滚段,还可使用UNDO表空间
  2. UNDO数据的做用:当用户执行DML操做修改数据时,UNDO数据被存放在UNDO段,而新数据则被存放到数据段中,若是事务操做存在问题,就须要回退事务,以取消事物变化。 例如:执行完UPDATE emp SET sal=1000 WHERE empno=7788后,发现应该修改雇员7963的工资,而不是7788.此时应该执行ROLLBACK语句。
  3. 读一致性 用户检索数据时,ORACLE老是使用户只能看到被提交过的数据,这是由Oracle自动提供的。当用户修改数据,可是没有提交时,另一个用户使用select语句查找该值时,该值就是从undo表空间中取得的。
  4. 事务恢复 事务恢复是例程恢复的一部分,它是由Oracle Server自动完成的。若是在数据库运行过程当中出线例程失败,那么当启动Oracle Server时,后台进程SMON会自动执行例程恢复。执行例程恢复时,Oracle会重作全部未应用的记录。而后打开数据库,回退未提交事务。 UNDO数据是数据修改前的备份,主要是保证用户的读一致性和事务回滚 在事务修改数据时产生,至少保存到事务结束
  1. REDO REDO记录transaction logs,分为online和archived。以恢复为目的。 好比,机器停电,那么在重起以后须要online redo logs去恢复系统到失败点。 好比,磁盘坏了,须要用archived redo logs和online redo logs区恢复数据。 好比,truncate一个表或其余的操做,想恢复到以前的状态,一样也须要。 redo日志应首先持久化在磁盘上,而后事务的操做结果才写入db buffer。

若是此时恰好系统故障,好比断电,在系统重启后,会读取之前的磁盘数据,而后查看redo日志,将那些已经写入redo日志,但没有更新磁盘的内容【重作】,这样就恢复到了系统故障前的那个点上。 因此,redo日志是很关键的东西。若是其丢失或者损坏了,则你极可能丢失了部分数据(不是必定)。

总结: 操做顺序redo--> undo-->datafile 当insert一条记录时, 表跟undo的信息都会放进 redo 中, 在commit 或以前, redo 的信息会放进硬盘上. 故障时, redo 即可恢复那些已经commit 了的数据. redo->每次操做都先记录到redo日志中,当出现实例故障(像断电),致使数据未能更新到数据文件,则数据库重启时须redo,从新把数据更新到数据文件

1.undo记录数据修改以前的操做,redo记录磁盘数据将要进行的操做. 2.undo用于数据的回滚操做,和实现一致性读,redo用于前滚数据库操做 3.undo存储在回滚段里,redo存储在重作日志文件里 4.undo用于在多用户并发的系统里保证一致性读,redo用于防止数据丢失

Oracle多版本

Oracle还实现了一种多版本控制(multi-versioning)体系结构,这种体系结构提供了一种受控但高度并发的数据访问。多版本控制是指oracle能同时物化多个版本的数据,这也是oracle提供数据读一致视图(即相对于某个时间点有一致的结果)的机制。"读一致性"反映了一个事实:Oracle中的查询会从某个一致的时间点开始返回,查询使用的每一个块都从同一个时间点开始,即便它在你执行查询时被修改或锁定。当你修改数据的时候,Oracle将会在两个不一样的位置建立记录,一个是重作日志,另外一个是回滚段。某一行的数据被修改,该行会增长一个行级锁,当读取这行数据时发现有行级锁则读取回滚段,从而保证读一致。多版本控制有一个至关使人惊喜的连带效果,即数据的读取器绝对不会被数据的写入器所阻塞。它不会与其余会话发生死锁,并且不可能获得数据库中根本不存在的答案。

表分区

当表中的数据量不断增大,查询数据的速度就会变慢,应用程序的性能就会降低,这时就应该考虑对表进行分区。表进行分区后,逻辑上表仍然是一张完整的表,只是将表中的数据在物理上存放到多个表空间(物理文件上)。分区可使某些查询以及维护操做的性能大大提升。 何时使用分区表:

表的大小超过2GB。 表中包含历史数据,新的数据被增长都新的分区中。

表分区有如下优势:

  1. 改善查询性能:对分区对象的查询能够仅搜索本身关心的分区,提升检索速度。
  2. 加强可用性:若是表的某个分区出现故障,表在其余分区的数据仍然可用;
  3. 维护方便:若是表的某个分区出现故障,须要修复数据,只修复该分区便可;
  4. 均衡I/O:能够把不一样的分区映射到磁盘以平衡I/O,改善整个系统性能。 范围分区表、列表分区表、哈希分区表、组合分区表。 索引 对于分区表的不分区索引 对于分区表的不分区索引

enter description here 对于分区表的分区索引

enter description here LOCAL索引结构

轻量级J2EE框架

Spring

spring原理

IoC 容器:最主要是完成了完成对象的建立和对象之间依赖关系的管理注入。Spring就是在运行时,根据xml 配置文件,利用java反射来动态的建立对象。让对象与对象(模块与模块)之间的关系没有经过代码硬关联,都是经过配置类说明管理的。Spring是一个容器,凡是在容器里的对象才会有Spring所提供的这些服务和功能。

当Spring IoC容器完成了Bean定义资源的定位、载入和解析注册之后,IoC容器中已经管理类Bean定义的相关数据,可是此时IoC容器尚未对所管理的Bean进行依赖注入,依赖注入在如下两种状况发生: (1)用户第一次经过getBean方法向IoC容索要Bean时,IoC容器触发依赖注入。 (2)当用户在Bean定义资源中为<Bean>元素配置了lazy-init属性,即让容器在解析注册Bean定义时进行预实例化,触发依赖注入。

AOP:就是面向切面编程,经过动态代理的方式能够为某一类对象 进行监督和控制(也就是 在调用这类对象的具体方法的先后去调用你指定的 模块)从而达到对一个模块扩充的功能。 动态代理模式图解 enter description here

代理模式的代理角色最起码要考虑三个阶段:

  1. 切入点(Point Cut)对哪些方法做代理实现
  2. 拦截行为(Advice)对应的的类方法的执行哪些时期作加强处理(方法调用前、调用异常、方法返回)
  3. 具体加强处理的内容

代理实现的方式 默认状况下,接口使用JDK动态代理,对象使用CGLIB代理。如何强制使用CGLIB实现AOP?

  • 添加CGLIB库,SPRING_HOME/cglib/*.jar
  • 在spring配置文件中加入<aop:aspectj-autoproxy proxy-target-class="true"/>

spring的三种注入方式是 setter、interface、constructor

Spring事务管理

事务有四个特性:ACID

原子性(Atomicity):事务是一个原子操做,由一系列动做组成。事务的原子性确保动做要么所有完成,要么彻底不起做用。 一致性(Consistency):一旦事务完成(无论成功仍是失败),系统必须确保它所建模的业务处于一致的状态,而不会是部分完成部分失败。在现实中的数据不该该被破坏。 隔离性(Isolation):可能有许多事务会同时处理相同的数据,所以每一个事务都应该与其余事务隔离开来,防止数据损坏。 持久性(Durability):一旦事务完成,不管发生什么系统错误,它的结果都不该该受到影响,这样就能从任何系统崩溃中恢复过来。一般状况下,事务的结果被写到持久化存储器中。

Spring并不直接管理事务,而是提供了多种事务管理器,他们将事务管理的职责委托给Hibernate或者JTA等持久化机制所提供的相关平台框架的事务来实现。 enter description here enter description here

事务的传播行为 事务的第一个方面是传播行为(propagation behavior)。当事务方法被另外一个事务方法调用时,必须指定事务应该如何传播。 |传播行为 |含义| |:------|:-------| |PROPAGATION_REQUIRED| 表示当前方法必须运行在事务中。若是当前事务存在,方法将会在该事务中运行。不然,会启动一个新的事务| |PROPAGATION_SUPPORTS| 表示当前方法不须要事务上下文,可是若是存在当前事务的话,那么该方法会在这个事务中运行| |PROPAGATION_MANDATORY| 表示该方法必须在事务中运行,若是当前事务不存在,则会抛出一个异常| |PROPAGATION_REQUIRED_NEW| 表示当前方法必须运行在它本身的事务中。一个新的事务将被启动。若是存在当前事务,在该方法执行期间,当前事务会被挂起。若是使用JTATransactionManager的话,则须要访问TransactionManager| |PROPAGATION_NOT_SUPPORTED |表示该方法不该该运行在事务中。若是存在当前事务,在该方法运行期间,当前事务将被挂起。若是使用JTATransactionManager的话,则须要访问TransactionManager| |PROPAGATION_NEVER| 表示当前方法不该该运行在事务上下文中。若是当前正有一个事务在运行,则会抛出异常| |PROPAGATION_NESTED| 表示若是当前已经存在一个事务,那么该方法将会在嵌套事务中运行。嵌套的事务能够独立于当前事务进行单独地提交或回滚。若是当前事务不存在,那么其行为与PROPAGATION_REQUIRED同样。注意各厂商对这种传播行为的支持是有所差别的。能够参考资源管理器的文档来确认它们是否支持嵌套事务|

Spring MVC

Spring web MVC框架提供了MVC(模型 - 视图 - 控制器)架构和用于开发灵活和松散耦合的Web应用程序的组件。 MVC模式致使应用程序的不一样方面(输入逻辑,业务逻辑和UI逻辑)分离,同时提供这些元素之间的松散耦合。

  • 模型(Model)封装了应用程序数据,一般它们将由POJO类组成。
  • 视图(View)负责渲染模型数据,通常来讲它生成客户端浏览器能够解释HTML输出。
  • 控制器(Controller)负责处理用户请求并构建适当的模型,并将其传递给视图进行渲染。

enter description here enter description here Spring MVC框架是一个基于请求驱动的Web框架,而且使用了前端控制器模式来进行设计,再根据请求映射规则分发给相应的页面控制器(动做/处理器)进行处理。

(1) Http请求:客户端请求提交到DispatcherServlet。 
(2) 寻找处理器:由DispatcherServlet控制器查询一个或多个HandlerMapping,找处处理请求的Controller。 
(3) 调用处理器:DispatcherServlet将请求提交到Controller。 
(4)(5)调用业务处理和返回结果:Controller调用业务逻辑处理后,返回ModelAndView。 
(6)(7)处理视图映射并返回模型: DispatcherServlet查询一个或多个ViewResoler视图解析器,找到ModelAndView指定的视图。 
(8) Http响应:视图负责将结果显示到客户端。
  1. DispatcherServlet接口: Spring提供的前端控制器,全部的请求都有通过它来统一分发。在DispatcherServlet将请求分发给Spring Controller以前,须要借助于Spring提供的HandlerMapping定位到具体的Controller。
  2. HandlerMapping接口: 可以完成客户请求到Controller映射。
  3. Controller接口: 须要为并发用户处理上述请求,所以实现Controller接口时,必须保证线程安全而且可重用。 Controller将处理用户请求,这和Struts Action扮演的角色是一致的。一旦Controller处理完用户请求,则返回ModelAndView对象给DispatcherServlet前端控制器,ModelAndView中包含了模型(Model)和视图(View)。 从宏观角度考虑,DispatcherServlet是整个Web应用的控制器;从微观考虑,Controller是单个Http请求处理过程当中的控制器,而ModelAndView是Http请求过程当中返回的模型(Model)和视图(View)。
  4. ViewResolver接口: Spring提供的视图解析器(ViewResolver)在Web应用中查找View对象,从而将相应结果渲染给客户。

MyBatis

MyBatis是目前很是流行的ORM框架,它的功能很强大,然而其实现却比较简单、优雅

框架设计

enter description here enter description here ####接口层 和数据库交互有两种方式: a.使用传统的MyBatis提供的API;

这是传统的传递Statement Id 和查询参数给 SqlSession 对象,使用 SqlSession对象完成和数据库的交互;MyBatis 提供了很是方便和简单的API,供用户实现对数据库的增删改查数据操做,以及对数据库链接信息和MyBatis 自身配置信息的维护操做。 enter description here enter description here 首先建立一个和数据库打交道的SqlSession对象,而后根据Statement Id 和参数来操做数据库,这种方式当然很简单和实用,可是它不符合面向对象语言的概念和面向接口编程的编程习惯。

b. 使用Mapper接口

MyBatis 将配置文件中的每个<mapper> 节点抽象为一个 Mapper 接口,而这个接口中声明的方法和跟<mapper> 节点中的<select|update|delete|insert> 节点项对应,即<select|update|delete|insert> 节点的id值为Mapper 接口中的方法名称,parameterType 值表示Mapper 对应方法的入参类型,而resultMap 值则对应了Mapper 接口表示的返回值类型或者返回结果集的元素类型。 enter description here enter description here 根据MyBatis 的配置规范配置好后,经过SqlSession.getMapper(XXXMapper.class) 方法,MyBatis 会根据相应的接口声明的方法信息,经过动态代理机制生成一个Mapper 实例,咱们使用Mapper 接口的某一个方法时,MyBatis 会根据这个方法的方法名和参数类型,肯定Statement Id,底层仍是经过SqlSession.select("statementId",parameterObject);或者SqlSession.update("statementId",parameterObject); 等等来实现对数据库的操做,

数据处理层

数据处理层能够说是MyBatis 的核心,从大的方面上讲,它要完成三个功能:

  1. 参数映射

参数映射指的是对于Java 数据类型和jdbc数据类型之间的转换:这里有包括两个过程:查询阶段,咱们要将java类型的数据,转换成jdbc类型的数据,经过 preparedStatement.setXXX() 来设值;另外一个就是对resultset查询结果集的jdbcType 数据转换成java 数据类型。

  1. 动态SQL语句生成

动态语句生成能够说是MyBatis框架很是优雅的一个设计,MyBatis 经过传入的参数值,使用 Ognl 来动态地构造SQL语句,使得MyBatis 有很强的灵活性和扩展性。

  1. 封装查询结果集成List<E>

动态SQL语句生成以后,MyBatis 将执行SQL语句,并将可能返回的结果集转换成List<E> 列表。MyBatis 在对结果集的处理中,支持结果集关系一对多和多对一的转换,而且有两种支持方式,一种为嵌套查询语句的查询,还有一种是嵌套结果集的查询。

框架支撑层

  1. 事务管理机制 MyBatis的事务管理分为两种形式: 1、使用JDBC的事务管理机制:即利用java.sql.Connection对象完成对事务的提交(commit())、回滚(rollback())、关闭(close())等 2、使用MANAGED的事务管理机制:这种机制MyBatis自身不会去实现事务管理,而是让程序的容器如(JBOSS,Weblogic)来实现对事务的管理

  2. 链接池管理机制 enter description here 今后结果能够清楚地看出,建立一个Connection对象,用了250 毫秒;而执行SQL的时间用了170毫秒。建立一个Connection对象用了250毫秒!这个时间对计算机来讲能够说是一个很是奢侈的! MyBatis将链接池中的PooledConnection分为两种状态: 空闲状态(idle)和活动状态(active),这两种状态的PooledConnection对象分别被存储到PoolState容器内的idleConnections和activeConnections两个List集合中:

  3. 缓存机制 一级缓存的工做机制是会话级别的,一个SqlSession对象会使用一个Executor对象来完成会话操做,Executor对象会维护一个Cache缓存,以提升查询性能。 二级缓存的工做机制的关键就是对这个Executor对象作文章。若是用户配置了"cacheEnabled=true",那么MyBatis在为SqlSession对象建立Executor对象时,会对Executor对象加上一个装饰者:CachingExecutor,这时SqlSession使用CachingExecutor对象来完成操做请求。CachingExecutor对于查询请求,会先判断该查询请求在Application级别的二级缓存中是否有缓存结果,若是有查询结果,则直接返回缓存结果;若是缓存中没有,再交给真正的Executor对象来完成查询操做,以后CachingExecutor会将真正Executor返回的查询结果放置到缓存中,而后在返回给用户。

  4. SQL语句的配置方式 传统的MyBatis 配置SQL 语句方式就是使用XML文件进行配置的,可是这种方式不能很好地支持面向接口编程的理念,为了支持面向接口的编程,MyBatis 引入了Mapper接口的概念,面向接口的引入,对使用注解来配置SQL 语句成为可能,用户只须要在接口上添加必要的注解便可,不用再去配置XML文件了,可是,目前的MyBatis 只是对注解配置SQL 语句提供了有限的支持,某些高级功能仍是要依赖XML配置文件配置SQL 语句。

相关文章
相关标签/搜索