论坛首页 Java企业应用论坛

2010 Java持久化之旅 --起源

浏览 6332 次
精华帖 (0) :: 良好帖 (5) :: 新手帖 (14) :: 隐藏帖 (6)
作者 正文
   发表时间:2010-03-07  
   在广大人民群众和资深玩家的建议下,我开始认真得不得再认真的学习Java持久层的技术。目前关于持久层的书太多,高手建议下,貌似开发hibernate 作者写的Persistence with hibernate 比较靠谱,so ,学习开始。先把这周的学习内容总结下。
1.起源
任何事情产生,都有原因。Hibernate或者其他持久层的框架iBATIS之类我一直认为是因为很多人不会写SQL或者说写不好SQL。But,看了P书Part1后,偶知道,偶错了。
SQL诞生
首先,从持久化说起。持久化,就是把Aplication的状态或者部分状态,保存到可以断电之后依然存在的设备中(比如说,纸上。。。)。
而所有这些东西中,平板文件,XML或者。。。纸,都不是很靠谱,也不好管理,不好阅读。所以,这是为什么数据库产生的原因。

持久化来了
继续来说持久化,把数据(Application中的状态)存入数据库中,然后在一定时间取出来,持久化大概就这样。
具体来说,持久化需要做到以下几点才能叫做真正的成功:
a.能够保存,组织数据,并且可以把数据以一定结构读出
b.处理并发,和保证数据完整性(如果存银行的时候是5000,取出来的时候是5块,那么久没必要存银行了)
c.处理数据共享

问题也来了
我看到这里的时候也很奇怪,为啥米会有问题,把对象的属性保存到数据库不久完事了吗?
但是,因为OO的出现,本来过程化编程中的结构体和数据库表之间几乎相等的映射关系被打破了。

a.Application模型粒度与数据库模型粒度不匹配
   假设有个User中有一些基本属性,又有一个名为Bill的对象引用。类像这样
User{
//some popers
String name;
Bill bill;
//methods
}
Bill{
//bill propers
}
数据库表
create table USER{
NAME varchar(10);
//the following propers represents bill information
MONEY int;
LAST_DATE int;
}
在Application中,有2层User,Bill (用DDD来说就是2个实体对象模型) 但在数据库这一层,我们只看到了一个表。
当时看到这里的时候,我就在想,作者傻呀,我再建一个BILL表不久完了。对,但这回引来另外一个模型不匹配。

b.关系映射不匹配
就像上面例子,如果我们多见一个表BILL.
首先需要明白的是:OO映射使用的是Reference,但数据库映射使用的是外键。这之间的区别会导致一些现在还没看到的问题:
我们先稍微修改下上面的两个类
User{
//some popers
String name;
Set<Bill> bills;
//methods
}
Bill{
Set<User> usersToPayTheBill;
//bill propers
}
简单的一一对应,变成了多对多。现在的问题是,如何能让数据库表现出这种关系呢?对,中间表。
这张中间表,USER_BILL可以使用User和Bill的主键做外键。问题搞定了。。。。吗?
我并没有在Application模型中看到哪里有USER_BILL表可以对应过去的地方。这也实际上是问题a,粒度匹配不上导致的。

c.问题还在继续,OO中的继承关系如何表示
还是拿代码说事,现在User和Bill都在和谐世界中改进了下,开始使用面向接口编程了。。。
User{
//some popers
String name;
Bill bill;
//methods
}
abstract Bill{
long defaultBill = 1000;
//bill propers
}
BillForDuty extends Bill{
//BillForDuty propers
}
BillForRent extends Bill{
//BillForRent propers
}
其他不用说,直接傻眼。对象模型中的继承是叫做Type Inheritance,但关系数据库中的对应类的Table不是一个类型,不存在SuperTable和SubTable之说。
问题还没有结束,面向对象中继承封装和多态,才说了一个不匹配。
当我把一个BillForDuty 得实力丢给User时,只有运行时才会知道这个Bill 引用背后就是个BillForDuty 而不是其他的Bill类型。如果我想根据对象去查询相关信息,我只有寄希望SQL可以做到,但是由于前面说过关系数据库维护关系是通过外键,而外键是直接把值绑定到具体的表上,所以挂了。

d.Equivalent不匹配
就是说对象的equals()或者 == 法在数据库这一层体现说来。因为不管是equals()还是 == ,都是针对对象模型,关系数据库的等同性是由主键决定。

e.查找不匹配
对象模型中要查找一个具体的值 比如 someObject.getProperA().getProperB() 就ok了。但是在关系数据库中要这样写
select * from Object o left outer join A a on a.B_id = o.O_id where o.A=123
好像没问题,但是问题就是:在对象模型中,你不知道getProperA()拿出来是什么就可以继续拿A中B的值,但是在关系数据库中尼必须先知道A是123才能继续找。
*这里有个问题。。。不是PreparedStatement就可以解决者问题吗?

模型不匹配的代价
最大的体会就是,要扭曲领域模型去匹配更难搞定的数据库模型。
今天到此为止,明后争取天把第二部分的总结弄好。






   发表时间:2010-03-08  
学习了,同样是初学,LZ比我理解的深刻,我该努力了
0 请登录后投票
   发表时间:2010-03-08  
看了LZ的话,才发现原来还是有很多人在关心
关系型数据库储存程序对象的问题哈!
0 请登录后投票
   发表时间:2010-03-08  
传说:持久化ORM的出现是数学领域与工程领域的纠结。。。
0 请登录后投票
   发表时间:2010-03-08  
买的孙卫琴的hibernate,刚看前几章感觉还行,后面还没看。

收藏了,看看你笔记。
1 请登录后投票
   发表时间:2010-03-08  
