对象关系映射概念性示例(怀疑ORM者请进)

bonhomme 2007-05-25 05:07:39
***引言***

过去我一直怀疑ORM,感觉它充其量可以用在小型的、具有简单业务模型和数据关系的项目中。复杂的项目,即使我们用尽了各种复杂的SQL“技巧”,还嫌不够,ORM再聪明,怎么可以生成那么复杂,有时简直是任意复杂的SQL语句呢?

直到有一天,我妻子无意中告诉我:织一件带花样图案的毛衣,其实只需要两根竹钎和一条毛线,织女甚至可以心不在焉地织!我终于恍然大悟,我们用惯了各种复杂SQL语句和DBMS提供的专有技术,是因为我们的业务模型和业务逻辑的设计实在太差,甚至没有设计!我们是被迫用千百根针和千百条线痛苦地编制只有我们自己才能理解的图案。

—— ORM不但适用于小项目,更适用于大项目。越是复杂的项目,受益越明显。


***业务对象模型***

我们将采用一个定单的数据模型。这个数据模型其实很复杂,涉及若干个业务对象(类和相应的数据库表),至少应该有5个:
1. 定单(Orders)
2. 定单明细(Order Details)
3. 厂家(Manufacturers)
4. 客户(Customers)
5. 产品(Products)

这5个业务对象以及它们之间的关系分别用下面5个C#类来大致表示:

[Table(”TBL_MANUFACTURER”)]
public class ManufacturerClass //厂家
{
[Column(”ID”)] public string ID;
[Column(”NAME”)] public string Name;
[Column(”CITY”)] public string City;
[Column(”ADDRESS”)] public string Address;
[Column(”BANK_AACOUNT”)] public string BankAccount;
[Column(”TAX_ACCOUNT”)] public string TaxAccount;
......
}

[Table(”TBL_CUSTOMER”)]
public class CustomerClass // 客户
{
[Column(”ID”)] public string ID;
[Column(”NAME”)] public string Name;
[Column(”CITY”)] public string City;
[Column(”ADDRESS”)] public string Address;
[Column(”BANK_AACOUNT”)] public string BankAccount;
[Column(”TAX_ACCOUNT”)] public string TaxAccount;
......
}

[Table(”TBL_PRODUCT”)]
public class ProductClass // 产品
{
[Column(”ID”)] public string ID;
[Column(”NAME”)] public string Name;
[Column(”PRICE”)]decimal Price;
[RELATION(KeyColumn=”MANUFACTURER_ID”)]
public ManufacturerClass Manufacturer; //厂家
......
}

[Table(”TBL_ORDER”)]
public class OrderClass // 定单
{
[Column(”ID”)] public string ID;
[Column(”DATE”)] datetime string Date;
[Column(”DELIVERY_ADDRESS”)] public string DelieveryAddress;
[Relation(KeyColumn=”CUSTOMER_ID”)] public CustomerClass Customer; //客户
[Relation(KeyColumn=”ORDER_ID”, IsDetail=true)]
public OrderDetailClass[] Details; //定单明细,数组,一对多主从关系
......
}

[Table(”TBL_ORDERDETAIL”)]
public class OrderDetailClass //定单明细
{
[Relation(KeyColumn=”ORDER_ID”)] public OrderClass Order;// 定单对象
[Relation(KeyColumn=”PRODUCT_ID”)] public ProductClass Product; //产品
[Column(“QUANTITY”)] public int Quantity;
[Column(“PRICE”)] public decimal Price;
/////////////////
public decimal ItemTotalPrice {get return (Quantity * Price)} //非映射属性
......
}

我们使用了Table/Column/Relation三个Attributes分别来作表映射、列映射和关系映射的元数据,三个Attribute的语义和语法一目了然,稍微值得注意是对主从关系(OrderClass.Details属性)的映射。

***CRUD操作***

下面展示如何通过ORM对上面的数据模型进行CRUD四项基本操作:

[1] 添加定单:
获得ORM的入口对象
ORMContext ormContext =ORMContext.GetContext(…);

建立定单对象
OrderClass order = new OrderClass();
order.ID = "0001";
order.Date = ......;
order.Customer = ormContext.Load<CustomerClass>("033232"); //通过客户代码获得一个
order.DelieveryAddress = "北京市黄浦区……";
客户对象

建立一个定单明细对象
OrderDetailClass orderItem = new OrderDetailClass()
orderItem.Product = ormContext.Load<ProductClass>("020021"); //通过产品代码获得一个产品对象
orderItem.Quantity = 100;
orderItem.Price = orderItem.Product.Price; //注意这一句
order.Details.Add(orderItem);
建立更多的定单明细对象
.......
保存定单,完成操作
ormContext.Save<OrderClass>(orderItem);

[2] 读取定单
OrderClass order = ormContext.Load("0001");
然后,我们可以访问各种来自上面5个类(表)的信息了,例如:
1) 定单的客户的银行帐号:
string bankAccount = order.Customer.BankAccount;
2) 定单中的第1个产品的厂家的地址
string ManufacturerAddress = order.Details[0].Manufacturer.Address;

[3] 修改定单
先加载一个定单:
OrderClass order = ormContext.Load("0001");
我们要修改定单的发货地址,并且需要删除第六个产品:
order.DelieveryAddress = "北京市朝阳区……";
order.Details.Delete(order.Details[5]);
保存一下,就完成了修改:
ormContext.Save<OrderClass>(orderItem);

[4] 删除定单
一个语句,就把定单和明细全部删除了
ormContext.Delete<OrderClass>(orderItem);


***对象查询***

