第二周

Tomcat运行原理

http://blog.csdn.net/pzxwhc/article/details/47129675 Tomcat执行流程

http://www.importnew.com/17124.html Tomcat server.xml配置示例

1、JavaWeb应用的概念

在Sun的Java Servlet规范中,对Java Web应用作了这样定义:“Java Web应用由一组Servlet、HTML页、类、以及其它可以被绑定的资源构成。它可以在各种供应商提供的实现Servlet规范的 Servlet容器 中运行。”

 

Servlet容器为JavaWeb应用提供运行时环境,它负责管理Servlet和JSP的生命周期,以及管理它们的共享数据。Servlet容器也称为JavaWeb应用容器,或者Servlet/JSP容器。

目前最流行的Servlet容器软件括:Tomcat,Resin,J2EE服务器(如Weblogic)中也提供了内置的Servlet容器。

2、Tomcat简介

Tomcat 是一个免费的开放源代码的 Servlet 容器,它是 Apache 软件基金会的一个顶级项目,由 Apache,Sun和其他一些公司及个人共同开发而成。由于有了 Sun 的参与和支持,最新的 Servlet 和 JSP 规范总是能在 Tomcat 中的到体现。

 

3、Tomcat Server组件

Tomcat是一个基于组件的服务器,他的构建组件都是可以配置的,其中最外层的组件是Catalina Servlet容器,其他组件一定要按照一定的格式要求配置在这个顶层的容器中。

<Server> 顶层类元素,可包含多个service

<Service> 顶层类元素,可包含一个Engine和多个Connector

<Connector/> 链接类容器,代表通信接口

<Engine> 容器元素,为Service处理客户请求,含多个Host

<Host> 容器元素,为Host处理客户请求,含多个Context

<Context/> 容器元素,为Web应用处理客户请求

</Host>

</Engine>

</Service>

</Server>

 

1) Server

A Server element represents the entire Catalina servlet Container. (Singleton)单实例的。

2) Service

Service是一个集合。它由一个或者多个Connector组成,以及一个Engine,负责处理所有Connector所获得的客户请求。

3) Connector  表示客户端和service之间的连接

一个Connector将在某个指定端口上侦听客户请求,并将获得的请求交给Engine来处理,从Engine处获得回应并返回客户。

 

TOMCAT有两个典型的Connector,一个直接侦听来自browser的http请求,一个侦听来自其它WebServer的请求。

Coyote Http/1.1 Connector 在端口8080处侦听来自客户browser的http请求。

Coyote JK2 Connector 在端口8009处侦听来自其它WebServer(Apache)的servlet/jsp代理请求。

4) Engine  表示指定service中的请求处理机,接收和处理来自Connector的请求

Engine下可以配置多个虚拟主机Virtual Host,每个虚拟主机都有一个域名。当Engine获得一个请求时,它把该请求匹配到某个Host上,然后把该请求交给该Host来处理。Engine有一个默认虚拟主机,当请求无法匹配到任何一个Host上的时候,将交给该默认Host来处理。

5) Host   表示一个虚拟主机

代表一个Virtual Host,虚拟主机,每个虚拟主机和某个网络域名Domain Name相匹配。每个虚拟主机下都可以部署(deploy)一个或者多个Web App,每个Web App对应于一个Context,有一个Context path

当Host获得一个请求时,将把该请求匹配到某个Context上,然后把该请求交给该Context来处理。匹配的方法是“最长匹配”,所以一个path==""的Context将成为该Host的默认Context。所有无法和其它Context的路径名匹配的请求都将最终和该默认Context匹配。

6) Context   表示一个web应用程序

一个Context对应于一个Web Application,一个Web Application由一个或者多个Servlet组成。

 

4、Web.xml文件

一个Context对应于一个Web App,每个Web App是由一个或者多个servlet组成的。

当一个Web App被初始化的时候,它将用自己的ClassLoader对象载入“部署配置文件web.xml”中定义的每个servlet类。

它首先载入在$CATALINA_HOME/conf/web.xml中部署的servlet类

然后载入在自己的Web App根目录下的WEB-INF/web.xml中部署的servlet类

