一名纽约女技术员的JDO经验

555定时器呼吸灯电路制作全攻略:从仿真到实物搭建(附避坑指南) 本文详细介绍了使用555定时器制作呼吸灯电路的完整流程,从基础原理到实物搭建,包括电路设计、元件选择、仿真验证、焊接技巧及调试优化。特别提供了避坑指南,帮助电子爱好者快速掌握这一经典DIY项目,实现美观的呼吸灯效果。 阅读详情

一个纽约女技术员的JDO经验

JDO应用介绍
by Teresa Lau
译自:http://www.sys-con.com/java/articleprint.cfm?id=1899

(译者注)本文以一个实际的具有一定相互关系的类结构实例和KodoJDO产品作基础,介绍JDO的原理、使用及特点。尤其是与传统JDBC技术的对比,比如一个类的代码从480行减少到140行的现实,说明JDO对代码的减少。另外,本文作者是一位具有五年以上Java顾问经验的女中豪杰,拥有硕士学位,目前工作于纽约。

Java Data Object(JDO) 是一个用于存取某种数据仓库中的对象的标准化API。

使JDO从各种数据对象存取技术中异军突起的是它的高度的易用性和灵活性。

JDO提供了透明的对象存储,因此对开发人员来说,存储数据对象完全不需要额外的代码(如JDBC API的使用)。这些繁琐的例行工作已经转移到JDO产品提供商身上,使开发人员解脱出来,从而集中时间和精力在业务逻辑上。另外,JDO很灵活,因为它可以在任何数据底层上运行。JDBC只是面向关系数据库(RDBMS鳭DO更通用,提供到任何数据底层的存储功能,比如关系数据库、文件、XML以及对象数据库(ODBMS)等等,使得应用可移植性更强。

概述



描述符(Metadata)和增强器(Enhancer)


在JDO中,任何需要存储的类必须是PersistenceCapable(可存储的),而任何用到这些类的其它类必须是PersistenceAware(存储可知的)。看上去有点复杂,不过好消息是采用JDO的透明存储技术,你不需要在代码中将你的类去实现javax.jdo.PersistenceCapable接口或PersistenceAware接口。你只需要象往常一样写一个类即可,JDO厂商会提供一个增强器,这个增强器会改造你的类代码(译者注:就是.class文件,改造class中的二进制代码并不是一件很高深的事,有很多工具可以提供给你对class文件进行改造,比如在某个方法开始和结束时输出日志等等),根据你的描述符使之实现PersistenceCapable接口。你需要做的唯一的额外工作就是为你需要存储的类写一个XML格式的描述符文件。附件1显示了一个我在后面的代码示范中会用到的描述符文件。(附件17和本文的代码可以在www.sys-com.com/java/sourcec.cfm下载。)

描述符一般来说很短,在默认条件下写起来一点也不难,JDO从类本身已经获取了大量的信息。你仅在下列情况下在描述符中添加额外信息:
。你需要改变JDO的默认操作方式,比如,使一个属性不存入数据库,即使它没有标记为transient
。有些额外的信息是JDO无法从类本身获取的,比如:哪一个属性你想设为数据库中的主键(译者注:只有使application identity时才有这个必要),或者某个集合类型(Collection或子接口/类)中的元素是什么类型

存储管理器(PersistenceManager)


当你的类被增强后,你就可能使用PersistenceManager来存储你的对象了。要获取一个PersistenceManager,先要设置一些属性,通常包括下列信息:
。数据库连接信息
。JDO产品的类名
。默认的一些属性,包括连接池大小等等

附件3的第23行显示了如何设置一个Properties对象,从而获取一个JDO的PersistenceManagerFactory(相当于JDBC连接池中的DataSource),进而获得一个PersistenceManager对象(相当于JDBC中的Connection对象),之后,你可以用这个PersistenceManager对象来增加、更新、删除、查询对象(这也是我在后面将会讨论的)。当你的这些操作做完后,你需要关闭主这个PersistenceManager对象,以释放它使之能被再次使用(比如另一个线程)。

附件3的代码片断告诉你如果使用JDO来存储和查询对象。利用一个PersistenceManager类型的对象pm,你可以使用pm.makePersistent()方法来将一个新的对象保存到数据库(第68行)。一个对象仅仅在第一次出现的时候才需要保存到数据库(译者注:更严格一点,只在没有已存储的对象引用时才需要显式地调用makePersistent()方法),当它已经在数据库中存在以后,可以直接通过访问其属性来更新该对象的信息。所有的更新在当前的Transaction(数据库概念:事务)被提交时全部保存到数据库中。而如果你不希望保存主这些更改,只需要简单地rollback当前的Transaction即可(第15到17行)。类似地,你可以调用pm.deletePersistent()删除一个对象(第26行)。

要访问已经存储过的对象,可以简单地遍历其Extent(类的所有扩展),这是一个对该类对象的逻辑上的总称(第12到15行)。

如果你希望有选择地(而不是一古脑地)取出某个类的所有对象的一个子集,你可以创建一个Query(查询)。要做到这一点,调用pm.newQuery()来获得一个Query对象,并传入参数:候选对象集合和一个过滤器。候选对象集合可以是一个Collection或者一个类的Extent。过滤器是一个JDOQL(JDO Query Language)语句。当你创建了这个Query以后,就可以执行它来获得一个符合条件的集合(Collection,第22到26行)。JDOQL是JDO的查询语言;它有点象SQL,但却是依照Java的语法的。这里的例子只是一个简单的示范;使用JDOQL,你的过滤串可以写得很复杂。另外,如果你在过滤串中使用绑定的参数的话,你可以写一个简单的查询然后执行很多次,每次给出新的参数值。关于JDOQL有很多资料可以参考,参见本文的资源列表。

一个对象存储的例子



要找出JDO是否象Sun说的那么好,我会写一些代码,分别使用JDO和JDBC来存储我创建的Book对象(见附件4)。这个Book对象有一个name属性和一个Block对象。为使示例有趣一些,Book对象有一个限制:每本书由其名称唯一确定,也就是说,你不能加入两本同名的书。

一个Block(块)是Book的组成部分,它可以是Document、Chapter或Section。最顶层的Block是Document类型的,并且可以包括任意数量的Chaptor Blocks。每个Chaptor Block可以包括任意数量的Setion Blocks,因此这些Block中有一种嵌套的关系。在每一个Block中,我们用一个HashMap来存放任意数量的其它Block的键值对。

附件5列出了一个我的例子中做测试用的Book。这本书包括两章(Chaptor),第一章有一节(Section),还有第二章。特别地,第二章有一个属性:Color=Red。

用这个图书的例子, 我要实现以下一个存储功能:

。增加:看看我能否成功地向数据库中添加两本书,并且如果我用同样的名字加入第三本书,将会产生一个名称唯一性检查失败的异常
。更新:看看我是否能够更新一本书:增加一个属性“Comment”到它的根Block中。当我提交(commit)的时候,这些更新应该被保存下来,而如果我回滚(rollback),这些更新将被丢弃。
。删除:看看能否通过Query查询一本书然后从数据库中将它删除。

如果没有JDO, 我通常会这样设计:先设计几个相关的关系数据表来存储书中的数据,然后使用SQL和JDBC来存储/读取这些表。由于长度的关系,我不会在这里列出我的JDBC实现,不过如果感兴趣,你可以从JDJ 网站上下载。注意,为了通过JDBC/SQL实现以上这些功能,我必须写很长一段代码(480行!)。我现在要做的是让你看看用JDO来实现同样的功能会有多么的简单。

用JDO存储一个Book对象



用JDO来存储一个Book对象时,尽管我使用与JDBC方式中同样的Book主键类,但Block的ID属性已经完全没有必要。在JDBC方式中,必须用ID属性来在内部引用数据表中的不同的Block。但在JDO中,我根本不需要这个属性,因为JDO会自动地在底层处理它。

为了标明Book对象是需要存储的,我写了一个描述符来标记Book和Block类(见附件1)。在描述符中,我为Block类的children集合属性标明其元素类型是Block(第10到11行),而HashMap的键和值的类型都是String(第12到14行)。此外,由于ID属性并不是Block真正需要的,我在描述符中标明它不需要存储(第8行)。在Book的描述符片断中,我标明nm(名称)属性是它的主键(第5行),因此Book类需要使用自定义的标识类型(Application Identity),类名是BookKey(第4行)。BookKey类的代码见附件6。

在本例中,我使用的JDO产品是KodoJDO(采用关系数据库作底层)。市场上有很多JDO的产品(Implementation);你可以选择其中任意一种,而你的代码不需要作任何变化。底层的关系数据库我选择Enhyda InstantDB(一个Kodo产品附带的关系数据库)。JDO的精髓在于开发人员不需要知道某个JDO产品是如何将数据存入数据库的,所以我也不需要设计任何数据表,尽管我们底层使用的是关系数据库。Kodo提供了一个名为schematool的工具,根据我的描述符自动地创建需要的数据表结构。我所需要做的全部事情就是运行下面的命令来准备数据库底层(译者注:实际上,KodoJDO2.4.0以上版本就可以完成自动的数据库同步,这一步都可以省略。不过只建议在开发时使用):
schematool action refresh Book
schematool action refresh Block

下一步我正常地编译我的类,然后用Kodo的增强器(Enhancer),名为jdoc,来增强我的类代码(译者注:这些步骤可以采用Ant批处理工具来完成,大多数JDO厂商都提供Ant任务支持):
jdoc Book
jdoc Block
jdoc BookPersistJDO

这里,只要我将未增强的class文件(Book.class,BlockPersist.class,BookPersistJDO.class)和描述符放到jdoc能找到的位置,jdoc就会更改这些类代码,使之成为PersistenceCapable,而没有标记为可存储的类将会被增强为PersistenceAware的。在本例中,Book.class和Block.class会被改造为PersistenceCapable的,而BookPersistJDO.class会被改造为PersistenceAware的。(译者注:此处需要说明一下,多数意见提倡非存储的类只通过访问器(accessors,即get/set/is方法)去访问可存储对象的属性,这样,这些非存储的类根本不需要强化,以减少复杂性。)

增强了这些类之后,任何对我的对象进行操作的工作都可以通过PersistenceManager完成。用我前面提到过的那些代码,我可以很简单地获取一个PersistenceManager pm,然后用它来增加、删除、更新一本书。附件7显示了我的BookPersistJDO.java的代码片断。里面的方法addBook(第3行)示范了我如何通过JDO增加一本书,而deleteBook(第13行)示范了我如何删除一本书。

为通过名称来取一本书,我使用JDOQL过滤器创建了一个Query。执行这个Query后,我得到一个符合条件的对象集合(Collection)(第25到29行)。从中得到一个Book对象后,我直接更改其属性然后提交。

附件3显示了我的JDO方式的例子的测试结果。结果符合我的预期。首先,我成功地将一本书加入数据库,然后加了另一本同名的书,结果产生了一个JDOUserException,告诉我违反了名称唯一性的规则。接着,我可以更新一本书的信息,提交这些更新,或者通过回滚放弃这些更新。最后,我可以从数据库中通过名称找出一本书,然后将它删除。

两种版本的比较(JDBC vs JDO)



通过使用JDO和JDBC来解决同样的问题,我观察到以下内容:
1、采用JDO的话,我可以做到与JDBC同样的事。我可以通过JDOQL来查询对象;通过标记Book类的nm属性为主键来保证书的名称唯一性;另外可以增加、删除、更新这些对象。
2、JDO使我的Transaction处理更加容易。在JDBC方式中,因为一本书实际上被对应到四个不同的关系数据表中的许多条记录,我必须保证所有的插入和删除操作在同一个Transaction中完成。相反,JDO只需要一个操作就可以保存所有这些变化,而我不需要使用Transaction来维护这个操作的原子性。
3、BookPersistJDO.java只有140行,比BookPersistJDBC.java(480行)少很多,这些事实都说明JDO使我的代码少了很多。尤其是我的类之间关系有嵌套的特性使得在关系数据库中的表结构比较复杂。在我的JDBC实现中,我不得不花很多心思来设计我的数据库,从而存储和获取这些嵌套的数据。我不得不用一个ID字段来表示每一个Block,并使用一个外键来表达父/子关系。在JDO实现中,我根本不需要考虑这些问题,一切都被正确地存储下来。
4、我为了提高性能而在JDBC实现中加入的缓冲机制在JDO中并不需要,因为JDO产品一般都包含了性能优化和缓冲。这些也节约了我很多工作量,因为我不需要担心我的缓冲是否始终与数据库保持同步。

在这些区别之外,JDO产品和我的JDBC实现可能没有多大区别。比如,这个JDO产品,使用了一个关系数据库,可能也采用类似的表结构设计和ID产生机制,并且用JDBC来存储数据。然而,关键在于我不需要了解这些实现上的细节:这些负担被转移到具有专业水平的JDO厂商身上,也正是这些人更希望在这些细节上做得更好。另外,这些厂商也可以自由地选择在其它类型的存储技术中实现存储,比如对象数据库或文件等等,这些给我们在选择具体存储方式上在有很大的灵活性。

结论



JDO提供了很多好处:
。它具有所有必须的数据存储功能:增、删、改、事务、数据唯一性、缓冲
。它免除了开发人员的一大堆繁琐的工作,使代码更易读和易维护
。它独立于具体的厂商,防止了厂商依赖性
。尽管我的代码没有显示,它可以在任何数据仓库中工作,使开发灵活而可移植

JDO是一种值钻研的技术。本文只是你的一个起点;更多的信息请看下面的资源。

资源

。一站式的网站:http://www.jdocentral.com/
。规范:http://access1.sun.com/jdo/
。Roos, R. (2002). Java Data Objects. Addison Wesley出版社:http://www.ogilviepartners.com (译者注,我有该书作者给我的pdf版本,可以与大家共享,但切勿作商业用途)
。本文例子用到的JDO产品:SolarMetric: http://www.solarmetric.com/Software/Kodo_JDO (译者注:KodoJDO是目前做得最好的产品,性能方面优化特别多,尤其是最新的2.5.0beta版本。该产品的开发团队基本上都来自于麻省理工大学。KodoJDO目前的缺点是不象南非的HemiSphere公司的JDOGenie产品一样,有独立的描述符编辑工具,只能搭配JBuilder7以上使用。不过在我的建议下,他们准备在3.0版本中加入这样的工具。)

JDO的属性配置



附件2提供了我后面用到的属性文件。我用了一个关系数据库,第14行包含了数据库连接的信息。第6行包含我用到的JDO产品的类名(译者注:即厂商对PersistenceManagerFactory的实现类)。第8到10行是对PersistenceManager的默认设置,标明我使用Optimistic Transaction,以及数据在rollback时可从缓冲中恢复,在提交时不保留这些值(译者注:目的是保证有些数据库中的触发器产生的更新可以再从数据库中读回来)。还有很多的细节,可以设置进行Transaction时采用哪些选项。请阅读JDO的API来找到它们的含义,并在需要的时候使用。

JDBC实现

这里我简单地描述一下我如何通过JDBC存储Book类。知道这里面包括多大的工作量后,你会更加理解JDO为你所做的一切。

我创建了四个表来存储Book(见图1)。为保证数据唯一性,Book表的nm字段标记为单一索引(译者注:实际上就是标为主键)。为跟踪每个块(Block)的属性和其子集,我为每个Block增加了一个blockId字段。这个BlockId字段在每个Block加入数据库的时候产生(在已经存在的最大的Block表中的blockId值的基础上加1)。

增加一本书涉及到将一个Book对象的信息分解为四个表:Book,Block,BlockRelation,以及BlockAttr。特别地,每个Block需要生成一个blockId。进一步,最麻烦的是Blocks是嵌套/递归的,我必须写入递归的代码将这些数据插入到数据库。

在附件5创建Book的例子中,这些数据表显示在图2中。你可以看到,一本书被转换成四个表中的很多行,因此,所有的插入操作都必须包装在一个Transaction中,这样才能保证一本书被完整地加入或完整地取消,永不残缺。同样的,删除一本书涉及到从四个表中找出所有合适的需要删除的行,并在一个Transaction中删除以保证这本书被完整地删除或取消删除。

为了更好的性能,我并不想每次有人需要查询一本书的时候都递归地从四个表中取出数据。我创建了一个BookCache,在应用开始运行的时候一下子从数据库中取出所有的书。当我增加、删除、更新这些书的时候,我的代码保证BookCache与数据库是同步的。所有这些工作都在这个cache中完成,使得取一本书只需简单地在cache中按名字查找。

仍不完美的地方



撇开以上谈到的这些优点,还有一些地方是JDO做得还不够的:
。它对新开发的项目很好,但如果要将现存的关系数据库也使用JDO,就需要多做一些映射工作(编辑描述符)
。对开发人员来说,采用JDO后,我们不再需要处理底层的数据库访问,所以在性能优化上可能比原来难一点。因为JDO必须做很多额外的工作,比如跟踪对象属性的变化以同步内部的缓冲等等,JDO产品做得如何对性能至关重要
。JDOQL还不支持聚合操作,比如max, min, sum这些SQL能做到的事。(译者注:在JDO1.0规范的第24章详细描述了下一步2.0规范应该做到的内容,其中包含这些)
。如果能在编译时就能找了JDOQL的错误就好多了。比如在一个过滤串中,你通过一个字符串来指定一个属性名,你很容易写错名称,但编译不会出错,运行时才出错。(译者注:SQL也存在同样问题)
。一些人认为JDO的好处在于你不需要再写SQL,但真实的情况是你必须学习JDOQL。

作者介绍



Teresa Lau已经作为独立的Java顾问五年多了,重点在金融系统上。她拥有计算机硕士学位,目前工作在纽约。

源代码:


Listing 1 Metadata for my example


1 <?xml version="1.0"?>
2 <jdo>
3 <package name="whs.jdo">
4 <class name="Book"
identity-type="application"
objectid-class="BookKey">
5 <field name="nm"
primary-key="true" />
6 </class>
7
8 <class name="Block" >
9 <field name="id"
persistence-modifier="none" />
10 <field name="children">
11 <collection
element-type="Block"/>
12 </field>
13 <field name="attributes">
14 <map key-type="String"/>
15 <map value-type="String"/>
16 </field>
17 </class>
18 </package>
19 </jdo>

Listing 2 Properties for setting up JDO


1 javax.jdo.option.ConnectionUserName=
Database user
2 javax.jdo.option.ConnectionPassword=
Password of the user
3 javax.jdo.option.ConnectionURL=
URL of the database
4 javax.jdo.option.ConnectionDriverName=
Classname of JDBC driver
5
6 javax.jdo.PersistenceManagerFactoryClass=
com.solarmetric.kodo.impl.jdbc.
JDBCPersistenceManagerFactory
7
8 javax.jdo.option.Optimistic=true
9 javax.jdo.option.RestoreValues=true
10 javax.jdo.option.RetainValues=false

Listing 3 JDO Code Fragment

1 // --- Get persistence manager ---
2 PersistenceManagerFactory factory =
JDOHelper.getPersistenceManagerFactory
(property);
3 PersistenceManager pm =
factory.getPersistenceManager()
4
5 // --- Add ---
6 pm.currentTransaction().begin ();
7 pm.makePersistent (obj);
8 pm.currentTransaction().commit ();
9
10 // --- Iterate Extent & Update ---
11 pm.currentTransaction().begin ();
12 Extent ext = pm.getExtent
(MyClass.class, false);
13 for (Iterator i = ext.iterator ();
i.hasNext();) {
14 MyClass obj = (MyClass)i.next ();
15 obj.setField1("AA");
16 }
17 pm.currentTransaction().commit ();
18
19
20 // --- Query and Delete ---
21 pm.currentTransaction().begin ();
22 String filter ="nm=/"JDO Book/"";
23 Query qry= pm.newQuery(ext, filter);
24 Collection c =
(Collection) qry.execute();
25 Object obj = c.iterator().next();
26 pm.deletePersistent (obj);
27 pm.currentTransaction().commit();
28
39 // --- Close resources ---
30 pm.close();

Listing 4 Book & Block object


1 class Book {
2 String nm;
3 Block block= new Block("Document");
4
5 Book(String name){
6 this.nm = name;
7 }
8
9 void addChild(Block e) {
10 block.addChild(e);
11 }
12 }
13
14 class Block {
15 String type;
16 Integer id;
17 Map attributes = new HashMap();
18 List children= new ArrayList();
19
20 Block(String type) {
21 this.type = type;
22 }
23
24 void addChild(Block e) {
25 children.add(e);
26 }
27
28 void setAttribute(String key,
String attr){
29 attributes.put(key, attr);
30 }
31 }

Listing 5 Create Test Book


1 Book book = new Book("Intro to JDO");
2 Block chp1= new Block
("Overview", "Chapter");
3 Block sec11 = new Block
("Advantage of JDO", "Section");
4 chp1.addChild(sec11);
5 Block chp2 = new Block
("Example", "Chapter");
6 chp2.setAttribute("Color", "Red");
7 Block sec21 =new Block
("JDBC Code", "Section");
8 Block sec22 = new Block
("JDO Code", "Section");
9 chp2.addChild(sec21);
10 chp2.addChild(sec22);
11 book.addChild(chp1);
12 book.addChild(chp2);

Listing 6 BookKey.java


1 public final class BookKey {
2 public String nm = null;
3 public BookKey(){}
4
5 public BookKey(String nm) {
6 this.nm = nm;
7 }
8
9 public boolean equals (Object o){
10 if (o == this) return true;
11 if (!(o instanceof BookKey))
return false;
12 return((BookKey)o).nm.equals(nm);
13 }
14
15 public int hashCode () {
16 return nm.hashCode();
17 }
18
19 public String toString() {
20 return nm;
21 }
22 }

Listing 7 BookPersistJDO.java


1 class BookPersistJDO {
2
3 public Book addBook (Book book)
4 throws JDOUserException {
5 PersistenceManager pm =getPM();
6 Transaction tran =
pm.currentTransaction ();
7 tran.begin ();
8 pm.makePersistent (book);
9 tran.commit ();
10 return book;
11 }
12
13 public void deleteBook (Book book){
14 PersistenceManager pm =getPM();
15 Transaction tran =
pm.currentTransaction();
16 tran.begin ();
17 pm.deletePersistent (book);
18 tran.commit ();
19 }
14
15 public Collection getAllBooks() {
15 PersistenceManager pm = getPM ();
17 String filter ="";
18 Extent extent =pm.getExtent
(Book.class, false);
19 Query qry = pm.newQuery
(extent, filter);
20 return (Collection)qry.execute();
21 }
22
23 public Book getBook(String name) {
24 PersistenceManager pm = getPM ();
25 String filter="nm==/"" +
name +"/"";
26 Extent extent = pm.getExtent
(Book.class, false);
27 Query qry = pm.newQuery
(extent, filter);
28 Collection c =
(Collection) qry.execute ();
29 return (Book) c.iterator().next();
30 }
31 }


Additional Code for this Article zip file ~7.78 KB

附图


图 1


图 2


图 3



网友评论



JDO Not Vendor Independent
Posted by Scott P. Smith on Mar 4 @ 01:27 PM

A few weeks ago, I attended a one hour talk by Oracle's Director of Technology, Donald Smith covering persistence archetectures. In it he strongly stated that JDO is not completely vender independent. I don't know that myself. I'm just repeating what he said, which conflicts with claims made in this article.


(read & respond...)

--------------------------------------------------------------------------------
Author lacks JDBC knowledge
Posted by Donald Bales on Mar 4 @ 07:39 PM
The whole article became tainted when the author stated: "...JDBC provides persistence only for relational databases..." Not true. JDBC can handle most of the data sources listed. In fact, many JDO implementations utilize JDBC "under the covers". Second, JDO claims to be able to support these other data sources, but I don't see many implementations. JDO provides a slick abstration for relational databases, but it's not the silver bullet that it's hyped to be.


(read & respond...)

--------------------------------------------------------------------------------
JDO Not Vendor Independant
Posted by I Davie on Mar 5 @ 04:51 AM
JDO is meant to be a Java standard not a database standard. Oracle are not interested in JDO because it gives developers choice and Oracle don't like that! If they're forced to move that way they will but not by choice :-)