下面进一步说明如何通过对象查询语言(Object Query Language, OQL)实现典型的二维报表。
例如我们要查询2005年第一季度来自“北京”的客户订购某一编号为“20039023”的厂家的产品的情况。
先定义一个类来组织报表数据集合:
public class OrderReportLine
{
string OrderID, //定单号
datetime Date, //日期
string CustomerName, //客户名称
string CustomerAddress, //客户地址
int Quantity, //数量
decimal Price //单价
}

准备一个OQL查询语句:
string queryText = @”
select Order.ID, Order.Date, Order.Customer.Name,
Order.Customer.Address, Order.Details.Quantity, Order.Details.Price
from Order
where Order.Date >=’20050101’ and Order.Date<’20050401’ and Order.Customer.City = ‘Beijing’ and Order.Details.Product.Manufacturer.ID = ‘20039023’”;

执行查询,获得结果:
OrderReportLine[] orderReport
= ormContext.ExecuteQuery<OrderReportLine>(queryText);

查询结果可以通过数组orderReport进行访问。
注意几点:
1. OQL的基本思想和语法与SQL非常相似,但也有本质区别。OQL的操作对象是类而不是表。from子句后面的Order是c#类名,不是表名。select和where子句里引用的各种名字也是类象名或属性名,不是表名、表别名或列名。另外虽然本例中select子句所列为标量数值,OQL也可以返回整个对象。
2. from子句没有使用join操作,所有的数据都是来自Order对象,和前面CRUD操作 的情形相似,Order类管理了5个业务对象类(表)之间的关系。

注:
文中使用的语法只是概念性的,并不严格符合某种特定ORM工具的具体语法。但各种ORM工具的基本思想都大致和本文所讨论的类似。

本文作者 夏成斌 .NET软件工程师 13764438712


...全文
2241 70 打赏 收藏 转发到动态 举报
写回复
用AI写文章
70 条回复
切换为时间正序
请发表友善的回复…
发表回复
缪军 2011-05-29
  • 打赏
  • 举报
回复
客户,厂商,承运商这些不同的所谓对象,实际上存储的时候,都可能放在org这一个表中,
而功能界面确实各个独立的模块和权限管理;
并且,一个订单业务的来源和目标都有可能是不同的组织机构,

再则,不同的角色对数据的操作方式和输出方式是千差万别的,
比如,应用程序提供的搜索引擎输入"张三",你将要提供关于张三的所有类型的订单索引,然后由用户选择以后再进入精确处理模式,
那种基于CURD和数据驱动思想的方法将会使项目根本经不起需求的风吹草动,更不要说促进用户发展了
  • 打赏
  • 举报
回复
本文和性能有什么关系
michael_jiwei 2008-10-23
  • 打赏
  • 举报
回复
只有一个问题,一般来说,orm映射到数据库都是指定的唯一数据库,如果我有多个数据库再跑,orm貌似不能动态切换数据源的吧?
acqy 2008-10-20
  • 打赏
  • 举报
回复
呵呵,我总结一下,也不知道是否正确
个人认为,ORM的任务就是在业务层“不知道持久化机制是什么、如何工作”的情况下,维持业务对象的“持久化”状态。当业务对象需要持久化时,ORM完成持久化;当业务对象需要从持久化机制中重建时,ORM重建对象。
Hibernate这一词感觉也很有用意:(业务对象的)冬眠,明确说明了持久化这一状态。
当然,我还是坚持具体情况具体分析。不是所有的应用需要ORM。ORM至少会要付出性能代价,是否采用ORM应该要根据应用的规模以及其它的非业务性需求。

cnapc 2008-10-20
  • 打赏
  • 举报
回复
赫赫,谢谢acqy指教.因为每个人的语境不同,那么表达出来意思也会不同,也许是想表述同样的东西.
解耦对于大多数系统来说是必要的
同样对于IDE或语言也是一样,它们也有客户就是开发者,它们同样需要解耦,分层/封装不同的逻辑和实现
如果他们如同偶做出的软件,笨重而又繁琐,大概也不会有多少人使用了...
偶觉得啊,ORM处理的不能够是业务对象,只能是数据对象,如同Java中的实体Bean,这样也许就是你开始说的
NHibernate的轻便快捷?
偶只是将数据对象通过ORM和后台数据作映射(关系也好,存储也好),
而数据之间的存储关系是有穷的,完全可以通过某些表达式来表述.
而逻辑关系应该不会有什么样的东东能够完全涵盖,如果有那一定是AI了
acqy 2008-10-20
  • 打赏
  • 举报
回复
[Quote=引用 62 楼 cnapc 的回复:]
ORM就是工具而已,解耦?解那一层偶?所有的逻辑代码在SQL那一层全部实现,为什么还要到中间层?为什么还要有客户层代码?
不要将某些概念想的太复杂,它们的目的真的很简单呢?
ORM做解耦?代价就太大了。
数据库难道不包括XML数据库?
[/Quote]

我想说明的是,其实数据库概念很广泛,关系型数据库只不过是其中的一种。
你可以选择自己的SQL层而不使用任何ORM,完全取决于你自己。但是无论是你自己写的SQL层,还是ORM,都不得不承担同样一个责任,就是分层解耦。因为业务层是不可能去考虑持久化细节的。
ORM与SQL层还有个细节上的区别,就是O。ORM处理的是业务对象,SQL处理的是数据。你可以去了解一下,.NET中引入Typed Data Set的用意,就能了解到为什么我们需要更多的关注O。
acqy 2008-10-20
  • 打赏
  • 举报
回复
[Quote=引用 62 楼 cnapc 的回复:]
ORM就是工具而已,解耦?解那一层偶?所有的逻辑代码在SQL那一层全部实现,为什么还要到中间层?为什么还要有客户层代码?
不要将某些概念想的太复杂,它们的目的真的很简单呢?
ORM做解耦?代价就太大了。
数据库难道不包括XML数据库?
[/Quote]