web.xml文件有两部分:servlet类定义和servlet映射定义

每个被载入的servlet类都有一个名字,且被填入该Context的映射表(mapping table)中,和某种URL PATTERN对应

当该Context获得请求时,将查询mapping table,找到被请求的servlet,并执行以获得请求回应

分析一下所有的Context共享的web.xml文件,在其中定义的servlet被所有的Web App载入。

5、处理HTTP请求过程

假设来自客户的请求为:

protocol :// hostname[:port] / path / [;parameters][?query]#fragment

http://localhost:8080/wsota/wsota_index.jsp

1) 请求被发送到本机端口8080,被在那里侦听的Coyote HTTP/1.1 Connector获得

2) Connector把该请求交给它所在的Service的Engine来处理,并等待来自Engine的回应

3) Engine获得请求localhost/wsota/wsota_index.jsp,匹配它所拥有的所有虚拟主机Host

4) Engine匹配到名为localhost的Host(即使匹配不到也把请求交给该Host处理,因为该Host被定义为该Engine的默认主机)

5) localhost Host获得请求/wsota/wsota_index.jsp,匹配它所拥有的所有Context

6) Host匹配到路径为/wsota的Context(如果匹配不到就把该请求交给路径名为""的Context去处理)

7) path="/wsota"的Context获得请求/wsota_index.jsp,在它的mapping table中寻找对应的servlet

8) Context匹配到URL PATTERN为*.jsp的servlet,对应于JspServlet类

9) 构造HttpServletRequest对象和HttpServletResponse对象,作为参数调用JspServlet的doGet或doPost方法

10)Context把执行完了之后的HttpServletResponse对象返回给Host

11)Host把HttpServletResponse对象返回给Engine

12)Engine把HttpServletResponse对象返回给Connector

13)Connector把HttpServletResponse对象返回给客户browser

 

6、tomcat部署一个java应用

建立一个符合web应用目录的程序结构MyWebContent。需要将类生成文件配置到WEB-INF的classes目录下。

 

将MyWebContent复制到E:\apache-tomcat-7.0.34-noinstall\webapps目录下,打开

http://localhost:8080/manager/html

 

打开

 

可以看到

 

WEB-INF目录下的classes和lib目录都可以存放Java的类文件,在Servlet容器运行时,Web应用程序的类加载器将首先加载classes目录下的,其次才是lib目录下的类。如果这两个目录下存在同名的类,起作用的将是classes目录下的类。

JdbcTemplate使用笔记

1、JdbcTemplate简介

  1. 为了使 JDBC 更加易于使用,Spring 在 JDBC API 上定义了一个抽象层,以此建立一个 JDBC 存取框架。
  2. 作为 Spring JDBC 框架的核心,JDBC 模板的设计目的是为不同类型的 JDBC 操作提供模板方法。 每个模板方法都能控制整个过程,并允许覆盖过程中的特定任务。通过这种方式,可以在尽可能保留灵活性的情况下,将数据库存取的工作量降到最低。

 

2、用sql更新数据库

 

例如:

 

3、批量更新数据库

 

例如:

 

4、查询单行记录

 

例如:

 

5、查询多行记录

 

例如:

 

6、单值查询

 

例如:

 

7、调用存储函数

 

第二种

 

8、调用存储过程

 

 

 

 

9、返回结果集

返回结果集,通过把游标作为一个out参数来返回的。

 

 

Java调用

 

 

 

10、blob和clob处理

BLOB和CLOB都是大字段类型,BLOB是按二进制来存储的,而CLOB是可以直接存储文字的。其实两个是可以互换的的,或者可以直接用LOB字段代替这两个。但是为了更好的管理ORACLE数据库,通常像图片、文件、音乐等信息就用BLOB字段来存储,先将文件转为二进制再存储进去。而像文章或者是较长的文字,就用CLOB存储,这样对以后的查询更新存储等操作都提供很大的方便。

 

 

插入成功!

 

读取并且复制

 

 

 

Java规范学习笔记

