자바에서 스파클 사용하기 ARQ - Application API

     




자바에서 jena API를 통해 sparql query를 사용해 보겠습니다.


공식 홈페이지 튜토리얼 주소 : http://jena.apache.org/documentation/query/app_api.html


ARQ - Application API


자바에서 스파클 관련 패키지는 com.hp.hpl.jena.query입니다. 다른 패키지도 있지만 일반적인 프로그램에서는 메인 패키지만 있어도 충분합니다.


Key Classes


  • Query - 쿼리문을 표현하는 클래스입니다. Query 클래스의 객체는 QueryFactory 메소드를 통해 만들어집니다.
  • QueryExecution - 쿼리의 실행을 표현합니다.
  • QueryExcutionFactory - QuertyExecution 객체를 얻기위한 클래스입니다.
  • DatasetFactory - DataSource를 포함한 dataset을 만드는 클래스입니다.
  • SELECT 쿼리에서는 : QuerySolution - 쿼리에대한 하나의 값을 표현합니다
                                    ResultSet - 모든 쿼리에대한 값을 표현합니다. iteratior값입니다.
                                    ResultSetFormatter - ResultSet의 값을 다른 값으로 변형시킵니다. (text,                                 RDF graph, XML)
SELECT queries

기본적인 SELECT 쿼리를 만드는 java코드입니다.


  import com.hp.hpl.jena.query.* ;
  Model model = ... ;
  String queryString = " .... " ;
  Query query = QueryFactory.create(queryString) ;
  QueryExecution qexec = QueryExecutionFactory.create(query, model) ;
  try {
    ResultSet results = qexec.execSelect() ;
    for ( ; results.hasNext() ; )
    {
      QuerySolution soln = results.nextSolution() ;
      RDFNode x = soln.get("varName") ;       // Get a result variable by name.
      Resource r = soln.getResource("VarR") ; // Get a result variable - must be a resource
      Literal l = soln.getLiteral("VarL") ;   // Get a result variable - must be a literal
    }
  } finally { qexec.close() ; }


예제로 나온거라 뭔지 잘 모르겠지요? 

이전 포스팅에서 명령 프롬프트를 통해 실행해본 예제를 직접 자바코드로 옮겼습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.ontology.OntModelSpec;
import com.hp.hpl.jena.query.Query;
import com.hp.hpl.jena.query.QueryExecution;
import com.hp.hpl.jena.query.QueryExecutionFactory;
import com.hp.hpl.jena.query.QueryFactory;
import com.hp.hpl.jena.query.QuerySolution;
import com.hp.hpl.jena.query.ResultSet;
import com.hp.hpl.jena.rdf.model.Literal;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.Resource;
 
 
public class Main {
    
    public static void main(String[] args){
            OntModelSpec oms= new OntModelSpec(OntModelSpec.OWL_MEM_RULE_INF);
 
        OntModel m =  ModelFactory.createOntologyModel( oms, null );
        
        m.read("file:C:/Users/Cho/Desktop/eclipse/jena-2.6.4/Jena-2.6.4/doc/tutorial/vc-db-1.rdf");
    
        String queryString = "SELECT ?x ?fname WHERE {?x  " +
                "<http://www.w3.org/2001/vcard-rdf/3.0#FN>  ?fname}";
        Query query = QueryFactory.create(queryString);
        QueryExecution qexec = QueryExecutionFactory.create(query,m);
        try{
            ResultSet results = qexec.execSelect();
            for(;results.hasNext();){
                QuerySolution soln = results.nextSolution();
                RDFNode x = soln.get("x");
                Resource r = soln.getResource("x");
                Literal l = soln.getLiteral("fname");
                System.out.println("result "+x+"  " + r+ "  "+l);
            }
        }finally{
            qexec.close();
        }
        
    
    }
}
 