我想说明的是,其实数据库概念很广泛,关系型数据库只不过是其中的一种。
你可以选择自己的SQL层而不使用任何ORM,完全取决于你自己。但是无论是你自己写的SQL层,还是ORM,都不得不承担同样一个责任,就是分层解耦。因为业务层是不可能去考虑持久化细节的。
ORM与SQL层还有个细节上的区别,就是O。ORM处理的是业务对象,SQL处理的是数据。你可以去了解一下,.NET中引入Typed Data Set的用意,就能了解到为什么我们需要更多的关注O。
acqy 2008-10-19
  • 打赏
  • 举报
回复
[Quote=引用 60 楼 cnapc 的回复:]
ORM和数据库细节并没有多大关系啊,他只是利于开发人员处理数据时简单灵活些(或者是少写N行代码)
偶们没必要认为ORM就是DB的Administrator,该划分到DB层的实现,还是划分到DB层.
Table的结构/View/存储过程,本来就是DB和应用的接口
如果不使用ORM,现在的代码还不是一样要关联到数据库的细节?
如果偶们认为ORM是一个编程工具(的规范),是不是会好理解些?
[/Quote]

ORM的引入正是为了在业务层(传统三层结构中的业务层)中屏蔽数据库(或者说是外部存储机制)的访问细节,使得业务层能够更加专注在解决业务问题上,而不是访问数据库上。相对较差的设计是,在业务层布满了繁杂的SQL或者存储过程的调用,此时当你的后台数据库有变更的时候,你将会被这一大堆SQL所困扰。在此,说相对较差的意思是,我们需要具体情况具体分析,加入系统本身就不大,那你引入ORM也没必要。如果系统对性能要求很高,那么还不如直接使用ADO。
从效果上来看,ORM确实是让我们少写许多代码。但ORM绝不仅仅是让我们少写些代码这样“肤浅”。这正如MVP模式一样,它使得应用系统的某个层能够更加独立(解耦)于其它层,这样才能使得应用系统更具备扩展性。ORM解决的是状态持久化问题,数据库是目前最为通用的数据保存机制,但对于对象状态的持久化,它不是唯一的机制。比如,对象完全可以在被序列化以后保存到XML文件中。
cnapc 2008-10-19
  • 打赏
  • 举报
回复
ORM和数据库细节并没有多大关系啊,他只是利于开发人员处理数据时简单灵活些(或者是少写N行代码)
偶们没必要认为ORM就是DB的Administrator,该划分到DB层的实现,还是划分到DB层.
Table的结构/View/存储过程,本来就是DB和应用的接口
如果不使用ORM,现在的代码还不是一样要关联到数据库的细节?
如果偶们认为ORM是一个编程工具(的规范),是不是会好理解些?
cnapc 2008-10-19
  • 打赏
  • 举报
回复
补充,并不是说acqy说的不正确^-^
而是各人的表述概念可能有不一样,ORM的确是封装了数据后台
而它对于偶来说也的确是一个工具,不用自己封装不同的数据SQL代码,不用写烦人的某些很相像的代码...
事实上,偶自己做了个类似于Java中Persist概念的库,来处理这些问题
所以从俩个角度来说,全正确
cnapc 2008-10-19
  • 打赏
  • 举报
回复
ORM就是工具而已,解耦?解那一层偶?所有的逻辑代码在SQL那一层全部实现,为什么还要到中间层?为什么还要有客户层代码?
不要将某些概念想的太复杂,它们的目的真的很简单呢?
ORM做解耦?代价就太大了。
数据库难道不包括XML数据库?
丛晓男 2008-10-18
  • 打赏
  • 举报
回复
学习
acqy 2008-10-18
  • 打赏
  • 举报
回复
在ORM上使用Attribute,本身就默认了领域对象需要关联数据库细节,事实上这种做法并不合理。
从分层角度考虑,领域层不应该考虑存储细节问题。在领域对象上设置“Table”、“PrimaryKey”等特性,事实上已经违背了这样的规律。
有兴趣的读者可以去比较一下Castle ActiveRecord以及NHibernate,虽然CA是建立在NHibernate之上,但意思完全不一样。
当然,也不是说NHibernate才是正道,如果项目规模不大,领域层对象关系不复杂的情况下,采用类似于Castle ActiveRecord这样的ORM或许更加轻便快捷。
cnapc 2008-10-18
  • 打赏
  • 举报
回复
偶自己写了个.net的持久化框架,呵呵.
个人觉得保持一个干净简单的目标软件设计框架是应用ORM的前提,ORM的实现倒不是太复杂的事情
可以相互参考.net和Java的ORM实现,有助于理解ORM的构造是为什么
chxljtt 2008-10-14
  • 打赏
  • 举报
回复
以后認真學習
yqyqyoyo 2008-10-08
  • 打赏
  • 举报
回复
mark!
cooolchen 2008-10-02
  • 打赏
  • 举报
回复
好,学习一下
hanjoe109 2008-09-29
  • 打赏
  • 举报
回复
寫得真好,我得好好學學
abcn 2008-09-28
  • 打赏
  • 举报
回复
mark
makecodeeasy 2008-09-13
  • 打赏
  • 举报