1、Object 的 equals 方法容易抛空指针异常,应使用常量或确定有值的对象来调用 equals。

       正例: "test".equals(object);

2、关于基本数据类型与包装数据类型的使用标准如下:

所有的 POJO 类属性必须使用包装数据类型。

RPC 方法的返回值和参数必须使用包装数据类型。

所有的局部变量推荐使用基本数据类型。

3、在集合迭代过程中,不能直接调用集合的add,remove方法,会报java.util.ConcurrentModificationException异常。应该使用迭代器的移除方法。

       ArrayList<String> list = new ArrayList<String>(Arrays.asList("a","b","c","d"));

//      Iterator<String> iterator = list.iterator();

//      while(iterator.hasNext()){

//          if(iterator.next().equals("a")){

//              iterator.remove();

//          }

//      }

        for(String s : list){

            if(s.equals("a")){

                list.add("bbb");

            }

        }//java.util.ConcurrentModificationException

4、高并发时,同步调用应该去考量锁的性能损耗。能用无锁数据结构,就不要用锁;能锁区块,就不要锁整个方法体;能用对象锁,就不要用类锁。

5、并发修改同一记录时,避免更新丢失,要么在应用层加锁,要么在缓存加锁,要么在数据库层使用乐观锁,使用 version 作为更新依据。

> 说明: 如果每次访问冲突概率小于 20%,推荐使用乐观锁,否则使用悲观锁。乐观锁的重试次数不得小于 3 次。

悲观锁(Pessimistic Lock),顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。

乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库如果提供类似于write_condition机制的其实都是提供的乐观锁。

两种锁各有优缺点,不可认为一种好于另一种,像乐观锁适用于写比较少的情况下,即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。但如果经常产生冲突,上层应用会不断的进行retry,这样反倒是降低了性能,所以这种情况下用悲观锁就比较合适。

6、如果使用要 if-else if-else 方式表达逻辑,【强制】请勿超过 3 层,超过请使用状态设计模式。

http://blog.csdn.net/hguisu/article/details/7557252   状态设计模式

 

 

7、避免用 Apache Beanutils 进行属性的 copy。

> 说明: Apache BeanUtils 性能较差,可以使用其他方案比如 Spring BeanUtils, CglibBeanCopier。

8、后台输送给页面的变量必须加$!{var}——中间的感叹号。

> 说明: 如果 var=null 或者不存在,那么${var}会直接显示在页面上。

 

Maven学习笔记

1、目前所存在的问题

1.一个项目就是一个工程。项目非常庞大,用package不适合划分。最好是一个模块对应一个工程。

    可以利用maven将一个项目拆分成多个工程。

2.项目里面的jar包都是手动复制和添加。这样,同一个jar包会出现在多个项目中。

3.jar包需要自己下载。Jar包依赖关系。

2、Maven概述

一款服务于java平台的自动化构建工具。Make、Ant、Maven、Gradle

运行时环境:就是一组jar包的引用。并没有正真放入工作目录。

   

编译------------部署------------搭建

 

构建过程的各个环节

    1.清理,将以前的字节码class文件删除

    2.编译,将java源程序编译成class文件

    3.测试,自动测试,调用junit程序

    4.报告,测试结果

    5.打包,web工程打war包,java工程打jar包

    6.安装,将打包文件复制到仓库的指定位置

    7.部署,将web动态工程生成的war包复制到severvlet容器的指定目录下。

 

原工程与编译结果对比图

 

3、Maven核心概念

1.约定的目录结构

2.POM,项目对象模型

3.坐标,利用三个向量,在仓库中定义一个Maven工程

    GroupId: 公司或组织域名倒序+项目名

    ArtifactId:模块名,比如Hello

    Version:版本,比如1.1.0,release可分离的稳定版,snapshot快照版迭代快

4.依赖,

    Maven解析依赖信息时,会到本地仓库中查找被依赖的jar包。

    对于自己开发的maven工程,使用install命令来安装,就可以进入仓库。

    依赖范围:<scope>compile</scope>

           Compile  对主程序是否有效,对测试程序是否有效,是否参与打包。

           Test  

           Provided  

 

   

