Java 应用程序开箱即用的对象持久性

Sami Salkosuo (sami.salkosuo@fi.ibm.com), 软件架构师, IBM

2007 年 3 月 12 日

    Simple Persistence for Java 是一个开源的对象关系型持久性库,它使用定制查询语言以及内建数据库支持来简化 Java 应用程序中的对象持久性。在本文中,软件架构师 Sami Salkosuo 介绍了该库,并带您领略解决对象持久性的零管理以及零配置方法。

    对象持久性几乎是所有 Java™ 应用程序(从桌面应用程序到企业级应用程序)中的必备。持久性的缺点是它一直都不太简单。但这一情况已在最近一版的 Simple Persistence for Java(一个开源的对象关系型持久性库)中有所改变。

    Simple Persistence for Java 2.1.0 版添加了对 HSQLDB 的支持,HSQLDB 是一个纯 Java 数据库。Simple Persistence for Java 和 HSQLDB 都不需要应用程序用户进行管理和配置。考虑以上因素,这些工具让您能够花相当少的力气就将持久性引入到应用程序中。

    本文向您介绍 Simple Persistence for Java v2.1.0,并展示了如何几乎不费力气地使用该库以在 Java 应用程序中获得对象持久性。

Simple Persistence for Java

    Simple Persistence for Java 是一个在 LGPL 许可下的开源库,由 Hungarian company NetMind Consulting 公司内部开发并发布到开源社区。

    Java 开发人员有许多对象关系型库可用。Simple Persistence for Java 与其他库的不同之处是它零配置即可使用。此库的一个主要设计原则是:无需配置配置文件、XML 映射文件和属性(当然,您要有一个合适的数据库)。

Simple Persistence for Java 库还有以下一些重要特征:

  • 小的存储空间(135KB)
  • 简单的 API
  • 支持多个数据库
  • 简单查询语言
  • 多态性
  • 惰性结果列表

    在 2.1.0 版中,Simple Persistence for Java 库添加了对 HSQLDB 数据库的支持。HSQLDB 是一个开源的、轻量级的纯 Java SQL 数据库引擎,它由一个 BSD 风格的许可协议授权。HSQLDB 支持 ANSI-92 SQL 的富子集,也支持 SQL 99 和 2003 增强版。它提供基于内存和基于磁盘的表,并支持内嵌式操作模式和服务器操作模式。

StockData 应用程序

    我将用一个叫做 StockData 的样例程序向您展示通过 Simple Persistence for Java 库和 HSQLDB 来获得对象持久性是多么简单。StockData 基于用户查询过滤历史证券数据(在一个 CSV 文件中)。该程序和一个内嵌式数据库一起操作,且从命令行中运行。

    为继续讨论,您需要重建类似我这样的开发环境并建立样例应用程序。StockData 的开发环境为 Eclipse 3.2.1,最低的 Java 版本是 JDK 1.5.0。我使用了基于内存的数据库选项在内嵌模式下开启了 HSQLDB 数据库。请注意,我可以选一个基于磁盘的内嵌式数据库或服务器端数据库,但出于演示的目的,我选了 HSQLDB 基于内存的数据库。

需要下列库来执行 StockData 样例程序:

  • commons-io-1.2.jar
  • commons-logging-api.jar
  • commons-logging.jar
  • hsqldb.jar
  • java-cup-11-runtime.jar
  • log4j-1.2.8.jar
  • netmind-persistence-2.1.0.jar

    StockData 程序使用 commons-io 包和 commons-logging 包,HQSLSB 并不依赖于任何 jar 文件。netmind-persistence-2.1.0.jar 依赖于 java-cup-11-runtime.jar 和 log4j-1.2.8.jar。 

样例源代码

清单 1 展示了 StockData 程序的源代码:


清单 1. StockData

				
public class StockData
{
  private static Log log;
  public static void main(String[] args)
  {
    System.setProperty("log4j.configuration", "file:log4j.properties");
    log = LogFactory.getLog(StockData.class);
    try
    {
      String symbol = args[0];
      String csvFile = args[1];
      String query = args[2];
      // open store, uses HSQLDB driver and memory only database
      Store store = new Store("org.hsqldb.jdbcDriver","jdbc:hsqldb:mem:stockdata");
      // read csv and generate beans
      List historicalData = FileUtils.readLines(new File(csvFile), "UTF-8");
      // remove first line (header)
      historicalData.remove(0);
      // store beans to database
      for (Object _data : historicalData)
      {
        String[] data = ((String) _data).split(",");
        StockBean bean = new StockBean(symbol, data[0],
            Double.parseDouble(data[4]), Double.parseDouble(data[5]));
        //save stock bean to database
        store.save(bean);
      }
      // find beans that match query
      List results=store.find(query);
      // print beans that matched
      System.out.println("Total results: "+results.size());
      for (Object object : results)
      {
        StockBean bean=(StockBean)object;
        System.out.println(bean.toString());
      }
    }
    catch (Exception e)
    {
      log.error(e.getMessage(), e);
      System.out
          .println("Usage: java sample.StockData " +
              "<symbol name> <historical prices file> <query>");
    }
  }
}

    StockData 应用程序使用 Apache Commons IO 包将 CSV 文件读入 List。然后,for 循环解析文本行并创建 StockBean 对象,该对象被存入数据库中。CSV 文件的格式如下:

