Sometimes, an application will be making a SPARQL query,
using the results from a previous query or using some RDF
term found through the other Jena APIs.
SQL has prepared statements - they allow an SQL statement to
take a number of parameters. The application fills in the
parameters and executes the statement.
One way is to resort to doing this in SPARQL by building
a complete, new query string, parsing it and executing it.
But it takes a little care to handle all cases like
quoting special characters; you can at least use some of the
many utilities in ARQ for producing strings such as
FmtUtils.stringForResource
(it's
not in the application API but in the util
package currently).
Queries in ARQ can be
built
programmatically but it is tedious, especially when the
documentation hasn't been written yet.
Another way is to use query variables and bind them to
initial values that apply to all query solutions. Consider
the query:
PREFIX dc <http://purl.org/dc/elements/1.1/>
SELECT ?doc { ?doc dc:title ?title }
It gets documents and their titles.
Executing a query in program
might
look like:
import com.hp.hpl.jena.query.* ;
Model model = ... ;
String queryString = StringUtils.join('\n',
new String[]{
'PREFIX dc <http://purl.org/dc/elements/1.1/>',
'SELECT ?doc { ?doc dc:title ?title }'
}) ;
Query query = QueryFactory.create(queryString) ;
QueryExecution qexec =
QueryExecutionFactory.create(query, model) ;
try {
ResultSet results = qexec.execSelect() ;
for ( ; results.hasNext() ; )
{
QuerySolution soln = results.nextSolution() ;
Literal l = soln.getLiteral('doc') ;
}
} finally { qexec.close() ; }
Suppose the application knows the title it's interesting
in - can it use this to get the document?
The value of ?title
made a parameter to the query
and fixed by an initial binding. All query solutions will
be restricted to patterns matches where ?title
is that RDF term.
QuerySolutionMap initialSettings = new QuerySolutionMap() ;
initialSettings.add('title', node) ;
and this is passed to the factory that creates QueryExecution's:
QueryExecution qexec =
QueryExecutionFactory.create(query,
model,
initialSettings) ;
It doesn't matter if the node is a literal, a resource with
URI or a blank node. It becomes a fixed value in the query, even
a blank node, because it's not part of the SPARQL syntax, it's a
fixed part of every solution.
This gives named parameters to queries enabling something
like SQL prepared statements except with named parameters not
positional ones.
This can make a complex application easier to structure and
clearer to read. It's better than bashing strings together,
which is error prone, inflexible, and does not
lead to clear code.