5.仓库,本地仓库和远程仓库。

6.声明周期/插件/目标

7.继承

8.聚合

4、Maven工程目录结构

    ①目录结构

           Hello  工程名

           |---src 源码

           |---|---main 主程序

           |---|---|---java  源码

           |---|---|---resources  框架和其他配置文件

           |---|---test  存放测试程序

           |---|---|---java

           |---|---|---resources

           |---pom.xml Maven核心配置文件

    ②POM文件内容

    Project Object Model项目对象模型

    Document Object Model 文档对象模型DOM

 

import static junit.framework.Assert.*; 静态导入。类里所有的静态资源可以直接用了。

assertEquals(“….”,results);断言结果与给定字符串一致。

5、Maven常用命令

执行与构建(编译、测试、打包)过程相关的命令,必须进入pom.xml文件所在目录。

1.   mvn  clean: 清理

2.   mvn  compile: 编译

3.   mvn test-compile: 编译测试程序

4.   mvn test: 执行测试程序

5.   mvn package: 打包

6.   mvn install: 将本地jar包安装到本地仓库中

7.   mvn site: 生成站点

先找本地仓库,没有相关jar包,就联网下载。

6、Maven生命周期

各个构建环境执行的顺序,顺序执行。

定义了抽象声明周期,具体由插件完成。

自动化构建的特点,不论要执行生命周期的哪一个阶段,都是从生命周期最初的位置开始执行。

 

可以将目标看做调用功能的命令。

7、jar包依赖

各个构的环境执行的顺序,顺序执行。

排除jar包

 

依赖原则:路径最短优先。路径相同时,先声明优先。

传递依赖,非compile范围内的不能传递依赖。

引用版本号:方便更改。

 

聚合:由于有继承后,需要先安装父工程。聚合的作用就是一键安装各个参与聚合的模块。

比如:在Parent模块中配置如下,

 

8、部署到服务器上

方法1(手动):

可以将web引用,package先打包成war包。将war包复制到Tomcat安装的webapps目录下。

方法2(自动):

    配置build标签后,最好用cmd来运行deploy命令,否则需要手动关闭Tomcat。

 

 

 

9、下载源码和javadoc

方法1:命令

命令使用方法:首先进入到相应的pom.xml目录中,然后执行以下命令:

mvn dependency:sources

mvn dependency:resolve -Dclassifier=javadoc

第一个命令是尝试下载在pom.xml中依赖的文件的源代码。

第二个命令是尝试下载对应的javadocs

但是有可能一些文件没有源代码或者javadocs

方法2:配置文件

打开maven配置文件 setting.xml文件(.../.m2/settings.xml) 增加如下配置:

  1. <profiles>  
  2. <profile>  
  3.     <id>downloadSources</id>  
  4.     <properties>  
  5.         <downloadSources>true</downloadSources>  
  6.         <downloadJavadocs>true</downloadJavadocs>             
  7.     </properties>  
  8. </profile>  
  9. </profiles>  
  10. 10.   

11. <activeProfiles>  

  1. 12.   <activeProfile>downloadSources</activeProfile>  

13. </activeProfiles>  

方法3:配置myeclipse    推荐使用

 

10、jar包查找总站

http://mvnrepository.com/

 

 

Hibernate学习笔记

1、hibernate简介

ORM:Object Relation Mapping  对象/关系映射

ORM 主要解决对象-关系的映射

 

ORM的思想:将关系数据库中表中的记录映射成为对象,以对象的形式展现,程序员可以把对数据库的操作转化为对对象的操作。

ORM 采用元数据来描述对象-关系映射细节,元数据通常采用 XML 格式, 并且存放在专门的对象-关系映射文件中。(描述类、对象、属性和表的行列对应关系)

元数据:描述数据的数据。

对象关系映射文件***.hbm.xml

 

2、hibernate开发步骤

1)hibernate配置文件hibernate.cfg.xml

2)创建对象-关系映射文件*.hbm.xml

编写持久化类: POJO + 映射文件

获取 Configuration 对象

获取 SessionFactory 对象