Date,Open,High,Low,Close,Volume,Adj. Close*
29-Dec-06,97.00,97.88,96.83,97.15,4455900,97.15
28-Dec-06,97.11,97.40,96.87,96.97,4501700,96.97
27-Dec-06,96.30,97.23,96.27,97.20,4571600,97.20

可下载演示包 中提供了一个样例 CSV 文件。

    将所有对象存入数据库后,会执行一个简单的 find 查询(在命令行中指定)并返回一份相匹配结果的 List。结果打印到 System.out。请注意,Simple Persistence for Java 实现 LazyList,对象可在 LazyList 中随需检索。这确保了内存中最终不会出现成千上万的对象。

StockBean 对象

    清单 2 展示了 StockBean Java 对象的源代码,该代码用于存储 StockData 中的信息。StockBean 有四个字段:symbol name、date、price 和 volume。


清单 2. StockBean 对象

				
public class StockBean
{
  private String symbolName = "";
  private String date = null;
  private double price = 0.0;
  private double volume = 0.0;
  public StockBean()
  {
    // no-argument constructor required by Simple Persistence
  }
  public String toString()
  {
    StringBuffer sb=new StringBuffer();
    sb.append(symbolName);
    sb.append(',');
    sb.append(date);
    sb.append(',');
    sb.append(price);
    sb.append(',');
    sb.append(volume);
    return sb.toString();
  }
  public StockBean(String symbolName, String date, double price, double volume)
  {
    this.symbolName = symbolName;
    this.date = date;
    this.price = price;
    this.volume = volume;
  }
  public String getDate()
  {
    return date;
  }
  public void setDate(String date)
  {
    this.date = date;
  }
  public double getPrice()
  {
    return price;
  }
  public void setPrice(double price)
  {
    this.price = price;
  }
  public String getSymbolName()
  {
    return symbolName;
  }
  public void setSymbolName(String symbolName)
  {
    this.symbolName = symbolName;
  }
  public double getVolume()
  {
    return volume;
  }
  public void setVolume(double volume)
  {
    this.volume = volume;
  }
}

 

简单元素

    正如能在 清单 1 的 StockData 源码中看到的那样,Simple Persistence for Java 真正简化了对象关系型持久性。基本上只需三行代码就可将持久性添加到您的 Java 应用程序中并从 HSQLDB 中检索对象:

  • Store 对象构造函数。
  • 将对象保存到数据库的 save() 方法。
  • 用于检索对象的一个或多个 find() 方法。

构造函数十分简单;只需将 JDBC 驱动作为第一个参数,将 JDBC URL 作为第二个参数:

Store store = new Store("org.hsqldb.jdbcDriver","jdbc:hsqldb:mem:stockdata");

稍后,Store 对象将用于存储及检索对象。

将对象保存到数据库中也很直接:

StockBean bean = new StockBean(symbol, date, price, volume);
store.save(bean);

只需调用 save() 将对象存储到数据库。任何必要的表都会在幕后创建。

使用用于检索对象的查询语言来查找对象也相当简单:

List results=store.find(query);

有四种不同的 find() 方法:

  • find(String statement)
  • find(String statement, Object[] parameters)
  • findSingle(String statement)
  • findSingle(String statement, Object[] parameters)

带参数的 find() 方法与在 SQL 中时一样:“?” 是参数对象的占位符。findSingle() 方法是自解释的。

定制查询语言

    到现在,您也许注意到了一件事,Simple Persistence for Java 使用定制查询语言来查找对象。查询语法是面向对象的,并且没有了表、索引或其他典型的对象关系型数据库的概念。例如,下列查询在一个 List 中返回所有 StockBean 对象:

find stockbean

    由于作为结果的 List 是惰性的,因而可以不影响应用程序性能或内存消耗即可查询大量对象。所以,即使实际对象是随需检索的,getSize() 方法也会返回一个结果的总数。

查询语法

Simple Persistence for Java 查询由 “find” 开始,第二个元素是要检索的类名。只有当许多类重名但所处包不同时才需要一个完整类名。

Where 子句与在 SQL 中的那些类似。典型的操作符,如 “or”、“and”、“not”、“<”、“>”、“=”、“like” 等等也得到了支持。

下列查询会返回其值介于 USD90 和 USD92.5 之间的所有 StockBean 对象:

find stockbean where price>90 and price6lt;'92.5' and symbolname='IBM'

注意,表示整型值可以不用引号,但双精度值和字符串值则需要引号。

也可以使用 SQL 中常见的 “order by” 语法来对结果进行排序。例如,下列命令指定结果按价格降序排列:

find stockbean where price>90 and price<'92.5' and symbolname='IBM' order by price desc

运行样例

StockData 程序在一个 CSV 文件中搜索证券数据。可下载包 包含编译过的源代码和一个叫做 stockdata.bat 的批处理文件。该程序的语法是 stockdata.bat <symbol name> <csv file name> <find query>。可以使用此语法自己来查询样例应用程序。

下列命令的结果

stockdata.bat IBM ibm_2006.csv "find stockbean where price>90 and price6lt;'92.5' and symbolname='IBM'"

如图 1 所示:


图 1. 查询 StockData 应用程序的输出
查询 StockData 的输出 

 

额外功能

    StockData 应用程序演示了 Simple Persistence for Java 的基本功能。除此之外, Simple Persistence for Java 库还有一些 StockData 未表现出来的更高级的功能,包括多态性和用户管理事务。

多态性

在 Simple Persistence for Java 中,想要存储到数据库中的 JavaBean 能够从类中扩展。例如:

public class StockBeanExt extends StockBean
{
  private int totalTrades=0;
  public StockBeanExt()
  {
    // no-argument constructor required by Simple Persistence
  }
  public int getTotalTrades()
  {
    return totalTrades;
  }
  public void setTotalTrades(int totalTrades)
  {
    this.totalTrades=totalTrades;
  }
}

    保存了多个 StockBean 和 StockBeanExt 对象后,目标字段处于 StockBean 类的查询会返回 StockBean 和 StockBeanExt 对象。

用户管理事务

Simple Persistence for Java 库也支持用户管理事务,允许指定事务何时开始,何时执行。以下列事务为例:

Transaction tx = tt.getTransaction(TransactionTracker.TX_REQUIRED);
tx.begin();
try
{
   ...operations...
} catch ( ... ) {
   ... handling code...
   tx.markRollbackOnly();
} finally {
   tx.commit();
}

注意 finally 子句是如何包含 commit 的。这行命令总在执行,即使出现异常也是一样。在 catch() 子句中,markRollbackOnly() 方法指示 commit() 何时被调用,它实际上会用回滚代替提交。

参见 参考资料 了解更多信息和 Simple Persistence for Java v2.1.0 库的其他功能。

结束语

在本文中,我介绍了 Simple Persistence for Java v2.1.0 库,解释了它的基本功能及组件。我还使用该库的定制查询语言和 HSQLDB 数据库演示了一个简单的对象持久性场景,也探讨了该库的一些高级功能。

我发现:Simple Persistence for Java 库简单的 API 和零配置方法极大地简化了对象关系型持久性。如果您需要持久性(尤其是在小的实用项目中)但又想避免编写 SQL、使用持久性框架或在计算机上安装一个独立的数据库,那么,使用带 HSQLDB 数据库的 Simple Persistence for Java v2.1.0 就是一个不错的选择。

参考资料

学习

  • 您可以参阅本文在 developerWorks 全球站点上的 英文原文

  • 轻量级开发的成功秘诀,第 6 部分: 持久性策略” (Bruce Tate,developerWorks,2005 年 9 月):关于 Java 持久性框架和策略的一个较早却仍有价值的概览。

  • 使用 Apache Derby 和 iBATIS 提高持久性” (Daniel Wintschel,developerWorks,2006 年 1 月):对 iBatis 和 Apache Derby(另一个 Java 应用程序中对象持久性的一流组合)的教程式介绍。

  • 不要重复 DAO!” (Per Mellqvist,developerWorks,2006 年 5 月):描述使用 Java 5 泛型解决对象持久性问题的一种更为面向配置的、更为类型安全的方法。

  • 使用 EJB 3.0 Java Persistence API 设计企业应用程序” (Borys Burnayev,developerWorks,2006 年 3 月):介绍了针对 EJB 3.0 的 Java 持久性 API。

  • LGPL:GNU Lesser General Public License 是一个由自由软件基金会发布的免费软件许可协议。

  • BSD 协议:Berkeley Software Distribution 的原始许可协议,现在进行了修订并具有许多分支协议。


获得产品和技术


讨论



 

关于作者

Sami Salkosuo 从 1999 年起一直在 IBM 工作。他的主要兴趣领域是 Java 编程,是 Sun 认证的 Java 程序员,IBM 认证的 XML 和相关技术解决方案开发人员,IBM 认证的 IBM WebSphere Portal 解决方案开发人员。除了 Java 技术,他还有 Python、Fortran、LabVIEW、Visual Basic、LISP、Perl 和 PHP 的经验。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值