回复
mark
加载更多回复(50)
第一部分 从Hibernate和EJB 3.0开始  第1章 理解对象/关系持久化    1.1 什么是持久化     1.1.1 关系数据库     1.1.2 理解SQL     1.1.3 在Java中使用SQL     1.1.4 面向对象应用程序中的持久化    1.2 范式不匹配     1.2.1 粒度问题     1.2.2 子类型问题     1.2.3 同一性问题     1.2.4 与关联相关的问题     1.2.5 数据导航的问题     1.2.6 不匹配的代价    1.3 持久层和其他层 显示全部信息第一部分 从Hibernate和EJB 3.0开始  第1章 理解对象/关系持久化    1.1 什么是持久化     1.1.1 关系数据库     1.1.2 理解SQL     1.1.3 在Java中使用SQL     1.1.4 面向对象应用程序中的持久化    1.2 范式不匹配     1.2.1 粒度问题     1.2.2 子类型问题     1.2.3 同一性问题     1.2.4 与关联相关的问题     1.2.5 数据导航的问题     1.2.6 不匹配的代价    1.3 持久层和其他层     1.3.1 分层架构     1.3.2 用SQL/JDBC手工编写持久层     1.3.3 使用序列化     1.3.4 面向对象的数据库系统     1.3.5 其他选项    1.4 ORM     1.4.1 什么是ORM     1.4.2 一般的ORM问题     1.4.3 为什么选择ORM     1.4.4 Hibernate、EJB 3和JPA简介    1.5 小结   第2章 启动项目    2.1 启动Hibernate项目     2.1.1 选择开发过程     2.1.2 建立项目     2.1.3 Hibernate配置和启动     2.1.4 运行和测试应用程序    2.2 启动Java Persistence项目     2.2.1 使用Hibernate Annotations     2.2.2 使用Hibernate EntityManager     2.2.3 引入EJB组件     2.2.4 切换到Hibernate接口    2.3 反向工程遗留数据库     2.3.1 创建数据库配置     2.3.2 定制反向工程     2.3.3 生成Java源代码    2.4 与Java EE服务整合     2.4.1 与JTA整合     2.4.2 JNDI绑定的SessionFactory     2.4.3 JMX服务部署    2.5 小结   第3章 领域模型和元数据    3.1 CaveatEmptor应用程序     3.1.1 分析业务领域     3.1.2 CaveatEmptor领域模型    3.2 实现领域模型     3.2.1 处理关注点渗漏     3.2.2 透明和自动持久化     3.2.3 编写POJO和持久化实体类     3.2.4 实现POJO关联     3.2.5 把逻辑添加到访问方法    3.3 ORM元数据     3.3.1 XML中的元数据     3.3.2 基于注解的元数据     3.3.3 使用XDoclet     3.3.4 处理全局的元数据     3.3.5 运行时操作元数据    3.4 其他实体表示法     3.4.1 创建动态的应用程序     3.4.2 表示XML中的数据    3.5 小结  第二部分 映射概念和策略  第4章 映射持久化类    4.1 理解实体和值类型     4.1.1 细粒度的领域模型     4.1.2 定义概念     4.1.3 识别实体和值类型    4.2 映射带有同一性的实体     4.2.1 理解Java同一性和等同性     4.2.2 处理数据库同一性     4.2.3 数据库主键    4.3 类映射选项     4.3.1 动态的SQL生成     4.3.2 使实体不可变     4.3.3 给查询命名实体     4.3.4 声明包名称     4.3.5 用引号把SQL标识符括起来     4.3.6 实现命名约定    4.4 细粒度的模型和映射     4.4.1 映射基础属性     4.4.2 映射组件    4.5 小结   第5章 继承和定制类型    5.1 映射类继承     5.1.1 每个带有隐式多态的具体类一张表     5.1.2 每个带有联合的具体类一张表     5.1.3 每个类层次结构一张表     5.1.4 每个子类一张表     5.1.5 混合继承策略     5.1.6 选择策略    5.2 Hibernate类型系统     5.2.1 概述实体和值类型     5.2.2 内建的映射类型     5.2.3 使用映射类型    5.3 创建定制的映射类型     5.3.1 考虑定制的映射类型     5.3.2 扩展点     5.3.3 定制映射类型的案例     5.3.4 创建UserType     5.3.5 创建CompositeUserType     5.3.6 参数化定制类型     5.3.7 映射枚举    5.4 小结   第6章 映射集合和实体关联    6.1 值类型的set、bag、list和map     6.1.1 选择集合接口     6.1.2 映射set     6.1.3 映射标识符bag     6.1.4 映射list     6.1.5 映射map     6.1.6 排序集合和有序集合  6.2 组件的集合     6.2.1 编写组件类     6.2.2 映射集合     6.2.3 启用双向导航     6.2.4 避免非空列    6.3 用注解映射集合     6.3.1 基本的集合映射     6.3.2 排序集合和有序集合     6.3.3 映射嵌入式对象的集合    6.4 映射父/子关系     6.4.1 多样性     6.4.2 最简单的可能关联     6.4.3 使关联双向     6.4.4 级联对象状态    6.5 小结   第7章 高级实体关联映射    7.1 单值的实体关联     7.1.1 共享的主键关联     7.1.2 一对一的外键关联     7.1.3 用联结表映射    7.2 多值的实体关联     7.2.1 一对多关联     7.2.2 多对多关联     7.2.3 把列添加到联结表     7.2.4 映射map    7.3 多态关联     7.3.1 多态的多对一关联     7.3.2 多态集合     7.3.3 对联合的多态关联     7.3.4 每个具体类一张多态表    7.4 小结   第8章 遗留数据库和定制SQL    8.1 整合遗留数据库     8.1.1 处理主键     8.1.2 带有公式的任意联结条件     8.1.3 联结任意的表     8.1.4 使用触发器    8.2 定制SQL     8.2.1 编写定制CRUD语句     8.2.2 整合存储过程和函数    8.3 改Schema DDL     8.3.1 定制SQL名称和数据类型     8.3.2 确保数据一致性     8.3.3 添加领域约束和列约束     8.3.4 表级约束     8.3.5 数据库约束     8.3.6 创建索引     8.3.7 添加辅助的DDL    8.4 小结  第三部分 会话对象处理  第9章 使用对象    9.1 持久化生命周期     9.1.1 对象状态     9.1.2 持久化上下文    9.2 对象同一性和等同性     9.2.1 引入对话     9.2.2 对象同一性的范围     9.2.3 脱管对象的同一性     9.2.4 扩展持久化上下文    9.3 Hibernate接口     9.3.1 保存和加载对象     9.3.2 使用脱管对象     9.3.3 管理持久化上下文    9.4 JPA     9.4.1 保存和加载对象     9.4.2 使用脱管的实体实例    9.5 在EJB组件中使用Java Persistence     9.5.1 注入EntityManager     9.5.2 查找EntityManager     9.5.3 访问EntityManagerFactory    9.6 小结   第10章 事务和并发    10.1 事务本质     10.1.1 数据库和系统事务     10.1.2 Hibernate应用程序中的事务     10.1.3 使用Java Persistence的事务    10.2 控制并发访问     10.2.1 理解数据库级并发     10.2.2 乐观并发控制     10.2.3 获得额外的隔离性保证    10.3 非事务数据访问     10.3.1 揭开自动提交的神秘面纱     10.3.2 使用Hibernate非事务地工作     10.3.3 使用JTA的可选事务    10.4 小结   第11章 实现对话    11.1 传播Hibernate Session     11.1.1 Session传播的用例     11.1.2 通过线程局部传播     11.1.3 利用JTA传播     11.1.4 利用EJB传播    11.2 利用Hibernate的对话     11.2.1 提供对话保证     11.2.2 利用脱管对象的对话     11.2.3 给对话扩展Session    11.3 使用JPA的对话     11.3.1 Java SE中的持久化上下文传播     11.3.2 在对话中合并脱管对象     11.3.3 在Java SE中扩展持久化上下文    11.4 使用EJB 3.0的对话     11.4.1 使用EJB的上下文传播     11.4.2 利用EJB扩展持久化上下文    11.5 小结   第12章 有效修改对象    12.1 传播性持久化     12.1.1 按可到达性持久化     12.1.2 把级联应用到关联     12.1.3 使用传播性状态     12.1.4 利用JPA的传播性关联    12.2 大批量和批量操作     12.2.1 使用HQL和JPA QL的大批量语句     12.2.2 利用批量处理     12.2.3 使用无状态的会话    12.3 数据过滤和拦截     12.3.1 动态数据过滤     12.3.2 拦截Hibernate事件     12.3.3 内核事件系统     12.3.4 实体监听器和回调    12.4 小结   第13章 优化抓取和高速缓存    13.1 定义全局抓取计划     13.1.1 对象获取选项     13.1.2 延迟的默认抓取计划     13.1.3 理解代理     13.1.4 禁用代理生成     13.1.5 关联和集合的即时加载     13.1.6 通过拦截延迟加载    13.2 选择抓取策略     13.2.1 批量预抓取数据     13.2.2 通过子查询预抓取集合     13.2.3 通过联结即时抓取     13.2.4 给二级表优化抓取     13.2.5 优化指导方针    13.3 高速缓存基本原理     13.3.1 高速缓存策略和范围     13.3.2 Hibernate高速缓存架构    13.4 高速缓存实践     13.4.1 选择并发控制策略     13.4.2 理解高速缓存区域     13.4.3 设置本地的高速缓存提供程序     13.4.4 设置重复的高速缓存     13.4.5 控制二级高速缓存    13.5 小结   第14章 利用HQL和JPA QL查询    14.1 创建和运行查询     14.1.1 准备查询     14.1.2 执行查询     14.1.3 使用具名查询    14.2 基本的HQL和JPA QL查询     14.2.1 选择     14.2.2 限制     14.2.3 投影    14.3 联结、报表查询和子查询     14.3.1 联结关系和关联     14.3.2 报表查询     14.3.3 利用子查询    14.4 小结   第15章 高级查询选项    15.1 利用条件和示例查询     15.1.1 基本的条件查询     15.1.2 联结和动态抓取     15.1.3 投影和报表查询     15.1.4 按示例查询    15.2 利用原生的SQL查询     15.2.1 自动的结果集处理     15.2.2 获取标量值     15.2.3 Java Persistence中的原生SQL    15.3 过滤集合    15.4 高速缓存查询结果     15.4.1 启用查询结果高速缓存     15.4.2 理解查询高速缓存     15.4.3 什么时候使用查询高速缓存     15.4.4 自然标识符高速缓存查找    15.5 小结   第16章 创建和测试分层的应用程序    16.1 Web应用程序中的Hibernate     16.1.1 用例简介     16.1.2 编写控制器     16.1.3 OSIV模式     16.1.4 设计巧妙的领域模型    16.2 创建持久层     16.2.1 泛型的数据访问对象模式     16.2.2 实现泛型CRUD接口     16.2.3 实现实体DAO     16.2.4 利用数据访问对象    16.3 命令模式简介     16.3.1 基础接口     16.3.2 执行命令对象     16.3.3 命令模式的变形    16.4 利用EJB 3.0设计应用程序     16.4.1 利用有状态的bean实现会话     16.4.2 利用EJB编写DAO     16.4.3 利用依赖注入    16.5 测试     16.5.1 理解不同种类的测试     16.5.2 TestNG简介     16.5.3 测试持久层     16.5.4 考虑性能基准    16.6 小结   第17章 JBoss Seam简介    17.1 Java EE 5.0编程模型     17.1.1 JSF详解     17.1.2 EJB 3.0详解     17.1.3 用JSF和EJB 3.0编写Web应用程序     17.1.4 分析应用程序    17.2 用Seam改善应用程序     17.2.1 配置Seam     17.2.2 将页面绑定到有状态的Seam组件     17.2.3 分析Seam应用程序    17.3 理解上下文组件     17.3.1 编写登录页面     17.3.2 创建组件     17.3.3 给上下文变量起别名     17.3.4 完成登录/注销特性    17.4 验证用户输入     17.4.1 Hibernate Validator简介     17.4.2 创建注册页面     17.4.3 用Seam实现国际化    17.5 利用Seam简化持久化     17.5.1 实现对话     17.5.2 让Seam管理持久化上下文    17.6 小结  附录A SQL基础知识  附录B 映射快速参考
Spring.NET是一个应用程序框架,其目的是协助开发人员创建企业级的.NET应用程序。它提供了很多方面的功能,比如依赖注入、面向方面编程(AOP)、数据访问抽象及ASP.NET扩展等等。Spring.NET以Java版的Spring框架为基础,将Spring.Java的核心概念与思想移植到了.NET平台上。 第一章 序言 第二章 简介 2.1.概述 2.2.背景 2.3.模块 2.4.许可证信息 2.5.支持 第三章 背景 3.1.控制反转 第一部分 核心技术 第四章 对象对象工厂和应用程序上下文 4.1.简介 4.2.IObjectFactory,IApplicationContext和IObjectDefinition接口介绍 4.2.1.The IObjectFactory和IApplicationContext 4.2.2.对象定义 4.2.3.对象的创建 4.2.3.1.通过构造器创建对象 4.2.3.2.通过静态工厂方法创建对象 4.2.3.3.通过实例工厂方法创建对象 4.2.4.泛型类的对象创建 4.2.4.1.通过构造器创建泛型类的对象 4.2.4.2.通过静态工厂方法创建泛型类的对象 4.2.4.3.通过实例工厂方法创建泛型类的对象 4.2.5.对象标识符(id和name) 4.2.6.Singleton和Prototype 4.3.属性,协作对象,自动装配和依赖检查 4.3.1.设置对象的属性和协作对象 4.3.2.构造器参数解析 4.3.2.1.根据参数类型匹配构造器参数 4.3.2.2.根据参数索引匹配构造器参数 4.3.2.3.根据名称匹配构造器参数 4.3.3.详细讨论对象属性和构造器参数 4.3.3.1.设置空值 4.3.3.2.设置集合值 4.3.3.3.设置泛型集合的值 4.3.3.4.设置索引器属性 4.3.3.5.内联对象定义 4.3.3.6.idref节点 4.3.3.7.引用协作对象 4.3.3.8.value和ref节点的简短格式 4.3.3.9.复合属性名 4.3.4.方法注入 4.3.4.1.查询方法注入 4.3.4.2.替换任意方法 4.3.5.引用其他对象或类型的成员 4.3.5.1.使用对象或类的属性值行注入 4.3.5.2.使用字段值行注入 4.3.5.3.使用方法的返回值行注入 4.3.6.IFactoryObject接口的其它实现 4.3.6.1.Log4Net 4.3.7.使用depends-on 4.3.8.自动装配协作对象 4.3.9.检查依赖项 4.4.类型转换 4.4.1.枚举类型的转换 4.4.2.内置的类型转换器 4.4.3.自定义类型转换器 4.4.3.1.使用CustomConverterConfigurer类 4.5.自定义对象的行为 4.5.生命周期接口 4.5.1.1.IInitializingObject接口和init-method属性 4.5.1.2.IDisposable接口和destroy-method属性 4.5.2.让对象了解自己的容器 4.5.2.1.IObjectFactoryAware接口 4.5.2.2.IObjectNameAware接口 4.5.3.IFactoryObject接口 4.6.抽象与子对象定义 4.7.与IObjectFactory接口交互 4.7.1.获得IFactoryObject对象本身,而非其产品 4.8.使用IObjectPostProcessor接口自定义对象 4.9.使用IObjectFactoryPostProcessor定制对象工厂 4.9.1.PropertyPlaceholderConfigurer类 4.9.1.1.使用环境变量行替换 4.9.2.PropertyOverrideConfigurer类 4.10.使用alias节点为对象添加别名 4.11.IApplicationContext简介 4.12.配置应用程序上下文 4.12.1.注册自定义解析器 4.12.2.创建自定义资源处理器 4.12.3.配置类型别名 4.12.4.注册类型转换器 4.13.IApplicationContext接口的扩展功能 4.13.1.上下文继承 4.13.2.使用IMessageSource接口 4.13.3.在Spring.NET内部使用资源 4.13.4.松耦合事件模型 4.13.5.IApplicationContext的事件通知 4.14.定制IApplicationContex中对象的行为 4.14.1.IApplicationContextAware标识接口 4.14.2.IObjectPostProcessor接口 4.14.3.IObjectFactoryPostProcessor接口 4.14.4.PropertyPlaceholderConfigurer类 4.15.从其它文件中导入对象定义 4.16.服务定位器访问 第五章. IObjectWrapper接口和类型转换 5.1.简介 5.2.使用IObjectWrapper接口管理对象 5.2.1.读、写普通及嵌套的属性 5.2.2.其它功能 5.3.类型转换 5.3.1.转换枚举类型 5.4.内置类型转换器 第六章. IResource接口 6.1.简介 6.2.IResource接口 6.3.内置的IResource实现类 6.4.IResourceLoader接口 6.5.IResourceLoaderAware接口 6.6.应用程序上下文和IResource路径 第七章. 多线程和并发操作 7.1.简介 7.2.线程本地存储 7.3.同步基础 7.3.1.ISync 7.3.2.SyncHolder 7.3.3.Latch 7.3.4.Semaphore 第八章. 对象池 8.1.简介 8.2.接口和实现 第九章. Spring.NET杂记 9.1.简介 9.2.PathMatcher 9.2.1.通用规则 9.2.2.匹配文件名 9.2.3.匹配子目录 9.2.4.大小写需要考虑,斜线可以任意 第十章. 表达式求值 10.1.简介 10.2.表达式求值 10.3.语言参考 10.3.1.文字表达式 10.3.2.属性,数组,列表,字典,索引器 10.3.2.1.定义内联的数组、列表和词典 10.3.3.方法 10.3.4.操作符 10.3.4.1.关系操作符 10.3.4.2.逻辑操作符 10.3.4.3.算术运算符 10.3.5.赋值 10.3.6.表达式列表 10.3.7.类型 10.3.8.类型注册 10.3.9.构造器 10.3.10.变量 10.3.10.1.'#this'和'#root'变量 10.3.11.三元操作符(If-Then-Else) 10.3.12.列表的投影(Projection)和选择(Selection) 10.3.13. 集合处理器和聚合器 10.3.13.1.Count聚合器 10.3.13.2.Sum聚合器 10.3.13.3.Average聚合器 10.3.13.4.Minimum聚合器 10.3.13.5.Maximum聚合器 10.3.13.6.nonNull处理器 10.3.13.7.distinct处理器 10.3.13.8.sort处理器 10.3.14.引用容器中的对象 10.3.15.Lambda表达式 10.3.16.空目标 10.4.本章使用的示例类型 第十一章. 验证框架 11.1.简介 11.2.用法示例 11.3.验证对象组 11.4.验证对象 11.4.1.条件验证对象 11.4.2.必需性验证对象 11.4.3.正则表达式验证对象 11.4.4.通用验证对象 11.4.5.条件型验证 11.5.验证行为 11.5.1.错误消息行为 11.5.2.通用行为 11.6.引用验证对象 11.7.在ASP.NET中的使用技巧 11.7.1.显示验证错误 11.7.1.1.配置错误显示类 第十二章. 使用Spring.NET行面向方面的编程 12.1.简介 12.1.1.AOP基本概念 12.1.2.Spring.NET AOP的功能 12.1.3.Spring.NET的AOP代理 12.2.Spring.NET中的切入点 12.2.1.概念 12.2.2.切入点的操作 12.2.3.Spring.NET提供的切入点实现类 12.2.3.1.静态切入点 12.2.3.2.动态切入点 12.2.4.自定义切入点 12.3.Spring.NET的通知类型 12.3.1.通知的生命周期 12.3.2.通知类型 12.3.2.1.拦截环绕通知 12.3.2.2.前置通知 12.3.2.3.异常通知 12.3.2.4.后置通知 12.3.2.5.引入通知 12.4.Spring.NET中的Advisor 12.5.使用ProxyFactoryObject创建AOP代理 12.5.1.基本原理 12.5.2.ProxyFactoryObject的属性 12.5.3.代理接口 12.5.4.代理一个类 12.6.使用ProxyFactory类以编程方式创建AOP代理 12.7.管理目标对象 12.8.使用“自动代理”功能 12.8.1.自动代理对象的定义 12.8.1.1.ObjectNameAutoProxyCreator 12.8.1.2.DefaultAdvisorAutoProxyCreator 12.8.1.3.AbstractAutoProxyCreator 12.8.2.使用特性驱动的自动代理 12.9.使用TargetSources 12.9.1.动态切换TargetSource 12.9.2.池化TargetSource 12.9.3.PrototypeTargetSource 12.10.定义新的通知类型 12.11.参考资源 第十三章.通用日志抽象层 13.1.简介 13.1.1.Logging API 13.2.实现与配置 13.2.1.控制台Logger 13.3.Log4Net 第二部分. 中间层数据访问 第十四章. 事务管理 14.1.简介 14.2.动机 14.3.核心接口 14.4.用事务行资源同步 14.4.1.高层次方法 14.4.2.低层次方法 14.5.声明式事务管理 14.5.1.理解Spring.NET声明式事务管理的实现 14.5.2.第一个例子 14.5.3.Transaction特性的设置 14.5.4.通过AutoProxyCreator使用声明式事务 14.5.5.通过TransactionProxyFactoryObject使用声明式事务 14.5.6. 通过ProxyFactoryObject使用声明式事务 14.5.7. Using Abstract object definitions 14.5.8. Declarative Transactions using ProxyFactoryObject 14.6. 编程方式的事务管理 14.6.1.使用TransactionTemplate 14.6.2.使用IPlatformTransactionManager 14.7.选择编程方式还是声明方式 第十五章. 数据访问对象 15.1.简介 15.2.统一的异常体系 15.3.为数据访问对象提供的统一抽象基类 第十六章. DbProvider 16.1.简介 16.1.1.IDbProvider和DbProviderFactory 16.1.2. XML配置 16.1.3.管理连接字符串 第十七章. 使用ADO.NET行数据访问 17.1.简介 17.2.动机 17.3.Provider抽象 17.3.1.创建IDbProvider类型的实例 17.4.命名空间 17.5.数据访问的方式 17.6.AdoTemplate简介 17.6.1.执行回调 17.6.2.在.NET 2.0中执行回调 17.6.3. .NET 1.1 17.6.4.AdoTemplate方法指南 17.7.异常翻译 17.8.参数管理 17.8.1. IDbParametersBuilder 17.8.2. IDbParameters 17.9. Mapping DBNull values 17.10. Basic data access operations 17.10.1. ExecuteNonQuery 17.10.2. ExecuteScalar 17.11. Queries and Lightweight Object Mapping 17.11.1. ResultSetExtractor 17.11.2. RowCallback 17.11.3. RowMapper 17.11.4. Query for a single object 17.11.5. Query using a CommandCreator 17.12. DataTable and DataSet 17.12.1. DataTables 17.12.2. DataSets 17.13. Deriving Stored Procedure Parameters 17.14. Database operations as Objects 17.14.1. AdoNonQuery 17.14.2. AdoQuery 17.14.3. MappingAdoQuery 17.14.4. Stored Procedure 17.14.5. DataSetOperation 18. ORM集成 18.1. 简介 第三部分. Web框架 第十九章. Web框架 19.1.简介 19.2.自动装载应用程序上下文和应用程序上下文嵌套 19.2.1. 配置 19.2.2.上下文嵌套 19.3.为ASP.NET页面行依赖注入 19.3.1.为Web控件行依赖注入 19.4.Master Page 19.4.1.将子页面与Master Page关联 19.5.双向数据绑定 19.5.1.数据绑定的后台实现 19.5.1.1.绑定方向 19.5.1.2.Formatters 19.5.1.3.类型转换 19.5.1.4.数据绑定事件 19.6.本地化 19.6.1.使用Localizer行自动本地化(“推”模型) 19.6.2.使用Localizer 19.6.3.手动应用资源(“拉”模型的本地化) 19.6.4.在Web应用程序中行图像本地化 19.6.5.全局资源 19.6.6.用户语言文化管理 19.6.6.1. DefaultWebCultureResolver 19.6.6.2. RequestCultureResolver 19.6.6.3. SessionCultureResolver 19.6.6.4. CookieCultureResolver 19.6.7.更改语言文化 19.7.结果映射 19.8.客户端脚本 19.8.1.在HTML的head节点内注册客户端脚本 19.8.2.向节点中添加CSS定义 19.8.3.全局目录(Well-Known Directories) 第四部分. 服务 第二十章. .NET Remoting 20.1.简介 20.2.在服务端发布SAO 20.2.1.SAO Singleton 20.2.2.SAO SingleCall 20.2.3.IIS应用程序配置 20.3.在客户端访问SAO 20.4.CAO 最佳实践 20.5.在服务端注册CAO 20.5.1.向CAO对象应用AOP通知 20.6.在客户端访问CAO 20.6.1.向客户端的CAO对象应用AOP通知 20.7. XML Schema for configuration 20.8.参考资源 第二十一章. .NET企业服务 21.1.简介 21.2.服务组件 21.3.服务端 21.4.客户端 第二十二章. Web服务 22.1.服务端 22.1.1.消除对.asmx文件的依赖 22.1.2.向web服务中注入依赖项 22.1.3.将PONO发布为web服务 22.1.4.将AOP代理发布为web服务 22.1.5.客户端的问题 22.2.客户端 22.2.1.WebServiceProxyFactory 22.2.2.WebServiceClientFactory 第二十三章. Windows后台服务 23.1.备注 23.2.简介 23.3.Spring.Services.WindowsService.Process.exe应用程序 23.3.1.安装 23.3.2.配置 23.4.将应用程序上下文发布为Windows服务 23.4.1.service.config 23.4.1.1.让应用程序了解自身的位置 23.4.2.watcher.xml - 可选的配置 23.4.3.bin目录 - 可选 23.5.自定义或扩展 23.5.1. .config文件 第五部分. 与Visual Studio.NET集成 第二十四章. 与Visual Studio.NET集成 24.1.XML编辑与验证 24.2.XML Schema的版本 24.3.集成API文档 第六部分. 快速入门程序 第二十五章. IoC快速入门 25.1.简介 25.2.Movie Finder 25.2.1.开始建立MovieFinder应用程序 25.2.2.第一个对象定义 25.2.3.属性注入 25.2.4.构造器参数注入 25.2.5.总结 25.2.6.日志 25.3.应用程序上下文和IMessageSource接口 25.3.1.简介 25.4.应用程序上下文和IEventRegistry接口 25.4.1.简介 25.5.对象示例 25.5.1.实现Spring.Pool.IPoolableObjectFactory 25.5.2.使用池中的对象 25.5.3.利用executor执行并行的grep 25.6.AOP 第二十六章. AOP指南 26.1.简介 26.2.基础知识 26.2.1.应用通知 26.2.2.使用切入点-基本概念 26.3.深入探讨 26.3.1.其它类型的通知 26.3.1.1.前置通知 26.3.1.2.后置通知 26.3.1.3.异常通知 26.3.1.4.引入(mixins) 26.3.1.5.通知链 26.3.1.6.配置通知 26.3.2.使用特性定义切入点 26.4.The Spring.NET AOP Cookbook 26.4.1.缓存 26.4.2.性能监视 26.4.3.重试规则 Spring.NET AOP最佳实践 第二十七章. .NET Remoting快速入门 27.1.简介 27.2.Remoting实例程序 27.3.实现 27.4.运行程序 27.5.Remoting Schema 27.6.参考资源 第二十八章. Web框架快速入门 28.1.简介 第二十九章. SpringAir - 参考程序 29.1.简介 29.2.架构 29.3.实现 29.3.1.业务层 29.3.2.服务层 29.3.3.Web层 29.4.总结 第三十章. 数据访问快速入门 30.1.简介 第三十一章. 事务管理快速入门 31.1.简介 31.2.应用程序概述 31.2.1.接口 第七部分. Java开发人员必读 第三十二章. Java开发人员必读 32.1.简介 32.2.Beans和Objects 32.3.PropertyEditor和TypeConverter 32.4.ResourceBundle和ResourceManager 32.5.异常 32.6.应用程序配置 32.7.AOP框架

13,190

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 分析与设计
社区管理员
  • 分析与设计社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