获取 Session,打开事务

用面向对象的方式操作数据库

关闭事务,关闭 Session

3)Configuration 类负责管理 Hibernate 的配置信息。包括如下内容:

配置1:Hibernate 运行的底层信息:数据库的URL、用户名、密码、JDBC驱动类,数据库Dialect,数据库连接池等(对应 hibernate.cfg.xml 文件)。

配置2:持久化类与数据表的映射关系(*.hbm.xml 文件)

4)SessionFactory针对单个数据库映射关系经过编译后的内存镜像,是线程安全的。 SessionFactory 对象一旦构造完毕,即被赋予特定的配置信息。SessionFactory是生成Session的工厂。构造 SessionFactory 很消耗资源,一般情况下一个应用中只初始化一个 SessionFactory 对象。

5)Session 是应用程序与数据库之间交互操作的一个单线程对象,是 Hibernate 运作的中心,所有持久化对象必须在 session 的管理下才可以进行持久化操作。此对象的生命周期很短。Session 对象有一个一级缓存,显式执行 flush 之前,所有的持久层操作的数据都缓存在 session 对象处。相当于 JDBC 中的 Connection。

       取得持久化对象的方法: get() load()

持久化对象都得保存,更新和删除:save(),update(),saveOrUpdate(),delete()

开启事务: beginTransaction().

管理 Session 的方法:isOpen(),flush(), clear(), evict(), close()等

 

注意红色部分,是以斜杠隔断。

 

3、Session 概述

Session 接口是 Hibernate 向应用程序提供的操纵数据库的最主要的接口,它提供了基本的保存,更新, 删除和加载 Java 对象的方法.

Session 具有一个缓存,位于缓存中的对象称为持久化对象,它和数据库中的相关记录对应。Session 能够在某些时间点,按照缓存中对象的变化来执行相关的 SQL 语句,来同步更新数据库,这一过程被称为刷新缓存(flush)。

站在持久化的角度,Hibernate 把对象分为 4 种状态:临时状态,持久化状态,游离状态,删除状态。 Session 的特定方法能使对象从一个状态转换到另一个状态。

4、Session缓存

在 Session 接口的实现中包含一系列的 Java 集合,这些 Java 集合构成了 Session 缓存。只要 Session 实例没有结束生命周期,且没有清理缓存,则存放在它缓存中的对象也不会结束生命周期。

Session 缓存可减少 Hibernate 应用程序访问数据库的频率。

 

Flush使得数据表中的记录和session缓存中的状态保持一致,可能会发送对应的SQL语句。

在Transaction的commit()方法中先调用flush方法,再commit。

Flush()方法可能会发送sql语句,但是不会提交事务,也就是数据表的记录不会改变。

3. 注意: 在未提交事务或显式的调用 session.flush() 方法之前,也有可能会进行 flush() 操作。

* 1). 执行 HQL 或 QBC 查询,会先进行 flush() 操作,以得到数据表的最新的记录

* 2). 若记录的 ID 是由底层数据库使用自增的方式生成的,则在调用 save() 方法时,就会立即发送 INSERT 语句。

* 因为 save 方法后,必须保证对象的 ID 是存在的!

Refresh会强制发送 SELECT 语句,以使 Session 缓存中对象的状态和数据表中对应的记录保持一致!

5、持久化对象的状态

站在持久化的角度,Hibernate 把对象分为 4 种状态:Transient,Persist,Detached,Removed。Session 的特定方法能使对象从一个状态转换到另一个状态。

临时对象(Transient):

在使用代理主键的情况下,OID 通常为 null

不处于 Session 的缓存中

在数据库中没有对应的记录

持久化对象(也叫”托管”)(Persist):

OID 不为 null

位于 Session 缓存中

对应性:若在数据库中已经有和其对应的记录,持久化对象和数据库中的相关记录对应

同步性:Session 在 flush 缓存时,会根据持久化对象的属性变化,来同步更新数据库

唯一性:在同一个 Session 实例的缓存中,数据库表中的每条记录只对应唯一的持久化对象。如果一个session的数据库记录有两个对象,那么以哪个更新呢?所以是只有一个。

