- Quick Intro to JDO
- The Problem at Hand
- Persisting the Objects
- Retrieving the Objects
- The Wrap-Up
The Problem at Hand
We'll develop an application that extracts quoted text out of electronic books, grouping quotes by source and allowing a user to retrieve the quotes with searches. As this article is about JDO and not file I/O, we won't focus too much on the bits of the application that pull the quotes from the files, but the app iterates over a set of text files in a directory, pulls the title from the first line of the file, and then pulls out any block of text wrapped in quotation marks, or three quotation marks and a paragraph boundary.
First we'll need a class that represents the source of the quote, as shown in Listing 1.
Listing 1 QuoteSource
public class QuoteSource { private String name = ""; private File sourceFile = null; public QuoteSource(String name, File sourceFile) { setName(name); setSourceFile(sourceFile); } public String getName() { return name; } protected void setName(String in) { name = in; } public File getSourceFile() { return sourceFile; } public void setSourceFile(File in) { sourceFile = in; } public String toString() { return name + "(" + sourceFile + ")"; } }
We also need to represent the quotes themselves, including the quote's source and line within the file (see Listing 2).
Listing 2 QuoteInfo
public class QuoteInfo { String quote = ""; BigInteger lineNumber = null; QuoteSource source = null; public QuoteInfo(QuoteSource source, String quote, BigInteger lineNumber) { setSource(source); setQuote(quote); setLineNumber(lineNumber); } public boolean equals(Object o) { QuoteInfo compare = null; if(!(o instanceof QuoteInfo)) return false; compare = (QuoteInfo)o; return(compare.getLineNumber().equals(getLineNumber()) && compare.getSource().equals(getSource()) && compare.getQuote().equals(getQuote())); } public boolean matches(String test) { return (getQuote().toLowerCase().indexOf(test.toLowerCase()) != -1); } public BigInteger getLineNumber() { return lineNumber; } protected void setLineNumber(BigInteger in) { lineNumber = in; } public String getQuote() { return quote; } public void setQuote(String in) { quote = in; } public QuoteSource getSource() { return source; } public void setSource(QuoteSource in) { source = in; } }
It's worth pointing out that no JDO-related code is needed here. The compiled classes will need to be enhanced, which we'll see in a moment. First, however, let's generate the database schema to store these classes, which JDO Genie Workbench will do automatically (see Figure 1).
Figure 1 A look at JDO Genie's automatically generated table-creation scripts.
As Figure 1 shows, we're specifying cached tables, telling HSQLDB to store the table data in files. That doesn't mean that we won't have any data in memory, but the bulk of it should stay on disk and out of RAM.
Once the JDO Genie project file has been generated from Workbench, we need to use it to enhance the classes that we want to persist via JDO. The easiest way to do this is through ANT. This is the task we'll use to compile our classes:
<target name="compile" depends="init"> <dependset> <srcfileset dir="${src}" includes="**/*.jdo"/> <targetfileset dir="${build.classes}" includes="**/*.class"/> </dependset> <javac srcdir="${src}" destdir="${build.classes}" classpathref="cp" debug="true"/> <jdo-enhance project="${jdo.project}" outputdir="${build.classes}"> <persistentaware dir="${build.classes}" /> </jdo-enhance> </target>
The jdo-enhance task takes a reference to the JDO Genie project file from Workbench, an input directory containing the classes to enhance, and an output directory for the enhanced classes (same as input in this case). Once the classes have been enhanced, we can persist and retrieve them through JDO. But first we need to add the code to do so to our main application.