﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-Adley-随笔分类-存储技术</title><link>http://www.blogjava.net/Adley/category/50390.html</link><description>机器，宇宙，编程泛型，JdonMVC(framework)</description><language>zh-cn</language><lastBuildDate>Thu, 10 May 2012 09:02:22 GMT</lastBuildDate><pubDate>Thu, 10 May 2012 09:02:22 GMT</pubDate><ttl>60</ttl><item><title>对象角度分析关系范式</title><link>http://www.blogjava.net/Adley/archive/2011/09/27/359585.html</link><dc:creator>Adley</dc:creator><author>Adley</author><pubDate>Tue, 27 Sep 2011 02:21:00 GMT</pubDate><guid>http://www.blogjava.net/Adley/archive/2011/09/27/359585.html</guid><wfw:comment>http://www.blogjava.net/Adley/comments/359585.html</wfw:comment><comments>http://www.blogjava.net/Adley/archive/2011/09/27/359585.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Adley/comments/commentRss/359585.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Adley/services/trackbacks/359585.html</trackback:ping><description><![CDATA[<span class="Apple-style-span" style="font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 12px; line-height: 18px; background-color: #ffffff; ">范式以及规范化过程&nbsp;<br /><br /><strong style="font-weight: bold; ">1NF ---&gt; 2NF,消除非主属性对码的部分函数依赖&nbsp;<br /><br />2NF&nbsp; ---&gt; 3NF,消除非主属性对码的传递函数依赖&nbsp;<br /><br />3NF&nbsp; ---&gt; BCNF, 消除主属性对码的部分和传递函数依赖&nbsp;<br /><br />BCNF&nbsp; ---&gt; 4NF, 消除非平凡且非函数依赖的多值依赖</strong>&nbsp;<br /><br />第一范式：属性不可再分，如果按照面向对象里面的字段和结合数据类型来分析，一就是一，二就是二，哪来再分的概念，第一范式不管从对象角度还是现有的关系数据管理系统角度都是符合的，你也设计不出不满足第一范式的表，这是最基本的了。&nbsp;<br /><br />第二范式：非主属性要完全依赖于主属性，官话叫做消除部分函数依赖。问题出在复合主键上，复合键里面的各个属性决定了整个表里的部分列，要解决此问题就要从DDD(领域驱动设计)里的实体分析，实体只定义一个ID，一般由机器产生，系统通过这个ID跟踪实体，好了，一个实体对象有哪些属性必然是完全依赖于主键，这样就符合二范式了，而且如果只有一个ID作为主属性，那么当再严格到三范式的时候就必然是BC范式。&nbsp;<br /><br />举例：&nbsp;<br />(学号, 课程名称) &#8594; (姓名, 年龄, 学分)&nbsp;<br />(课程名称) &#8594; (学分)&nbsp;<br />(学号) &#8594; (姓名, 年龄)&nbsp;<br /><br />第三范式：重点在非主键列上，如果一个非主键列决定了另外的非主键列，这样官话叫做传递函数依赖，要实现互不依赖，这就是提取值对象的时候，把传递部分取出来作为对象的值，用hibernate映射就是一个组件，如果事先按照对象角度分析就没有这些范式问题。&nbsp;<br /><br />关键字段 &#8594; 非关键字段x &#8594; 非关键字段y&nbsp;<br /><br />现在是不是可以得到一个结论，优秀的数据库建模专家和优秀的面向对象建模人员搞出来的业务对象其字段是差不多的？关于这部分的思考可参考这个帖子<a href="http://www.jdon.com/mda/oo_relation.html">http://www.jdon.com/mda/oo_relation.html<br /></a>勇敢的抛弃PB,拿起DDD,DCI,Color UML，对象和时间结合，和场景相结合，外静内动，演绎事实。<br />&nbsp;<img src="http://www.blogjava.net/images/blogjava_net/adley/d2fad869-186e-3be5-9a7b-3d11be10c8e8.png" width="851" height="400" alt="" /><br /><br />但是数据库建模和对象建模一个非常严重的不匹配就是继承，关系模式不支持继承，在表达关系上，关系模式只能通过外键表达一对一和一对多，而且无方向，但对象关系却可以表达多对对，这也是对象思维的抽象美，而关系数据还是靠近数学了一点。这也再一次佐证软件开发需要的不仅仅是数学。&nbsp;<br /><br /><br /><strong style="font-weight: bold; ">总之，规范化或者对象设计的基本思想都是概念上的单一化和足够内聚，规范化具体是逐步消除依赖中的不合适部分，使模式中的各关系模式达到某种程度的分离，让一个关系描述一个概念，一个实体或者一种联系，如果超过一就要把它分离。<br /></strong></span><span class="Apple-style-span" style="font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 12px; line-height: 18px; background-color: #ffffff; color: red; "><strong style="font-weight: bold; ">关键词：实体，聚合，值，边界，不变量，一致性，时间函数，场景，动与静，不变和易变，泛化和多态，副作用，事件，事实空间。</strong></span><span class="Apple-style-span" style="font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 12px; line-height: 18px; background-color: #ffffff; "><strong style="font-weight: bold; "></strong></span><img src ="http://www.blogjava.net/Adley/aggbug/359585.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Adley/" target="_blank">Adley</a> 2011-09-27 10:21 <a href="http://www.blogjava.net/Adley/archive/2011/09/27/359585.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>对象关系不匹配</title><link>http://www.blogjava.net/Adley/archive/2011/09/26/359496.html</link><dc:creator>Adley</dc:creator><author>Adley</author><pubDate>Mon, 26 Sep 2011 03:43:00 GMT</pubDate><guid>http://www.blogjava.net/Adley/archive/2011/09/26/359496.html</guid><wfw:comment>http://www.blogjava.net/Adley/comments/359496.html</wfw:comment><comments>http://www.blogjava.net/Adley/archive/2011/09/26/359496.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/Adley/comments/commentRss/359496.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Adley/services/trackbacks/359496.html</trackback:ping><description><![CDATA[<div><div>关系模型中的范式如果仔细观察就是在将关系模式OO化，范式越高，整个关系模式表示的记录就越OO，不匹配问题，我们要放在对象模型的层次上来分析，有几大类(来自Gavin King的书)：</div><div></div><div>1， &nbsp;粒度问题（对象有聚合，组合，子对象，而关系只有行和列两种粒度）</div><div></div><div>2， &nbsp;子类型问题（关系模型没有继承策略）</div><div></div><div>3， &nbsp;同一性问题（对象的比较有地址比较和值比较，而数据库呢？同一个行可以对应多个恒等对象，equls问题。</div><div></div><div>4， &nbsp;关联相关问题（对象关联有一对一，一对多，多对多，但是数据库只用通过外键表达的一对一和一对多，而且没有方向）</div><div></div><div>5， &nbsp;数据导航问题（关系数据我们可以通过定制sql来导航，而对象导航是渐进的，可怕的n+1问题就在这里）</div><div></div><div>&nbsp;</div><div>面向对象能够最大改善代码的可重用性和可维护性，我们的业务逻辑是在领域模型中被执行而不是sql或者存储过程，对象层次的编码，我们可以大胆的使用各种设计模式，这些都依赖于多态的方法调用，而关系呢？本质就是一个表格或者集合，sql操作的源头和结果都是一个表格或者集合，这与Java应用程序中用来执行业务逻辑的关联对象网络大不相同，如果我们硬是要把对象持久化到关系数据库中，你会发现数据被分解了而不是被表达了，数据库的外键如果在sql中不指定连接将不会起任何作用，而对象可以自由导航。</div><div></div><div>&nbsp;</div><div>关系和领域模型都必须包含相同的业务实体，但是一位面向对象的纯化论者给出实体建模方法与一位经验丰富的关系型数据库建模者各给出的不同，这个问题的通常解决方案是扭曲领域模型和被实现的类，直到他们和sql数据库Schema相匹配，毕竟保证数据安全是长久之计，这样就牺牲了OO的优势，关系模型是有关系理论这个数学基础的，而OO则没有严格的数学定义和理论实体，所以就找不到从数学来解释应该如何对这两种范式建立某种关系，没有优雅的转化被发现。</div><div></div><div>所以很有可能：软件开发是一种艺术，一种需要哲学素养的艺术，艺术就只能靠有艺术感觉的人来创造和享受，这个和音乐，绘画等艺术是一样的，艺术不是数学，不能够被形式化证明，但是创造艺术的过程会用到被数学可以证明的东西，比如音乐中的乐理和物理，这就好比软件开发中的OO和关系数据库。</div><div></div><div>当然数学也是艺术，抽象而冷峻的艺术，应用软件的开发大部分是技术，技术后面是思想，记得周爱民说过的一句话：我们要改变的是思想，提高的是能力，大部分人都是提高能力而不改变思想，这就是大部分人都不是大师的原因。</div><div></div><div>关系数据库不支持继承，我们可以做如下的映射，这些映射都是牺牲关系模式的范式基础的。</div><div></div><div>1， &nbsp;用一个表包含所有继承层次的所有字段，然后标识列来标示是哪个类。这种映射方法最简单，但是是违反规范化的，而且有些字段要强制为NULL值，无法保证关系数据模型的数据完整性，这种映射方式性能最高，最简单。</div><div></div><div>2， &nbsp;每个具体类一张表（意思就是父类不需要表），所有父属性在具体类表中重复，这种映射如果要查询父类要全部扫描子类表，而且一旦父类变化，这些字表要全部变化。</div><div></div><div>3， &nbsp;每个类一张表，表里只包含所属类的属性，然后子类和父类共享外键，这种映射避免了第2种的可怕的修改，但是查询的时候要执行连接。</div></div><img src ="http://www.blogjava.net/Adley/aggbug/359496.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Adley/" target="_blank">Adley</a> 2011-09-26 11:43 <a href="http://www.blogjava.net/Adley/archive/2011/09/26/359496.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>领悟OSIV</title><link>http://www.blogjava.net/Adley/archive/2011/09/25/359483.html</link><dc:creator>Adley</dc:creator><author>Adley</author><pubDate>Sun, 25 Sep 2011 15:34:00 GMT</pubDate><guid>http://www.blogjava.net/Adley/archive/2011/09/25/359483.html</guid><wfw:comment>http://www.blogjava.net/Adley/comments/359483.html</wfw:comment><comments>http://www.blogjava.net/Adley/archive/2011/09/25/359483.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/Adley/comments/commentRss/359483.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Adley/services/trackbacks/359483.html</trackback:ping><description><![CDATA[<span class="Apple-style-span" style="font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 12px; line-height: 18px; background-color: #ffffff; ">OSIV是Open Session In View的简写，这个东西如果项目使用Hibernate或者SSH肯定会遇到，这是一个反模式，它频繁的出现在SSH,和SH的框架组合中，虽然互联网上的讨论很多，如果结合用户友好角度和伸缩性角度来思考，有点自己的感想，OSIV分为两种：&nbsp;<br />第一种OSIV: 在SH架构中，表现层打开session,表现层渲染页面，然后提交事务和关闭session,问题是如果在渲染完页面后发现数据库提交失败怎么办？&nbsp;<br />第二种OSIV: 在SSH架构中，表现层打开session,然后在业务层提交事务，然后session继续保持打开，然后开始渲染页面，然后被表现层关闭，同学们，这个过程是在事务外面进行的，怎么保证数据隔离，你的数据库隔离级别有用吗？我们来看SSH在打开OSIV和没打开OSIV的日志&nbsp;<br /><img src="http://www.blogjava.net/images/blogjava_net/adley/f5754dc1-d1a4-3165-b4a8-3846718be302.jpg" width="1351" height="419" alt="" /><br /><img src="http://www.blogjava.net/images/blogjava_net/adley/900f5d35-409c-3e90-acd8-f4ff9bd1091e.jpg" width="1355" height="357" alt="" /><br /></span><span class="Apple-style-span" style="font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 12px; line-height: 18px; background-color: #ffffff; ">注意上面第一张图片，事务提交，然后表现层渲染，这里就是在事务控制能力之外的。&nbsp;<br />顺便提一下banq老师(Jdon框架的作者)的CSIV解决方法，他有第一种OSIV的问题，但是少了无谓打开session的问题。&nbsp;如果他的Session管理是在Domain Event监听器的执行周期之内，那么就可以回避OSIV问题。<br />为什么有OSIV?&nbsp;<br />因为扭曲的面向对象，因为扭曲的模式：对象被强制作为数据容器，数据重于行为，或者根本没有行为，对象编程是要严格管理状态的，在web开发中更是要考虑用户操作的工作单元。&nbsp;<br /><br />怎么解决？&nbsp;<br /><br />第一种：Gavin King，发明的Seam，支持用户工作空间和对话上下文，一次请求用两个事务，一个用于更新数据库，一个用于渲染页面时读取数据库。&nbsp;<br />第二种：用DDD提升对象到业务层，不要被ORM挟持，异步加载，缓存，DTO等方案。&nbsp;<br />第三种：用Ibatis等工具，直接用SQL定制数据返回&nbsp;<br />第四种：CQRS架构，写和读完全两条路径，彻底解决，干干净净。&nbsp;</span><span class="Apple-style-span" style="font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 12px; line-height: 18px; background-color: #ffffff; "><br /><br /><br /></span><img src ="http://www.blogjava.net/Adley/aggbug/359483.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Adley/" target="_blank">Adley</a> 2011-09-25 23:34 <a href="http://www.blogjava.net/Adley/archive/2011/09/25/359483.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>