游离对象(也叫”脱管”) (Detached):类似于公司中员工请假了,不受公司管理,但是还属于公司

OID 不为 null

不再处于 Session 缓存中

一般情况需下,游离对象是由持久化对象转变过来的,因此在数据库中可能还存在与它对应的记录

删除对象(Removed)

在数据库中没有和其 OID 对应的记录

不再处于 Session 缓存中

一般情况下,应用程序不该再使用被删除的对象

 

1. save() 方法

        * 1). 使一个临时对象变为持久化对象

        * 2). 为对象分配 ID.

        * 3). 在 flush 缓存时会发送一条 INSERT 语句.

        * 4). 在 save 方法之前的 id 是无效的

        * 5). 持久化对象的 ID 是不能被修改的!

2. persist(): 也会执行 INSERT 操作

        * 和 save() 的区别 :

        * 在调用 persist 方法之前,若对象已经有 id 了,则不会执行 INSERT,而抛出异常

3. get VS load:

        * 1. 执行 get 方法:会立即加载对象

        *    执行 load 方法:若不使用该对象,则不会立即执行查询操作,而返回一个代理对象

        *    get 是 立即检索,load 是延迟检索

        * 2. load 方法可能会抛出 LazyInitializationException 异常:在需要初始化

        * 代理对象之前已经关闭了 Session

        * 3. 若数据表中没有对应的记录,Session 也没有被关闭

        *    get 返回 null

        *    load 若不使用该对象的任何属性,没问题。若需要初始化了,抛出异常

4. update:

        * 1. 若更新一个持久化对象,不需要显示的调用 update 方法。因为在调用 Transaction的 commit() 方法时,会先执行 session 的 flush 方法

        * 2. 更新一个游离对象,需要显式的调用 session 的 update 方法。可以把一个游离对象变为持久化对象

        * 需要注意的:

        * 1. 无论要更新的游离对象和数据表的记录是否一致,都会发送 UPDATE 语句

        *    如何能让 update 方法不再盲目的出发 update 语句呢 ? 在 .hbm.xml 文件的 class 节点设置

        *    select-before-update=true (默认为 false)。但通常不需要设置该属性

        * 2. 若数据表中没有对应的记录,但还调用了 update 方法,会抛出异常

        * 3. 当 update() 方法关联一个游离对象时

        * 如果在 Session 的缓存中已经存在相同 OID 的持久化对象,会抛出异常。因为在 Session 缓存中

        * 不能有两个 OID 相同的对象!

5. saveOrUpdate:同时包含了save和update方法

 

6.delete: 执行删除操作。只要 OID 和数据表中一条记录对应,就会准备执行 delete 操作

        * 若 OID 在数据表中没有对应的记录,则抛出异常

        * 可以通过设置 hibernate 配置文件 hibernate.use_identifier_rollback 为 true

        * 使删除对象后,把其 OID 置为  null

       可以在删除方法调用后,将OID立即置为null

7.evict: 从 session 缓存中把指定的持久化对象移除

6、调用存储过程

Work 接口: 直接通过 JDBC API 来访问数据库的操作。

 

Session 的 doWork(Work) 方法用于执行 Work 对象指定的操作,即调用 Work 对象的 execute() 方法。Session 会把当前使用的数据库连接传递给 execute() 方法

 

7、触发器协同工作

Hibernate 与数据库中的触发器协同工作时,会造成两类问题:

1)触发器使 Session 的缓存中的持久化对象与数据库中对应的数据不一致:触发器运行在数据库中,它执行的操作对 Session 是透明的。

即,session操作导致触发器更改了数据库内容,需要同步,要立即调用flush和refresh方法

2)Session 的 update() 方法盲目地激发触发器:无论游离对象的属性是否发生变化,都会执行 update 语句,而 update 语句会激发数据库中相应的触发器。

因此,需要在映射文件的<class>元素中设置select-before-update属性:当 Session 的 update 或 saveOrUpdate() 方法更新一个游离对象时,会先执行 Select 语句,获得当前游离对象在数据库中的最新数据,只有在不一致的情况下才会执行 update 语句。

