- 浏览: 292483 次
- 性别:
- 来自: 上海
-
文章分类
最新评论
-
SpringJava:
摘过来的
小心使用ArrayList和LinkedList -
jingjing0907:
我要成为第一个赞的人!呵呵,
小心使用ArrayList和LinkedList -
SpringJava:
cilendeng 写道应该用ConcurrentHashMa ...
实现单用户登陆session先进先出(session踢出) -
lingxiajiudu:
不错,完美解决我了的问题,赞一个。
子窗体给父窗体传值 javascript opener -
cilendeng:
应该用ConcurrentHashMap
实现单用户登陆session先进先出(session踢出)
信息存储和检索作为同义语伴随 RDBMS 已经 10 来年了,但现在情况有所改变。Java 开发人员尤其厌倦于所谓的对象关系型阻抗失配,也对试图解决这个问题失去了耐心。再加上可行的替代方案的出现,就导致了人们对对象持久性和检索的兴趣的复 苏。本系列是对开放源码数据库 db4o 的详尽介绍,db4o 可以充分利用当前的面向对象的语言、系统和理念。要下载 db4o,可以参考 db4o 主页;为了实践本系列的示例,需要下载 db4o。Web Site : http://developer.db4o.com/
早就听说数据库间的大战以关系型数据库的胜利告终。然而,这之后,编程界真的就风平浪静、一片繁荣了吗?持肯定观点的人恐怕最近都没有试过使用关系数据库来支持 Java™ 对象吧。著名作家和讲师 Ted Neward 为我们带来了这个由多个部分组成的 系列 ,深入介绍了 db4o,它是当前关系型数据库的一种面向对象的可选方案。
在我出道成为程 序员的时候,数据库之战似乎已完全平息。Oracle 和其他几个数据库供应商都非常支持和看好关系模型及其标准查询语言 SQL。实际上,坦率地讲,我从未将任何关系数据库的直接祖先,比如 IMS 或无处不在的平面文件,用于长期存储。客户机/服务器看起来似乎长久不衰。
之 后,忽然有一天,我发现了 C++。正像许多在这个特别的时刻发现了这个特别的语言的其他人一样,它改变了我的整个编程 “世界观”。我的编程模型从基于函数和数据的变成了基于对象的。一时间,再也听不到开发人员大谈构建优雅的数据结构和 “信息隐藏” 了,现在,我们更热衷于多态 、封装 和继承 —— 一整套新的热门字眼。
![]() |
|
与此同时,关系数据库已风光不再,一种新的数据库 —— 对象数据库 —— 成为了人们的新宠。若能再结合一种面向对象的语言,例如 C++ (或与之类似的编程新贵,Java 编程),OODBMS 真是可以堪称编程的理想王国。
但 是,事情的发展并非如此。OODBMS 在 90 年代晚期达到了顶峰,随后就一直在走下坡路。原来的辉煌早已退去,剩下的只有晦涩和局限。在第二轮的数据库之战结束之时,关系数据库又成了赢家。(虽然大 多数 RDBMS 供应商都或多或少地采用了对象,但这不影响大局。)
上述情况中存在的惟一问题是,开发人员对 OODBMS 的热衷一直没有衰退,db4o 的出现就很好地说明了这一点。
对象关系型阻抗失配 这个话题完全可以拿出来进行学术讨论,但简单说来,其本质是:对象系统与关系系统在如何处理实体之间的互动方面所采取的方式是截然不同的。表面上看,对象系统和关系系统彼此非常合适,但若深入研究,就会发现二者存在本质差异。
首先,对象具有身份的隐式性质(其表征是隐藏/隐式的 this
指针或引用,它实际上是内存的一个位置),而关系则具有身份的显式性质(其表征是组成关系属性的主键)。其次,关系数据库通过隐藏数据库范围内的数据查询
和其他操作的实现进行封装,而对象则在每个对象上实现新的行为(当然,模块所实现的继承都在类定义中进行指定)。另外,可能也是最有趣的是,关系模型是个
封闭的模型,其中任何操作的结果都将产生一个元组集,适合作为另一个操作的输入。这就使嵌套的 SELECT
以及很多其他功能成为可能。而对象模型则无此能力,尤其是向调用程序返回 “部分对象” 这一点。对象是要么全有要么全无的,其结果就是:与 RDBMS 不同,OODBMS 不能从表或一组表返回任一、全部或部分列。
简言之,对象(用像 Java 代码、C++ 和 C# 这类语言实现)和关系(由像 SQLServer、Oracle 和 DB/2 这样的现代 RDBMS 实现)操作的方式有极大的差异。对于减少这种差异,程序员责无旁贷。
![]() ![]() |
![]() |
过 去,开发人员曾试图减少对象和关系间的这种差距,尝试过的方式之一是手动映射,比如通过 JDBC 编写 SQL 语句并将结果收集进字段。对这种方式的一个合理的质疑是:是否还有更简化的方法来进行处理。开发人员大都用自动的对象关系映射实用工具或库(比如 Hibernate)来解决这个问题。
即使是通过 Hibernate(或 JPA、JDO、Castor JDO、Toplink 或任何可用的其他 ORM 工具),映射问题也无法彻底解决,它们只会转移到配置文件。而且,这种方式与要解决的问题颇有些风马牛不相及。比方说,如果您想要创建一个分层良好的继承 模型,将它映射到表或一组表无疑是失败之举。若用对常规形式的违背来换取查询的性能,就会将 DBA 与开发人员在某种程度上对立起来。
可问题是很难构建一个富域模型(参见 Martin Fowler 和 Eric Evans 各自所著的书),不管是您以后想要调整它来匹配现有的数据库模式,还是想要调整数据库执行其操作的功能来支持对象模型(甚或这两者)。
但如果能不调整,岂不是更好?
![]() ![]() |
![]() |
db4o 库是最近才出现在 OODBMS 领域的,它使 “纯对象存储” 的概念在新一代对象开发人员中重获新生。(他们笑称,现在不是很流行怀旧么。)为了让您对如何使用 db4o 有一个概念,特给出如下代表单个人的一个基本类:
注意: 如果还尚未下载,请现在就 下载 db4o 。为了更好地进行讨论(或至少编译代码),db4o 是必需的,本系列的后续文章也会用到它。
package com.tedneward.model; public class Person { public Person() { } public Person(String firstName, String lastName, int age) { this.firstName = firstName; this.lastName = lastName; this.age = age; } public String getFirstName() { return firstName; } public void setFirstName(String value) { firstName = value; } public String getLastName() { return lastName; } public void setLastName(String value) { lastName = value; } public int getAge() { return age; } public void setAge(int value) { age = value; } public String toString() { return "[Person: " + "firstName = " + firstName + " " + "lastName = " + lastName + " " + "age = " + age + "]"; } public boolean equals(Object rhs) { if (rhs == this) return true; if (!(rhs instanceof Person)) return false; Person other = (Person)rhs; return (this.firstName.equals(other.firstName) && this.lastName.equals(other.lastName) && this.age == other.age); } private String firstName; private String lastName; private int age; } |
在众多的类中,Person
类显得极为寻常;还很简单。但若深入探究,就不难看出这个类会呈现出非常类似于对象的有趣属性和功能,例如它可以有配偶类,也可以有子类,等等。(我在后续的专栏中会历数这些属性和功能;现在,我只侧重于进行概括介绍。)
在基于 Hibernate 的系统中,将这个 Person
类的一个实例放入数据库,需要如下几个步骤:
- 需要创建关系模式,向数据库描述类型。
- 需要创建映射文件,用这些文件将列和数据库的表映射到域模型的类和字段。
- 在代码中,需要通过 Hibernate 打开到数据库的连接(用 Hibernate 术语来说,就是会话 ),并与 Hibernate API 进行交互来存储对象和将对象取回。
上述操作在 db4o 中出奇地简单,如清单 2 所示:
import com.db4o.*; import com.tedneward.model.*; public class Hellodb4o { public static void main(String[] args) throws Exception { ObjectContainer db = null; try { db = Db4o.openFile("persons.data"); Person brian = new Person("Brian", "Goetz", 39); db.set(brian); db.commit(); } finally { if (db != null) db.close(); } } } |
这样就行了。无需生成模式文件,无需创建映射配置,需要做的只是运行客户机程序,当运行结束时,为存储在 persons.data 中的新 “数据库” 检查本地目录。
检索所存储的 Person
在某些方面非常类似于某些对象关系型映射库的操作方式,原因是对象检索最简单的形式就是按例查询(query-by-example)
。只需为 db4o 提供相同类型的一个原型对象,该对象的字段设置为想要按其查询的值,这样一来,就会返回匹配该条件的一组对象,如清单 3 所示:
import com.db4o.*; import com.tedneward.model.*; public class Hellodb4o { public static void main(String[] args) throws Exception { ObjectContainer db = null; try { db = Db4o.openFile("persons.data"); Person brian = new Person("Brian", "Goetz", 39); Person jason = new Person("Jason", "Hunter", 35); Person clinton = new Person("Brian", "Sletten", 38); Person david = new Person("David", "Geary", 55); Person glenn = new Person("Glenn", "Vanderberg", 40); Person neal = new Person("Neal", "Ford", 39); db.set(brian); db.set(jason); db.set(clinton); db.set(david); db.set(glenn); db.set(neal); db.commit(); // Find all the Brians ObjectSet brians = db.get(new Person("Brian", null, 0)); while (brians.hasNext()) System.out.println(brians.next()); } finally { if (db != null) db.close(); } } } |
运行上述代码,会看到检索出两个对象。
![]() ![]() |
![]() |
在您将我定义为狂热的推崇者之前,请允许我先列举几条反对 db4o 的言论。
Person
类的定义并将其传递进 ObjectContainer
,正如我这里所做的一样。在 OODBMS 内,类定义本身就充当模式,所以无需其他的工具来获取 Person
对象。但是如果您这里所谓的 “其他程序” 指的是其他语言的代码,那么问题就会复杂一些。对于 db4o 不支持的语言,比如 C++ 或 Python,数据基本上是访问不到的,除非是您能从 Java 代码构建程序。db4o 适用于 C# 和其他的 .NET 语言,而其数据格式在二者之间是兼容的,这就使得 Java 对象对同样定义的 .NET 类也可用。如果您这里所谓的 “其他程序” 指的是使用 SQL 和标准调用级接口(比如 ODBC 或 JDBC)来与数据库进行交互的报告工具,那么 db4o(或与此相关的任何 OODBMS)可能未必是很好的选择。机警的读者会发现报告功能现在对 OODBMS 还不可用,但好消息是:已针对此问题发起很多产品和项目,而且 db4o 还支持 “复制(Replication)”,它允许 db4o 实例将数据从其自身的存储格式复制进 RDBMS。
当创建新对象并将其 “放” 进数据库中时,新对象并不具有与其相关的 OID,因而会收到其自身惟一的 OID 值。它会复制,就如同 RDBMS 在执行每个 INSERT 操作时生成主键所做的那样(比如 顺序计数器或自动增量字段)。换言之,就主键而言,OODBMS 与 RDBMS 相当接近,但主键本身并非传统 RDBMS(或过去习惯使用 RDBMS 的程序员)认为的那种主键。
换言之,db4o 旨在解决某些方面的问题,而不是成为解决全部持久性问题的一站式通用解决方案。实际上,这让 db4o 首轮就战胜了 OODBMS:db4o 无意向那些生产 IT 人员宣称自己是多么好的一种理念,以至于完全可以放弃他们在关系数据库上的投资。
![]() ![]() |
![]() |
传 统的集中关系型数据库作为数据存储和操纵的首选工具的地位在短期内无法撼动。以这种数据库为基础发展起来的工具非常之多,历史也很久远,而且许多程序员也 都陷在 “我们总需要数据库” 的思维模式之中,这些无疑加固了其地位。实际上,db4o 在技术上的设计和定位并不是为了挑战 RDBMS 的这一地位。
但 “面向服务” 社区迫切要求我们构建松散耦合的多层世界,当您开始将 OODBMS 放到这种环境中去审视的时候,有趣的现象就出现了:如果要实现组件(服务、层或诸如此类的东西)间真正的松散耦合,那么结果常常是某种程度的耦合只存在于 服务的调用程序和该服务的公开 API(或 XML 类型,不管您如何看待它)之间。无需数据类型,无需公开对象模型,无需共享数据库 —— 本质上讲,持久性方法仅仅是一个实现细节。因此,在大量场景中可用的持久性方法的范围会显著扩大。
发表评论
-
栈的简单应用--单词反转
2014-07-03 16:00 718我们知道栈是一种先进后出,也就是后进先出的数据 ... -
java实现简单的栈
2014-07-01 11:56 658栈--只允许访问第一个数据项即:最后插入的数据。最简单的一句 ... -
小心使用ArrayList和LinkedList
2014-06-30 16:32 801ArrayList内部是使用可増长数组实现的,所以是用ge ... -
有趣的Java算法(3)
2014-06-30 16:29 701给定两个排序后的数组A和B,其中A的末端有足够的空间容纳B ... -
有趣的Java算法(2)
2014-06-30 16:29 1079今天分享一个"将一个整数的每位数分解并按逆序输 ... -
有趣的Java算法
2014-06-20 17:00 767题目及源码分析: /* * 今天在BBS里面看到这 ... -
java 值传递 引用传递
2010-12-17 23:11 2089java方法用的是值传递还是引用传递。你在blogjava上还 ... -
用java代码编写堆栈
2010-05-03 17:39 1255public class Stack { int[] ... -
几种读取属性文件的JAVA实现方式
2010-04-30 19:20 1195转载:http://darkranger.iteye.com/ ... -
Site
2010-04-30 19:20 988http://www.szikao.com/computer/ ... -
JAVA对XML的几种解析方式
2010-04-29 19:53 974对于XML介绍比较全面的还是IBM的专栏: ... -
集合与通用集合
2010-04-29 19:44 1449URL: http://www.ibm.com/develop ... -
HashMap 和TreeMap
2010-04-29 19:41 1294本文重点介绍HashMap。首先介绍一下什么是Map。在数组中 ... -
TreeMap和HashMap的问题
2010-04-29 19:39 2112在一次面试的过程 ... -
实现单用户登陆session先进先出(session踢出)
2010-04-29 19:33 9500首先在系统增加sessionListener 来监听sessi ... -
Java单态模式的实现
2010-04-29 19:23 16031.饿汉式:public class Sing ... -
请教java反射机制里可以调用私有方法吗?
2010-04-27 19:17 1636如题:请教java反射机制里可以调用私有方法吗? Metho ... -
利用java反射机制调用类的私有方法
2010-04-27 18:59 14341.将getInstance()方法设置为private ... -
String是原始数据类型还是引用数据类型
2010-04-26 19:22 1724请教各位高手,String是原始数据类型还是引用数据类型?谢谢 ... -
java中堆(heap)和堆栈(stack)有什么区别
2010-04-26 19:13 2210stack 和 heap 都是内存的 ...
相关推荐
55links友情链接网址跟踪器,放在桌面,每次直接打开就可以访问55links友情链接交易平台,方便快捷。
AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!
moore_01_0909
FIBR English learning
AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!
OIF_IEEE802.3_liaison_19OCt09
做网络安全FTP内容的实验必备
nagarajan_01_1107
AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!
mellitz_3cd_01_0318
PyQt6实战派 配套代码
陕西省省级非物质文化遗产经纬度数据统计表 统计内容包含以下字段: 1. 项目名称 2. 遗产类别 3. 入选批次 4. 所属地区 5. 申报地区/单位 6. 地理经度 7. 地理纬度 该统计表系统记录了陕西省省级非物质文化遗产的地理空间信息,为文化遗产的数字化保护与研究工作提供了重要的数据支撑。
ran_3ck_02a_0918
毕业设计_基于springboot+vue开发的汽车租赁管理系统【源码+sql+可运行】【50308】.zip 全部代码均可运行,亲测可用,尽我所能,为你服务; 1.代码压缩包内容 代码:springboo后端代码+vue前端页面代码; 脚本:数据库SQL脚本 效果图:运行结果请看资源详情效果图 2.环境准备: - JDK1.8+ - maven3.6+ - nodejs14+ - mysql5.6+ - redis 3.技术栈 - 后台:springboot+mybatisPlus+Shiro - 前台:vue+iview+Vuex+Axios - 开发工具: idea、navicate 4.功能列表 - 系统设置:用户管理、角色管理、资源管理、系统日志 - 业务管理:汽车管理、客户管理、租赁订单 3.运行步骤: 步骤一:修改数据库连接信息(ip、port修改) 步骤二:找到启动类xxxApplication启动 4.若不会,可私信博主!!!
# Runcorder - 跑步训练管理系统 Runcorder 是一款专为跑步爱好者、马拉松运动员及高校体育生设计的本地化跑步训练管理工具,基于 Python 开发,结合 Tkinter 图形界面与强大的数据处理能力,为用户提供从训练记录到数据分析的全方位支持。无论是初学者还是专业跑者,Runcorder 都能帮助你科学规划训练、精准追踪进度,并通过可视化图表直观呈现训练成果,让你的跑步训练更智能、更高效! - **多用户管理**:支持创建、加载和删除用户档案,每个用户的数据独立存储,确保隐私与安全。 - **科学训练记录**:全维度记录跑步数据,包括日期、里程、配速、自评和晨跑标记,支持智能输入校验,避免数据错误。 - **多维数据分析**:通过动态可视化图表展示跑步里程趋势、平均配速曲线,支持自定义 Y 轴范围,帮助用户深入理解训练效果。 - **高阶功能**:提供 4 种科学训练模式(有氧/无氧/混合),支持历史记录修改与删除,数据以 JSON 格式持久化存储,跨平台兼容。
paatzsch_01_0708
AnythingLLM是一个全栈应用程序,您可以使用流行的开源大语言模型,再结合向量数据库解决方案构建个人本地AI大模型知识库
mellitz_3ck_02_0519
petrilla_01_0708