(read & respond...)

--------------------------------------------------------------------------------
Pro-JDO comments from JDO vendors
Posted by Scott P. Smith on Mar 5 @ 10:12 AM
Another thing that Donald Smith (no relation) from Oracle said was that the only people making positive comments about JDO are JDO vendors. I see "I Davie" is with Versant, which is soon to be a JDO vendor according to their web site.

I am very neutral with regard to JDO. I have never used it. Can we hear comments from someone (who doesn


(read & respond...)

--------------------------------------------------------------------------------
jdo
Posted by bret on Mar 9 @ 11:22 PM
http://www.sys-con.com/java/article.cfm?id=1899


(read & respond...)

--------------------------------------------------------------------------------
Anti-JDO comments
Posted by David Tinker on Mar 14 @ 08:26 AM
Treat anything that anyone associated with Oracle has to say about JDO with caution. Oracle own Toplink, a $10K/CPU O/R mapping tool that competes directly with JDO. If JDO is sucessful who will pay that kind of money for vendor-lock-in O/R mapping? The most expensive JDO implementations are approx $3K with no runtime costs.

I won't say anything about JDO as I work on JDO Genie from Hemisphere Technologies :) Try it for yourself!


(read & respond...)

--------------------------------------------------------------------------------
Non-Vendor Comment
Posted by Chester Arnold on Mar 24 @ 07:49 AM
I agree with David Tinker. You need to learn to try things out and not always believe vendors who are trying to salvage tanking stock prices. I've used a number of JDO implementations including the one the article used (Kodo JDO). The quality of JDO implementations vary widely so trying them out is probably the best thing you can do.

You can find a list of JDO implementations at www.jdocentral.com.


(read & respond...)

--------------------------------------------------------------------------------
Oracle FEAR!!
Posted by Alf on Mar 25 @ 09:57 AM
It is a matter of time. You will see that programmers prefer JDO , and ORACLE will have to offer their own implementation of the JDO Specification .
You CAN


(read & respond...)
--------------------------------------------------------------------------------



本文的版权属于笔者本人,但欢迎转载,前提是注明出处和原作者。另外,欢迎在我的专栏中查看我的另几篇文章,并提出宝贵意见!

Wireshark抓包实战:5个CTF比赛中高频出现的流量分析技巧(附真实案例) 本文分享了Wireshark在CTF比赛和实战渗透中的五个核心流量分析技巧。内容涵盖从宏观统计概览锁定可疑目标、深度解析ICMP与HTTP等协议、追踪重组完整会话流,到利用字符串搜索和命令行工具进行自动化分析。掌握这些高阶技巧能显著提升分析海量网络流量的效率与精准度。 阅读详情

相关推荐

通讯软件019——分分钟学会Prosys OPC UA Server配置

本文介绍如何配置Prosys OPC UA Simulation Server,通过本文可以对OPC UA的基本概念有所了解,掌握OPC UA的本质。

zhouwl72的博客 4300

DataSphere Studio Caused by: java.lang.ClassNotFoundException: javax.jdo.JDOQLTypedQuery

报错:解决办法:

gs80140的专栏 305

Cartographer从安装到实战:手把手教你运行2D/3D建图与定位

本文提供了一份详尽的Cartographer从零安装到实战应用的完整指南。内容涵盖环境准备、依赖编译、源码构建等关键步骤,并手把手指导读者运行2D/3D官方数据集进行建图与定位测试。文章深入解析了参数配置与自定义数据适配方法,帮助开发者快速掌握这一强大的实时同步定位与建图工具,并将其应用于机器人导航与自动驾驶等实际场景。

rice5的博客 951

JDO技术分析及如何进入企业应用的研究

本文引自:http://www.cn-java.com/target/news.php?news_id=3340 出处 Java研究组织 曹振新 JDO(Java Data Object)是JCP中较早开发出来并形成规范的JSR12,该规范对数据的持久化存储进行了一系列规范,并已有众多的商业产品和开源项目是基于该规范。作为一种需要引起重视的技术,研究并探讨其企业应用可行性是十分重要的。 ...

TrampEagle的专栏 298

地平线天工开物AI开发平台实战:从量化训练到模型部署的完整指南

本文提供了地平线天工开物(OpenExplorer)AI开发平台的实战指南,详细解析了从量化训练到模型部署的完整流程。文章重点对比了量化感知训练(QAT)与训练后量化(PTQ)两条核心路径的优劣与适用场景,并分享了图像分类模型PTQ部署的实战经验与常见问题调试技巧,旨在帮助开发者高效地将AI模型部署到地平线AI芯片上。

weixin_29046035的博客 456

SAP系统从ECC升级至S/4 HANA的实现路径及项目过程

从SAP ECC升级到 S/4 HANA,通常是一个复杂的转型过程,涉及到企业资源规划系统的全面现代化

saplakes的博客 2903

JDO快速入门

<br />JDO快速入门Java数据对象(Java Data Objects,JDO)是一个应用程序接口(API),它是Java程序员能够间接地访问数据库,也就是说,不需使用直接的结构化查询语言(SQL)语句。JDO是作为Java数据库连接(JDBC)的一个补充来介绍的,而JDBC是一个支持使用SOL语句对流行的数据库程序进行访问的接口。有了 JDO,程序员就可以使用类来定义数据对象,然后支撑程序就会根据类的定义来管理对给定数据库的实际的数据访问了。  <br /><br />      JDO是以Sun

liuzhigang1237的专栏 1万+

Autosar开发实战:DaVinci Configurator Pro新建工程保姆级教程(附目录结构解析)

本文详细介绍了使用DaVinci Configurator Pro创建Autosar工程的完整流程,包括环境准备、工程配置、目录结构解析及常见问题排查。通过实战演示和深度解读,帮助开发者快速掌握工具使用技巧,优化工程管理,提升开发效率。特别适合需要理解Autosar开发中DaVinci Config工具链的工程师。

weixin_30872157的博客 458

Java 数据对象(JDO)介绍

 Java 数据对象(JDO)介绍byJeff Brown, Senior Software Engineer Object Computing, Inc. (OCI) 介绍Java 数据对象 (JDO) is 是一个存储Java对象的规范.   它已经被JCP组织定义成JSR12规范。JDO的第一个版本在2000年6月6日提交并在2002年4月30日正式发布1.0版本规范

1714

【华为Hilink SDK Linux系统开发】目录 开源一小步

目录 【华为Hilink开发】第一章:华为hilink平台简介及开发流程 【华为Hilink开发】第二章:华为hilink SDK网络适配、网关添加删除 【华为Hilink开发】第三章:华为hilink SDK子设备添加、删除 【华为Hilink开发】第四章:华为hilink SDK子设备控制及同步 【华为Hilink开发】第五章:华为hilink SDK适配遇到的问题 ...

开源一小步 3620

SAPGUI 与 ADT 的时代分野:在多云架构下,谁还能代表现代 SAP 开发

摘要(149字) SAP开发工具正经历代际更迭:SAPGUI基于专有协议(NI/DIAG)的厚客户端架构难以适配多云环境,而ADT(ABAP Development Tools)通过HTTP(S)协议和Eclipse生态成为ABAP Cloud/RAP开发的唯一入口。关键差异体现在:ADT支持CDS、行为定义等云原生对象建模,天然对齐BTP的零信任网络;集成ATC、Git等DevOps工具链;而SAPGUI无法创建RAP核心对象,在跨平台、自动化方面存在硬限制。官方文档明确将ADT作为Clean Core战

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 390

Java数据对象技术JDO初步概览(Java数据对象技术JDO)

作为异军突起的新型语言,Java定义了一个标准的运行环境,用户定义的类在其中得到执行。这些用户自定义类的实例代表了真实环境中的数据,包括储存在数据库、文件或某些大型事务处理系统中的数据,而小型系统通常也需要一种在本地负责控制数据存储的机制。    由于数据访问技术在不同的数据源类型中是不一样的,因此对数据进行访问成了给程序开发人员的一种挑战,程序员需要对每一种类型的数据源使用特定的编程接口 ...

weimou66 263

成功解决raise Py4JError py4j.protocol.Py4JError: py4j.protocol.Py4JError: Could not find py4j jar at 

成功解决raise Py4JError("Could not find py4j jar at {0}".format(jarpath)) py4j.protocol.Py4JError: Could not find py4j jar at 目录 解决问题 解决思路 解决方法 1、第一步安装jdk 2、第二步安装或升级py4j 解决问题 raise Py4JError("Could not find py4j jar at {0...

头部AI社区如有邀博主AI主题演讲请私信—心比天高,仗剑走天涯,保持热爱,奔赴向梦想!低调,专注,谦虚,自律,反思,成长,还算比较正能量的博主,公益免费传播…内心特别想在AI界做出一些可以推进历史进程影响力的技术(兴趣使然,有点小情怀,也有点使命感呀 4627

一名纽约女技术员的JDO经验 (转)

一名纽约女技术员的JDO经验 (转)[@more@]一个纽约女技术员的JDO经验 JDO应用介绍by Teresa Lau译自:http://www.sys-con.com/Java/articleprint.cfm?id=18...

ciya3282的博客 206

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

一个纽约女技术员的JDO经验

google_ad_client = "pub-8800625213955058";/* 336x280, 创建于 07-11-21 */google_ad_slot = "0989131976";google_ad_width = 336;google_ad_height = 280;//<script type="text/java

java专栏 521

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

JDO2.0 五一公投结果浅析

  没有策略性枪击,没有争议性投票,在我们享受五一长假的过程中,JDO2.0规范的首轮议会投票结束了。  自从2004年4月20日JDO2.0规范的制定流程(JSR243)开动以来,JDO又开始回到人们的视线中,并且在五一假期结束之前,规范的制定委员会成员陆续地进行了投票,以表达各自的支持程度,目前投票已经全部结束。下面列举一下投票结果,并在最后发表几点个人愚见。  下面先列举一下投票结果

sun2bin的专栏 2266

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

《自然》:人工智能在创造性思维方面超越人类

ChatGPT-4 在三项有151名人类参与的**发散思维测试中,**展现出比人类更高水平的创造力,结果显示人工智能在创意领域持续发展。5、人工智能可以让我们从创造性工作中解放出来,这样我们就可以专注于做体力劳动的真正目的,而这些体力劳动的报酬太低,无法让自动化盈利。6、创造力就是将人们能记住的想法混合在一起,所以想法越多,混合的方式越多,这也是一种想法,就意味着创造力越高。理论上人工智能拥有接近无限的内存,而人类只有大约 100 兆字节的内存,因此人工智能肯定比人类有更多的想法。

极道Jdon的技术博客 603

亚马逊AI把码农逼成码头工人

不过,也有人觉得这没啥大不了。还有,公司还搞了个“黑客大赛”,鼓励大家开发新的AI工具,简直是“AI催着你再造AI”!不过,哈佛大学的专家劳伦斯·卡茨(Lawrence Katz)说,这对老手程序员可能是个福音,但对新手来说,AI让工作变得太“机械化”,就像19世纪的工厂工人,干的都是简单重复的活儿,脑子都不用动了。亚马逊程序员兄弟说,公司现在狂推人工智能(AI),让他们的工作变得跟流水线上的工人似的,干活得快!亚马逊的程序员们现在就像坐上了“AI过山车”,速度快得吓人,刺激归刺激,但也有点晕乎乎。

极道Jdon的技术博客 709

机器人迎来了chatGPT时刻

以前的机器人都是人类事先编程好动作循序,然后机器人执行完成,但是它们不能处理动作过程中遇到的各种新情况,这种机器人实际是自动化机器。为什么这一点如此重要?之所以说这具有开创性意义,是因为如果您能获得某个应用(煮咖啡、叠衣服、仓库工作等)的人类。就可以在此的基础上对人工智能系统进行端到端训练 这样就有了扩展到每种使用情况的途径。方面取得突破 机器人技术即将迎来它的 ChatGPT 时刻 而这一时刻就在明天。而新的机器人是通过学会观察人类动作后模仿,并能处理煮咖啡过程的各种新情况。

极道Jdon的技术博客 818

内存缓存(in-memory cache)

内存缓存(in-memory cache) 当建立一个大型Java应用时,引起性能问题大部分是延迟,延迟是指请求和响应之间的时间差,在一个分布式Java系统中引起延迟的原因有: 从磁盘上加装数据的IO延迟 跨网络加装数据的IO延迟。 在分布式锁上的资源争夺。 垃圾回收引起的暂停。 典型Ping时间是:本地机器是57µs;局域网是300 µs;从伦敦到纽约是100ms;对于1Gb网络,网络数据传...

qinheJ的博客 1251

杨立昆退休?中国Deepseek超Llama 4触发Meta

我可以自信地说,在我使用它完成的任务中,R1 与 o1 非常接近,接近到我取消了 chatgpt 订阅。在我非常重要的工作中,我们经常开玩笑说 Gemini 比 Deepseek 差远了,因为 Gemini 需要试 5-6 次才能做到 Deepseek 一次就能搞定的事情。这个组织本应该是一个专注于工程的小团队,但因为很多人想加入并争夺影响力,导致招聘人数被人为地扩大了,结果大家都输了。这真的太神奇了,我感觉自己像是在和其他智慧生物一起生活在地球上,因为我真的能看到这个模型是怎么一步步想出最终答案的。

极道Jdon的技术博客 1276

一行代码,损失 6000 万美元!

你好,我是 EarlGrey,喜欢翻译点东西,偶尔写写代码。点击下方卡片关注我,一起向上进击,提升自我。后台回复关键词“电子书”,送你一份我收藏的电子书合集。1990 年 1 月 15 日,AT&T 的新泽西运营中心检测到大范围的系统故障,网络显示屏上出现了大量红色警告。尽管试图排除故障,但网络故障仍持续了 9 个小时,导致呼叫连接故障率达到 50%。AT&T 因此损失了 6000...

codingpy的博客 170

java 内存数据网格_内存缓存与数据网格

内存缓存(in-memory cache)与数据网格IMGD当建立一个大型Java应用时,引起性能问题大部分是延迟,延迟是指请求和响应之间的时间差,在一个分布式Java系统中引起延迟的原因有:从磁盘上加装数据的IO延迟跨网络加装数据的IO延迟。在分布式锁上的资源争夺。垃圾回收引起的暂停。典型Ping时间是:本地机器是57μs;局域网是300 μs;从伦敦到纽约是100ms;对于1Gb网络,网络数据...

weixin_39936558的博客 365

转载   banq---阎宏之间的恩怨

我和banq之间的恩怨直到今日,让我感叹。 我们之间最早的摩擦开始于他的一篇关于Abstract Factory的网上文章,中间放了一张我在yesky.com的插图。他本人以免费刊载的方式鼓励转载,因此文章流传较广,出现在很多的网站,最后回到 yesky.com。而我对这个流传过程并不知道,第一次看到此文章就是在yesky.com,他的文章就在我的文章下面,而里面有我使用 Together画的...

218

转载   banq---阎宏之间的恩怨

我和banq之间的恩怨直到今日,让我感叹。 我们之间最早的摩擦开始于他的一篇关于Abstract Factory的网上文章,中间放了一张我在yesky.com的插图。他本人以免费刊载的方式鼓励转载,因此文章流传较广,出现在很多的网站,最后回到 yesky.com。而我对这个流传过程并不知道,第一次看到此文章就是在yesky.com,他的文章就在我的文章下面,而里面有我...

weixin_34259559的博客 214

Android数据库程序设计pdf

下载地址:网盘下载作者简介编辑Jason Wei 2011年毕业于斯坦福大学,在校期间他获得了数学计算科学专业的理学学士,同时辅修了统计学专业,接着获得了管理科学与工程专业的理学硕士,主要研究方向为机器学习。在大学期间的前两年里,他在硅谷进行第一次创业,而在他第二次创业(BillShrink公司)期间开始接触到Android系统。从那以后,他开发了一些应用...

weixin_30652271的博客 237
上一篇: 最权威的JDO新书《Java Data Objects》(不同于Robin Roos的那本)
下一篇: JDO对开发的帮助有哪些 - 实例解析
sun2bin
博客等级 码龄25年 1粉丝 15原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值