扭曲领域模型去匹配更难搞定的数据库模型

这句话道出了ORM的所为
0 请登录后投票
   发表时间:2010-03-08  
总结的不错.
语言稍微再组织下就更好了.
0 请登录后投票
   发表时间:2010-03-09  
好像hibernate quickily里面也提到过这些东西
0 请登录后投票
   发表时间:2010-03-09   最后修改:2010-03-09
Kensai 写道
   在广大人民群众和资深玩家的建议下,我开始认真得不得再认真的学习Java持久层的技术。目前关于持久层的书太多,高手建议下,貌似开发hibernate 作者写的Persistence with hibernate 比较靠谱,so ,学习开始。先把这周的学习内容总结下。
1.起源
任何事情产生,都有原因。Hibernate或者其他持久层的框架iBATIS之类我一直认为是因为很多人不会写SQL或者说写不好SQL。But,看了P书Part1后,偶知道,偶错了。
SQL诞生
首先,从持久化说起。持久化,就是把Aplication的状态或者部分状态,保存到可以断电之后依然存在的设备中(比如说,纸上。。。)。
而所有这些东西中,平板文件,XML或者。。。纸,都不是很靠谱,也不好管理,不好阅读。所以,这是为什么数据库产生的原因。

持久化来了
继续来说持久化,把数据(Application中的状态)存入数据库中,然后在一定时间取出来,持久化大概就这样。
具体来说,持久化需要做到以下几点才能叫做真正的成功:
a.能够保存,组织数据,并且可以把数据以一定结构读出
b.处理并发,和保证数据完整性(如果存银行的时候是5000,取出来的时候是5块,那么久没必要存银行了)
c.处理数据共享

问题也来了
我看到这里的时候也很奇怪,为啥米会有问题,把对象的属性保存到数据库不久完事了吗?
但是,因为OO的出现,本来过程化编程中的结构体和数据库表之间几乎相等的映射关系被打破了。

a.Application模型粒度与数据库模型粒度不匹配
   假设有个User中有一些基本属性,又有一个名为Bill的对象引用。类像这样
User{
//some popers
String name;
Bill bill;
//methods
}
Bill{
//bill propers
}
数据库表
create table USER{
NAME varchar(10);
//the following propers represents bill information
MONEY int;
LAST_DATE int;
}
在Application中,有2层User,Bill (用DDD来说就是2个实体对象模型) 但在数据库这一层,我们只看到了一个表。
当时看到这里的时候,我就在想,作者傻呀,我再建一个BILL表不久完了。对,但这回引来另外一个模型不匹配。

b.关系映射不匹配
就像上面例子,如果我们多见一个表BILL.
首先需要明白的是:OO映射使用的是Reference,但数据库映射使用的是外键。这之间的区别会导致一些现在还没看到的问题:
我们先稍微修改下上面的两个类
User{
//some popers
String name;
Set<Bill> bills;
//methods
}
Bill{
Set<User> usersToPayTheBill;
//bill propers
}
简单的一一对应,变成了多对多。现在的问题是,如何能让数据库表现出这种关系呢?对,中间表。
这张中间表,USER_BILL可以使用User和Bill的主键做外键。问题搞定了。。。。吗?
我并没有在Application模型中看到哪里有USER_BILL表可以对应过去的地方。这也实际上是问题a,粒度匹配不上导致的。

c.问题还在继续,OO中的继承关系如何表示
还是拿代码说事,现在User和Bill都在和谐世界中改进了下,开始使用面向接口编程了。。。
User{
//some popers
String name;
Bill bill;
//methods
}
abstract Bill{
long defaultBill = 1000;
//bill propers
}
BillForDuty extends Bill{
//BillForDuty propers
}
BillForRent extends Bill{
//BillForRent propers
}
其他不用说,直接傻眼。对象模型中的继承是叫做Type Inheritance,但关系数据库中的对应类的Table不是一个类型,不存在SuperTable和SubTable之说。
问题还没有结束,面向对象中继承封装和多态,才说了一个不匹配。
当我把一个BillForDuty 得实力丢给User时,只有运行时才会知道这个Bill 引用背后就是个BillForDuty 而不是其他的Bill类型。如果我想根据对象去查询相关信息,我只有寄希望SQL可以做到,但是由于前面说过关系数据库维护关系是通过外键,而外键是直接把值绑定到具体的表上,所以挂了。

d.Equivalent不匹配
就是说对象的equals()或者 == 法在数据库这一层体现说来。因为不管是equals()还是 == ,都是针对对象模型,关系数据库的等同性是由主键决定。

e.查找不匹配
对象模型中要查找一个具体的值 比如 someObject.getProperA().getProperB() 就ok了。但是在关系数据库中要这样写
select * from Object o left outer join A a on a.B_id = o.O_id where o.A=123
好像没问题,但是问题就是:在对象模型中,你不知道getProperA()拿出来是什么就可以继续拿A中B的值,但是在关系数据库中尼必须先知道A是123才能继续找。
*这里有个问题。。。不是PreparedStatement就可以解决者问题吗?

模型不匹配的代价
最大的体会就是,要扭曲领域模型去匹配更难搞定的数据库模型。
今天到此为止,明后争取天把第二部分的总结弄好。









楼主,给你一个中肯的批评。
之所以你感到是用ORM这么吃力,或者说模型上很扭曲,究其根本是,你在使用“面向数据的思维”做设计,却又利用“面向对象的工具”来实现你的设计,再说的直白一些,你没有掌握从OOD--OOP的过程,这个是无数写SQL的大拿都长犯得“弊病”,主要是思维习惯了。

没有贬义的意思,就是提醒楼主,从改变思维方式的角度出发,尝试是用PD中的OOM来设计吧,而不要从CDM入手了。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics