分层体系结构:
逻辑上一般分为三层:表述层(提供与用户交互的界面)、业务逻辑层(实现各种业务的逻辑)、数据库层(负责存放和管理应用的持久性业务数据)。
物理上一般分为两层:物理层(每一层都运行在网络上的单独的机器节点上)和逻辑层(每一层由一个相对独立的软件模块来实现。)
软件层必须符合以下特征:
(1)每个层由一组相关的类或组件构成,完成特定的功能。
(2)层与层之间存在自上而下的依赖关系,即上层组件可以访问下层组件的API(application programming interface 应用程序接口),而下层组件不应该依赖上层组件。
(3)每个层对上层公开API,但具体的实现细节对外透明。
概念模型描述了每个实体的概念和属性,以及实体之间的关系,但并不描述实体的行为。实体和实体之间存在着一对一、一对多和多对多的关系。
关系模型是在概念模型的基础上建立起来的,用于描述这些关系数据库的静态结构,它由以下内容组成:一个或多个表、表的所有索引、视图、触发器和表与表之间的参照完整性。
域模型是面向对象的,也可称为设计模型。由域对象(具有状态和行为的域对象)和域对象之间的关系组成。
域对象(Domain Object)是对真实世界的实体的软件抽象。还可叫做业务对象(Business Object)。分为一下几种:实体域对象(业务领域中的名次,像订单、商品、客户等)、过程域对象(代表业务逻辑或流程,通常依赖于实体域对象)和事件域对象(代表应用中的一些事件,像警告、异常或超时等,这些事件通常由系统中的某种行为触发)。
域对象之间的关系:关联(association)、依赖(dependency)、聚集(aggregation)和一般化(generalization)。
关联指的是类之间的引用关系,可分为一对一、一对多和多对多关联。关联还是有方向的,可以分为单向关联和双向关联。
依赖指的是类之间的访问关系。如果类A访问类B的属性或方法,或类A负责实例化类B,则可以说类A依赖类B。
聚集指的是整体与部分的关系。
一般化指的是类之间的继承关系。
业务数据有两种表现形式:在内存中表现为实体域对象以及实体域对象之间的各种关系。在关系数据库中表现为表,以及表之间的参照关系。
ORM(object-relation mapping,对象-关系映射)模式指的是在单个组件中负责所有实体域对象的持久化,封装数据访问细节。ORM采用映射元数据(mapping meta data)来描述对象-关系映射细节,使ORM中间件能在任何一个Java应用的业务逻辑层和数据库层之间充当桥梁。元数据通常使用XML格式,并且存放在专门的对象-关系映射文件中。只要提供了持久化类与表的映射关系,ORM中间件在运行期间就能参照映射文件的信息,把域对象持久化到数据库中。
主动域对象模式:在它的实现中封装了关系数据模型和数据访问细节。主动域对象模式有以下有点:在实体域对象中封装自身的数据访问细节,过程域对象完全负责业务逻辑,使程序结构更加清晰;如果关系数据模型发生改变,只需修改主动域对象的代码,不需要修改过程域对象的业务方法。但也存在一下缺点:在实体域对象的实现中仍然包含SQL语句;每个实体域对象都负责自身的数据访问实现,会造成一定的代码冗余。
在J2EE框架中,EJB组件分为会话EJB和实体EJB。会话EJB通常实现业务逻辑,而实体EJB表示业务实体。实体EJB又分为两种:由EJB本身管理持久化,即BMP(bean-managed persistence)和由EJB容器管理持久化,即CMP(container-managed persistence)。
JDO(java data object)是SUN公司指定的描述对象持久化语义的标准API。它并不是单纯的对象-关系映射接口,它支持把对象持久化到任意一种存储系统中。
Hibernate的API中的接口可以分为一下几个类:提供访问数据库的操作的接口(Session、Transaction和Query);用于配置Hibernate的接口(Configuration);使应用程序拦截Hibernate内部发生的事件,并做成相关的回应的接口(Interceptor、localEventListener、SaveEventListener等);用于扩展Hibernate的功能接口(UserType、CompositeUserType等)。
所有的Hibernate应用中都会访问Hibernate的5个核心接口:Configuration接口:配置Hibernate,根启动Hibernate,创建SessionFactory对象;SessionFactory接口:初始化Hibernate,充当数据存储源的代理,创建Session对象;Session接口:负责保存、更新、删除、加载和查询对象;Transaction接口:管理事务;Query和Criteria接口:执行数据库查询。
Configuration接口:Hibernate应用通过Configuration实例来获得对象-关系映射文件中的元数据,以及动态配置Hibernate属性,然后创建SessionFactory实例。
SessionFactory接口:一个SessionFactory对应一个数据存储源,应用从SessionFactory中获得Session实例。它有以下特点:它是线程安全的,这意味着它的同一个实例可以被应用的多个线程共享。它是重量级的(它需要很大的缓存用来存放预定义的SQL语句及映射元数据等),这意味着不能随意创建或销毁它的实例。如果应用只访问一个数据库,则只需要创建一个SessionFactory。用户可以为SessionFactory配置一个缓存插件,被称为Hibernate第二级缓存,用来存放被工作单元读过的数据。
Session接口:它提供了和持久化相关的工作。有以下特点:不是线程安全的、是轻量级的(它的创建或销毁Session对象不需要消耗太多的资源)。Session有一个缓存,被称为Hibernate的第一级缓存,它存放当前工作单元加载的对象。
Transaction接口:它是Hibernate的数据库事务接口,底层事务接口包括:JDBC API、JTA、CORBA。
Query和Criteria接口:它是Hibernate的查询接口,用于向数据库查询对象,以及控制执行查询的过程。Query实例包装了以HQL查询语句,Criteria接口完全封装了基于字符串形式的查询语句,比Query接口更加面向对象,擅长动态查询。
事件及事件监听接口:在Hibernate API,针对每一种事件都有相应的事件监听器。
org.hibernate.Interceptor接口:应用程序可以定义实现Interceptor接口的类,Interceptor实现类负责响应持久化类的实例被加载、保存、更新或删除事件。
org.hibernate.type.Type接口表示Hibernate映射类型,用于把域对象映射为数据库的关系数据。Hibernate为Type接口提供了各种实现类,他们代表具体的Hibernate映射。Primitive Type类:映射java基本类型,包括:ByteType、ShortType、IntegerType、LongType、FloatType、DoubleType、CharrcterType和BooleanType。DateType和BinaryType。
可扩展接口:当Hibernate内置的策略不能满足需求时,Hibernate允许用户以实现接口或扩展特定类的方式,定义客户化的策略。Hibernate的扩展点包括一下几点内容:定制主键的生成策略IdentifierGernerator接口;定制本地SQL方言的Dialect抽象类;定制缓存机制的Cache和CacheProvider接口;定制JDBC连接管理的ConnectionProvider接口;定制事务管理的TransactionFactory、Transaction和TransactionManagerLookup接口;定制属性访问策略的PropertyAccessor接口;创建代理的ProxyFactory接口和定制客户化映射类型的UserType和CompositeUserType接口。
Hibernate的配置文件有两种形式:一种是XML格式的文件,还有一种是Java属性文件(键=值)。
以java属性文件的格式来创建Hibernate的配置文件。默认文件名为hibernate.properties。
hibernate.dialect = org.hibernate.dialect.MySQLDialect
hibernate.connection.driver_class = com.mysql.jdbc.Driver
hibernate.connection.url = jdbc:mysql://localhost:3306/databaseName
hibernate.connection.username = root
hibernate.connection.password = tiger
hibernate.show_sql = true
Hibernate并不要求持久化类必须实现java.io.Serializable接口,但对于采用RMI或JavaEE分布式结构的java应用,当Java对象在不同的进程节点之间传输时,这个对象所属的类必须实现Serializable接口,此外,在Java Web应用中,若希望HttpSession中存放的Java对象进行持久化,那么这个Java对象所属的类也必须实现Serializable接口。
Hibernate要求持久化类必须提供一个不带参数的默认构造方法,因为在程序运行时,Hibernate会运用Java反射机制,调用java.lang.reflect.Constructor.newInstance()方法来构造持久化类的实例。这个默认的构造方法可以采用任意的访问级别。若对这个持久化类使用延迟检索策略,则要求持久化类的默认构造方法的访问级别不可以是private。
Hibernate采用XML格式的文件来指定对象和关系数据之间的映射。在运行时,Hibernate将根据这个映射文件来生成各种SQL,通常这个文件(xxx.hbm.xml)应该和.class放在同一个目录下。
映射文件的文档类型定义(DTD):它对XML文件的语法和格式做了定义。Hibernate的XML解析器将根据DTD来核对XML文件的语法。DTD中特殊符号的作用:无符号:该子元素在父元素内必须存在且只能存在一次;+:该元素在父元素内必须存在,可以存在一次或多次;*:该子元素在父元素内可以不存在,或者存在一次或多次;?:该子元素在父元素内可以不存在或只存在一次。
Hibernate采用XML文件来配置对象-关系映射,有以下优点:Hibernate既不会渗透到上层域模型中,也不会渗透到下层关系数据模型中。域模型和关系数据模型相互独立。对象-关系映射不依赖与任何程序代码。
Hibernate提供的实用工具:
hbm2java:根据映射文件自动生成Java源文件
hbm2ddl:根据映射文件自动生成数据库Schema
XDoclet:根据带有XDoclet标记的Java源文件生成映射文件
Middlegen:根据数据库Schema自动生成映射文件
定制持久化类:若把<meta>元素放在最上边,则所有类全部继承,可以设置inherit="false"来指定只有第一个类继承,或者使用作用域。
指定描述类的JavaDoc
<class name="xx">
<meta attribute="class-description">
Represent a singgle xx
</meta>
...
</class>
表示在xx类中添加描述类的JavaDoc,hbm2java工具生成的Java源代码如下
/**
* Represent a singgle xx
*/
public class xx implements Serialize
指定类所继承的类
<class name="xx">
<meta attribute="extends">xxFather</meta>
...
</class>
public class xx extends xxFather inplements Serializable
指定描述类的属性JavaDoc
<property name="xx" type="boolean" column="isXX">
<meta attributes="field-description">Is xx?</meta>
</property>
/**
* *Is xx?
*/
public Boolean getXx(){
return this.xx;
}
指定类、类的属性及类属性的getXXX()方法或setXXX()方法的修饰符。可选值包括static、final、abstract、public、protect和private。
<id name="id" type="long">
<meta attribute="scope-set">private</meta>
<generate class="native" />
</id">
private void setId(long id){
this.id = id;
}
指定在类的toString()方法返回的字符串中是否包含特定的属性
<property name="name" type="string" not-null="true">
<meta attribute="use-in-tostring">true</meta>
</property>
public String toString(){
StringBuffer buffer = new StringBuffer();
buffer.append(getClass().getName())
.append("@")
.append(Integer.toHexString(hashCode())).append("[");
buffer.append("name").append("='")
.append(getName()).append("'");
...
}
<meta>元素的所有属性的
class-description 指定描述类的JavaDoc
field-description 指定描述类的属性的JavaDoc
interface 如果为true,表示生成接口而非类,默认为false
implements 指定类所实现的接口
extends 指定类所继承的父类名
generated-class 重新制定生成的类名
scope-class 指定类的修饰符,默认为public
scope-set 指定set方法的修饰符,默认为public
scope-get 指定get方法的修饰符,默认为public
scope-field 指定类的属性的修饰符,默认为private
use-in-tostring 如果为true,表示在toString()方法中包含此属性
gen-property 如果是false,不会在java类中生成此属性,默认为true
<property>元素的<column>子元素用于精粒度的控指表的定义。
<column>元素的主要用法:
设定字段名、字段长度及唯一性。 name length unique
设定字段不允许为空,并且为这个字段设立检查约束 not-null check
设置索引 index=""
设置字段的SQL类型 sql_type=""
利用ANT运行项目。build.xml
<?xml version="1.0" ?>
<project name="ANT" default="prepare" basedir=".">
<!-- set up properties containing important project directories -->
<property name="source.root" value="src" />
<property name="class.root" value="classes" />
<property name="lib.dir" value="lib" />
<property name="schema.dir" value="schema" />
<!-- set uo the class path for compilation and execute -->
<path id="project.class.path">
<!-- include our own classes , of course -->
<pathelement location="${class.root}" />
<!-- include jars in the project library directory -->
<fileset dir="${lib.dir}">
<include name="*.jar" />
</fileset>
</path>
<!-- create our runtime subdirectories and copy resources into them -->
<target name="prepare" description="sets uo build structures">
<delete dir="${class.root}" />
<mkdir dir="${class.root}" />
<!-- copy our property files and O/R mappings for use at runtime -->
<copy todir="${class.root}">
<fileset dir="${source.root}">
<include name="**/*.properties" />
<include name="**/*.hbm.xml" />
<include name="**/*.cfg.xml" />
</fileset>
</copy>
</target>
<target name="codegen" depends="prepare">
<taskdef name="hbm2javaTask"
classname="org.hibernate.tool.ant.HibernateToolTask"
classpathref="project.class.path" />
<hbm2javaTask destdir="${source.root}">
<configuration
configirationfile="${class.root}/hibernate.cfg.xml" />
<hbm2java />
</hbm2javaTasl>
</target>
<!-- compile the java source of the project -->
<target name="compile" depends="codegen"
description="compiles all java classes" >
<javac srcdir="${source.root}" destdir="${class.root}"
debug="on" optimize="off" deprecation="on" >
<classpath refid="project.class.path" />
</javac>
</target>
<target name="schema" depends="compile">
<taskdef name="hbm2ddlTask"
classname="org.hibernate.tool.ant.HibernateToolTask"
classpathref="project.class.path" />
<hbm2ddlTask destdir="${schema.dir}">
<configuration
configirationfile="${class.root}/hibernate.cfg.xml" />
<hm2ddl export="true" console="true" create="true"
drop="true" outputfilename="dbName.slq" />
</hbm2ddlTask>
</target>
<target name="run" description="run a Hibernate sample"
depends="schema">
<java classname="xxx" fork="true">
<classpath refid="project.class.path" />
</java>
</target>
</project>
</xml>
perpare target:如存在classes目录,先将它删除,接着重新创建classes子目录。然后把src子目录下所有扩展名为properties、hbm.xml、cfg.xml的文件复制到classes目录下。
codegen target:利用hbm2java工具生成java源码,并将这些源码存放到src子目录下。
compile target:编译src子目录下的所有Java源文件。编译生成的类文件存放在classes子目录下。
schema target:利用hbm2ddl工具生成数据库schema,数据量schema的脚本文件存放在schema子目录下,文件名为dbName.sql。
run target:运行类。