How to build SPARQL queries in java?

2019-03-09 13:25发布

问题:

Is there a library, which is able to build SPARQL queries programmatically like the CriteriaBuilder in JPA or to build the queries like with a PreparedStatement for SQL?

Similar (for SQL): Cleanest way to build an SQL string in Java

回答1:

You can build queries programmatically in Jena using two methods: syntax or algebra. There's an introduction in the jena wiki.

Using the algebra you'd do something like:

Op op;
BasicPattern pat = new BasicPattern();                 // Make a pattern
pat.add(pattern);                                      // Add our pattern match
op = new OpBGP(pat);                                   // Make a BGP from this pattern
op = OpFilter.filter(e, op);                           // Filter that pattern with our expression
op = new OpProject(op, Arrays.asList(Var.alloc("s"))); // Reduce to just ?s
Query q = OpAsQuery.asQuery(op);                       // Convert to a query
q.setQuerySelectType();                                // Make is a select query

(taken from the wiki page)

It's not CriteriaBuilder (nor was it intended to be), but is some of the way there. You OpJoin rather than AND, OpUnion when you want to OR, etc. The pain points are expressions in my experience: you probably want to parse them from a string.



回答2:

The recent versions of Jena have added a StringBuilder style API for building query/update strings and parameterizing them if desired.

This class is called ParameterizedSparqlString, here's an example of using it to create a query:

ParameterizedSparqlString queryStr = new ParameterizedSparqlString();
queryStr.setNSPrefix("sw", "http://skunkworks.example.com/redacted#");
queryStr.append("SELECT ?a ?b ?c ?d");
queryStr.append("{");
queryStr.append("   ?rawHit sw:key");
queryStr.appendNode(someKey);
queryStr.append(".");
queryStr.append("  ?rawHit sw:a ?a .");
queryStr.append("  ?rawHit sw:b ?b .");
queryStr.append("  ?rawHit sw:c ?c . ");
queryStr.append("  ?rawHit sw:d ?d .");
queryStr.append("} ORDER BY DESC(d)");

Query q = queryStr.asQuery();

Disclaimer - I'm the developer who contributed this functionality to Jena

See What's the best way to parametize SPARQL queries? for more discussion on doing this across various APIs.



回答3:

I implemented SPARQL Java - a kind of DSL for writing SPARQL queries in Java.

It solves the problem with IDE's auto formatting of concatenated SPARQL query strings and things like that.

As for example:

String shortQuery = Q.prefix("books", "http://example.org/books#")
            .select("?book ?authorName", new where() {
                {
                    $("?book books:author ?author");
                    $("?author books:authorName ?authorName");
                }
            }).get();


回答4:

I recently started to use Sesame query builder. It looks promising except it doesn't provide much documentation and I struggled to find examples. Here is simple sample which may help you to get started:

ParsedTupleQuery query = QueryBuilderFactory
            .select("pubProperty", "pubPropertyValue")
                .group()
                    .atom(cmResource(resourceId), LinkPublicationsTransformation.REFERENCE_URI, "pubUri")
                    .atom("pubUri", "pubProperty", "pubPropertyValue")
                    .filter(isLiteral("pubPropertyValue"))
                .closeGroup()
            .query();

Just note that isLiteral and cmResource are my own little static helper classes. isLiteral stands for new IsLiteral(new Var("...")) for example where the latter one create URI with my heavily used prefix.

You might be then also interested in SPARQLQueryRenderer which can turn ParsedQuery into String which may be convenient for further usage.

If you end up using String(Builder) approach what I discourage you to do have at least a look on RenderUtils from sesame-queryrendered which has all the convenient methods to add < > around URIs, escape special characters etc.



回答5:

The Sesame framework offers a Repository API which is somewhat similar to JDBC - it allows you to create a prepared Query object and inject variable bindings before executing it:

String query = "SELECT * WHERE {?X ?P ?Y }";
TupleQuery preparedQuery = conn.prepareQuery(QuerLanguage.SPARQL, query);
preparedQuery.setBinding("X", someValue);
...
TupleQueryResult result = preparedQuery.evaluate();


回答6:

Jena provides a QueryBuilder in the Extras package.

https://jena.apache.org/documentation/extras/querybuilder/index.html

It does what you want.



回答7:

You can use the Jena Semantic Framework (SPARQL documentation). Also take a look at this related question. Sadly, its syntax is closer to a SQL PreparedStatement than to the JPA.



回答8:

I have just released a beta project to do just this, called Spanqit.

I strove for readability and an intuitive interface, for example, here is some example Spanqit syntax for creating a query:

query.prefix(foaf).select(name)
    .where(x.has(foaf.iri("name"), name))
    .orderBy(name)
    .limit(5)
    .offset(10);

Check it out, and feel free to comment and suggest improvements!