8、hbm.xml文件

hibernate-mapping.xml

类层次:class

主键:id

基本类型:property

实体引用类: many-to-one  |  one-to-one

集合:set | list | map | array

one-to-many

many-to-many

子类:subclass | joined-subclass

其它:component | any 等

查询语句:query(用来放置查询语句,便于对数据库查询的统一管理和优化)

每个Hibernate-mapping中可以同时定义多个类。但更推荐为每个类都创建一个单独的映射文件

 

1)class标签中,dynamic-update:若设置为 true,表示当更新一个对象时,会动态生成 update 语句,update 语句中仅包含所有取值需要更新的字段。默认值为 false。

2)类型映射

 

 

9、时间类型的映射

在 Java 中,代表时间和日期的类型包括: java.util.Date 和 java.util.Calendar. 此外,在 JDBC API 中还提供了 3 个扩展了 java.util.Date 类的子类: java.sql.Date,java.sql.Time 和 java.sql.Timestamp,这三个类分别和标准 SQL 类型中的 DATE,TIME 和 TIMESTAMP 类型对应。

所以在持久化类中,应设置为java.util.Date类型,这样就可以接收数据库所有类型。

如何映射:type设置为date、time、timestamp三类Hibernate类型

 

10、blob类型的映射

在 Java 中, java.lang.String 可用于表示长字符串(长度超过 255),字节数组 byte[] 可用于存放图片或文件的二进制数据。此外,在 JDBC API 中还提供了 java.sql.Clob 和 java.sql.Blob 类型,它们分别和标准 SQL 中的 CLOB 和 BLOB 类型对应。CLOB 表示字符串大对象(Character Large Object),BLOB表示二进制对象(Binary Large Object)。

 

 

 

 

 

11、组成关系映射

问题来源:建立域模型和关系数据模型有着不同的出发点:

域模型:由程序代码组成,通过细化持久化类的粒度可提高代码的可重用性,简化编程。

类,越多越细化越好

 

在没有数据冗余的情况下,应该尽可能减少表的数目,简化表之间的参照关系,以便提高数据的访问速度。

数据表,越少越好

 

Hibernate 把持久化类的属性分为两种:

值(value)类型:没有 OID,不能被单独持久化,生命周期依赖于所属的持久化类的对象的生命周期

实体(entity)类型:有 OID,可以被单独持久化,有独立的生命周期

显然无法直接用 property 映射 pay 属性

Hibernate 使用 <component> 元素来映射组成关系,该元素表名 pay 属性是 Worker 类一个组成部分,在 Hibernate 中称之为组件。

 

12、一对多关联关系

在领域模型中,类与类之间最普遍的关系就是关联关系。

在 UML 中,关联是有方向的。以 Customer 和 Order 为例: 一个用户能发出多个订单,而一个订单只能属于一个客户。从 Order 到 Customer 的关联是多对一关联;而从 Customer 到 Order 是一对多关联。

单向关联

n-1:order里面有一个对customer的引用

1-n:customer中有order的集合的引用

双向关联

 

 

1)单向n-1

单向 n-1 关联只需从 n 的一端可以访问 1 的一端。

域模型:从 Order 到 Customer 的多对一单向关联需要在Order 类中定义一个 Customer 属性,而在 Customer 类中无需定义存放 Order 对象的集合属性。

 

关系数据模型:ORDERS 表中的 CUSTOMER_ID 参照 CUSTOMER 表的主键

 

在order.hbm.xml中配置

 

Session.save()保存的时候需要先保存一customer的一端。

查询多的一端order的时候,进行了延迟加载,没有查出一的customer一端。若先关闭了session再使用customer会报懒加载异常LazyInitalizationException。

在不设定级联关系下,删除一的customer一端会报错。

2)双向n-1

双向 1-n 与 双向 n-1 是完全相同的两种情形

双向 1-n 需要在 1 的一端可以访问 n 的一端,反之依然.

域模型:从 Order 到 Customer 的多对一双向关联需要在Order 类中定义一个 Customer 属性,而在 Customer 类中需定义存放 Order 对象的集合属性。

 