SELECT ?x ?fname
WHERE {?x  <http://www.w3.org/2001/vcard-rdf/3.0#FN>  ?fname}

이전 포스팅 바로가기


코드를 분석하면 일단 모델을 만듭니다. 모델에 대한 파일은 4명의 Vcard가 기록되어있는 vc-db-1.rdf입니다. 쿼리는 리소스인 ?x와 value인 ?fname입니다. 쿼리는 queryString이라는 문자열변수 안에 입력하였고 실질적으로 쿼리를 실행하는 부분은 

QueryExecution qexec = QueryExecutionFactory.create(query,m); 입니다.


쿼리를 실행한 결과값은 ResultSet 클래스를 통해 받고, for문을 통해 출력합니다. 이 예제에서는 값을 가져오는 클래스를 3가지를 표시했는데 RDFNode, Resoruce, Literal입니다. 각각의 차이점은 RDFNode의 경우 입력받은 값이 Resoruce타입이면 Resoruce타입으로 읽고, Literal타입이면 Literal타입으로 읽습니다. 즉 입력받는 값에 따라 자동으로 맞춰줍니다. Resource의 경우에는 무조건 Resource인 자료형만 받을 수 있고, Literal의 경우도 Literal형태의 자료만 받을 수 있습니다.


위 코드의 출력은 다음과 같습니다.


1
2
3
4
result http://somewhere/MattJones/  http://somewhere/MattJones/  Matt Jones
result http://somewhere/SarahJones/  http://somewhere/SarahJones/  Sarah Jones
result http://somewhere/RebeccaSmith/  http://somewhere/RebeccaSmith/  Becky Smith
result http://somewhere/JohnSmith/  http://somewhere/JohnSmith/  John Smith



위와같이 for문을 사용해서 일일이 출력하는 방법도 있지만 (아마 대부분의 프로그램에서 사용할 것 같지만) 단순한 출력을 원하는 경우에는 간단한 코드로 출력을 할 수 있습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.ontology.OntModelSpec;
import com.hp.hpl.jena.query.Query;
import com.hp.hpl.jena.query.QueryExecution;
import com.hp.hpl.jena.query.QueryExecutionFactory;
import com.hp.hpl.jena.query.QueryFactory;
import com.hp.hpl.jena.query.ResultSet;
import com.hp.hpl.jena.query.ResultSetFormatter;
import com.hp.hpl.jena.rdf.model.ModelFactory;
 
 
public class Main {
    
    public static void main(String[] args){
            OntModelSpec oms= new OntModelSpec(OntModelSpec.OWL_MEM_RULE_INF);
 
        OntModel m =  ModelFactory.createOntologyModel( oms, null );
        
        m.read("file:C:/Users/Cho/Desktop/eclipse/jena-2.6.4/Jena-2.6.4/doc/tutorial/vc-db-1.rdf");
    
        String queryString = "SELECT ?x ?fname WHERE {?x  " +
                "<http://www.w3.org/2001/vcard-rdf/3.0#FN>  ?fname}";
        Query query = QueryFactory.create(queryString);
        QueryExecution qexec = QueryExecutionFactory.create(query,m);
        try{
            ResultSet results = qexec.execSelect();
            ResultSetFormatter.out(System.out,results,query);
            /*
            for(;results.hasNext();){
                QuerySolution soln = results.nextSolution();
                RDFNode x = soln.get("x");
                Resource r = soln.getResource("x");
                Literal l = soln.getLiteral("fname");
                System.out.println("result "+x+"  " + r+ "  "+l);
            }
            */
        }finally{
            qexec.close();
        }
        
    
    }
}


ResultSetFormatter클래스를 사용하여 깔끔하게 출력을 할 수 있습니다.



이전 포스팅에서 쿼리문은 SELECT말고도 다른 종류가 있다고 말했습니다. 다른 쿼리문은 단순한 결과가 아닌 다양한 값을 반환하기 때문에 반환값을 다루는 방법이 조금씩 다릅니다.


CONSTRUCT, DESCRIBE의 경우에는 모델자체를 반환하기 때문에 쿼리의 결과가 모델로 받아집니다.

Query query = QueryFactory.create(queryString) ;
QueryExecution qexec = QueryExecutionFactory.create(query, model) ;
Model resultModel = qexec.execConstruct() ;
qexec.close() ;


ASK의 경우 boolean값으로 결과값을 받습니다.

Query query = QueryFactory.create(queryString) ;
QueryExecution qexec = QueryExecutionFactory.create(query, model) ;
boolean result = qexec.execAsk() ;
qexec.close() ;



Datesets을 활용한 코드는 다음과 같습니다.


String dftGraphURI = "file:default-graph.ttl" ;
List namedGraphURIs = new ArrayList() ;
namedGraphURIs.add("file:named-1.ttl") ;
namedGraphURIs.add("file:named-2.ttl") ;

Query query = QueryFactory.create(queryString) ;

Dataset dataset = DatasetFactory.create(dftGraphURI, namedGraphURIs) ;
QueryExecution qExec = QueryExecutionFactory.create(query, dataset) ;
try { ... }
finally { qExec.close() ; }


모델 대신 dataset이 들어간거 빼고는 특별한 점이 없습니다.

반응형

댓글

Designed by JB FACTORY