关系数据模型:ORDERS 表中的 CUSTOMER_ID 参照 CUSTOMER 表的主键。和上面的数据表设计一样。

 

 

在java,Customer类中这样设置:

 

在Customer.hbm.xml中这样配置:

 

3)1-1

1对1关联关系,利用了多对一关联关系来建立。域模型:一个部门只能有一个领导,一个领导也只能管理一个部门。

 

关系数据库模型,有两种:

一、按照外键映射,利用多对一,但是多的那一端需要加上unique关键字。即在配置many-to-one那一端会有一个外键生成。

 

配置如下:

Department.hbm.xml

 

Manager.hbm.xml,注意需要property-ref属性指定出了所关联实体主键以外的关联字段!!!左外连接

 

二、按照主键映射

 

基于主键的映射策略:指一端的主键生成器使用 foreign 策略,表明根据”对方”的主键来生成自己的主键,自己并不能独立生成主键。 <param> 子元素指定使用当前持久化类的哪个属性作为 “对方”。

Department.hbm.xml中配置。注意是当前持久化类的哪一个属性作为主键配置!!!

 

在Manager.hbm.xml中配置

 

3)单向多对多

域模型:商品,列表。一个商品可以属于多个列表类,一个列表类也可以有多个商品。

 

关系数据模型:

 

 

 

 

 

在Category.hbm.xml中配置

 

在Item.hbm.xml中配置

 

13、继承关系映射

子类和父类公用一张数据表。父类中没有的字段值为空。有一列为TYPE辨别者列,作为类型区分。

对于面向对象的程序设计语言而言,继承和多态是两个最基本的概念。Hibernate 的继承映射可以理解持久化类之间的继承关系。例如:人和学生之间的关系。学生继承了人,可以认为学生是一个特殊的人,如果对人进行查询,学生的实例也将被得到。

1)使用 subclass 进行映射:将域模型中的每一个实体对象映射到一个独立的表中,也就是说不用在关系数据模型中考虑域模型中的继承关系和多态。

只用配置父类Person.hbm.xml文件

 

 

 

 

2)使用 joined-subclass 进行映射: 对于继承关系中的子类使用同一个表,这就需要在数据库表中增加额外的区分子类类型的字段。

 

 

 

3)使用  union-subclass 进行映射:域模型中的每个类映射到一个表,通过关系数据模型中的外键来描述表之间的继承关系。这也就相当于按照域模型的结构来建立数据库中的表,并通过外键来建立表之间的继承关系。

 

 

14、hibernate检索方式

导航对象图检索方式:根据已经加载的对象导航到其他对象。比如,customer得到order

OID 检索方式:按照对象的 OID 来检索对象,get,lod

HQL 检索方式:使用面向对象的 HQL 查询语言

QBC 检索方式:使用 QBC(Query By Criteria) API 来检索对象。这种 API 封装了基于字符串形式的查询语句,提供了更加面向对象的查询接口。

本地 SQL 检索方式:使用本地数据库的 SQL 查询语句。

 

1)HQL

HQL(Hibernate Query Language) 是面向对象的查询语言,它和 SQL 查询语言有些相似。在 Hibernate 提供的各种检索方式中,HQL 是使用最广的一种检索方式。它有如下功能:

在查询语句中设定各种查询条件

支持投影查询,即仅检索出对象的部分属性

支持分页查询

支持连接查询

支持分组查询,允许使用 HAVING 和 GROUP BY 关键字

提供内置聚集函数,如 sum(),min() 和 max()

支持子查询

支持动态绑定参数

能够调用 用户定义的 SQL 函数或标准的 SQL 函数

 

 

2)QBC 查询就是通过使用 Hibernate 提供的 Query By Criteria API 来查询对象,这种 API 封装了 SQL 语句的动态拼装,对查询提供了更加面向对象的功能接口

3)本地SQL查询来完善HQL不能涵盖所有的查询特性

posted @ 2017-03-21 13:56  水木仕林  阅读(178)  评论(0编辑  收藏  举报