zoukankan      html  css  js  c++  java
  • 导入本体到Jena TDB数据库

          本体的存储方法或称本体持久化,大致分为基于内存的方式、基于文件的方式、基于数据库的方式和专门的管理工具方式4种(傅柱等, 2013)。其中,基于数据库的方式又有基于关系数据库、基于面向对象数据库、基于Native XML数据库和基于NoSQL的三元组数据库(Triple Store)4种主要方式。基于数据库的本体持久化方式充分利用了数据库的安全可靠(数据保密、数据完整性、并发控制、故障恢复等)、高效、易于管理并易于与应用系统集成等优点,是主要的本体持久化方式。

          在本体中,数据被表示为一系列由主语(subject)、谓词(predicate)和宾语(object)组成的陈述(statement),即三元组(triple)的集合。基于关系数据库的本体持久化使用二维表对本体的三元组进行处理,不可避免地需要对本体中的复杂关系进行不自然的分解,而查询时又需要将基于图的查询转换为关系查询(傅柱等, 2013) ,需要进行大量的关联、连接操作,因而,现有基于关系数据库的本体存储方法都存在大规模存储、更新、修改和查询效率低、数据库操作代价大等问题(李勇和李跃龙, 2008)。因此,效率、性能更优越的专门或扩展了RDF存储、查询甚至推理能力的非关系型三元组数据库(Triple Store,或称图数据库),如GraphDB (OWLIM) [1]、Virtuoso Universal Server[2]、AllegroGraph[3]、Jena TDB(Triple DB)等(Rohloff et al., 2007)目前已逐渐成为本体存储主流工具。本文采用基于Jena TDB的方式。

      TDB存储的本体数据集由node表、Triple和Quad索引、prefixes表组成,存放在指定的文件系统目录下。TDB采用B+树维护三种基本形式的Triple索引:SPO、POS和OSP(S、P、O分别代表Subject、Predicate和Object)。若存在命名图(Named Graph),则同时维护相应的Quad索引(G表示Graph):GOSP、SPOG、GSPO、OSPG、GPOS和POSG。

          如上图所示,本体应用程序首先通过URI(Uniform Resource Identifier)地址映射文件实现本体URI与其对应的本体模块文件存放的文件系统地址的映射,然后使用自定义的Java类TDBPortal通过程序或配置文件读取各本体模块文件持久化到TDB。TDB中数据可通过TDBPortal实现增删改查操作,和进一步应用于本体查询与推理等操作;或作为SPARQL(SPARQL Protocol and RDF Query Language)服务器Jena Fuseki的数据源,对外提供基于HTTP的SPARQL查询服务。

         下面介绍TDBPortal
         
      1  package cn.geodata.ont.tdb;
      2  
      3  import java.util.ArrayList;
      4  import java.util.Iterator;
      5  import java.util.List;
      6  
      7  import org.apache.commons.lang3.StringUtils;
      8  import org.apache.jena.riot.RDFDataMgr;
      9  import org.slf4j.Logger;
     10  import org.slf4j.LoggerFactory;
     11  
     12  import cn.geodata.ont.file.OntFile;
     13  
     14  import com.hp.hpl.jena.ontology.OntModel;
     15  import com.hp.hpl.jena.query.Dataset;
     16  import com.hp.hpl.jena.query.ReadWrite;
     17  import com.hp.hpl.jena.rdf.model.Model;
     18  import com.hp.hpl.jena.rdf.model.ModelFactory;
     19  import com.hp.hpl.jena.tdb.TDBFactory;
     20  import com.hp.hpl.jena.tdb.base.file.Location;
     21  
     22  /**
     23   * @TODO TDB CRUD操作,包含事务
     24   * @author Zhiwei HOU
     25   * @date 2015年12月2日
     26   */
     27  public class TDBPortal
     28  {
     29      final static Logger logger = LoggerFactory.getLogger(TDBPortal.class);
     30  
     31      // 必须close
     32      Dataset ds = null;
     33     
     34      /**
     35       * 连接TDB
     36       * 
     37       * @param tdbPath TDB目录或配置文件tdb-assembler.ttl路径. tdbPath可以通过配置文件进行设置
     38       * @param useAssemblerFile 是否使用配置文件连接
     39       */
     40      public TDBPortal(String tdbPath, boolean useAssemblerFile)
     41      {
     42          if (!useAssemblerFile)
     43          {
     44              Location location = Location.create(tdbPath);
     45              ds = TDBFactory.createDataset(location);
     46          }
     47          else
     48              ds = TDBFactory.assembleDataset(tdbPath);
     49      }
     50  
     51      public TDBPortal(String tdbPath)
     52      {
     53          Location location = Location.create(tdbPath);
     54          ds = TDBFactory.createDataset(location);
     55      }
     56  
     57      /**
     58      * 往模型中添加内容。不载入引用本体
     59      * 
     60      * @param modelUri 本体的uri
     61      * @param sourcePath  本体文件实际地址
     62      * @param override 是否覆盖
     63      * @return
     64      * @Houzw at 2016年4月1日下午11:36:13
     65      */
     66      public int loadModel(String modelUri, String sourcePath, Boolean isOverride)
     67      {
     68          Model model = null;
     69          ds.begin(ReadWrite.WRITE);
     70          try
     71          {
     72              if (ds.containsNamedModel(modelUri))
     73              {
     74                  if (isOverride)// 覆盖
     75                  {
     76                      removeModel(modelUri);//只是移除地址,实际数据不会移除
     77                      loadModel(modelUri, sourcePath, false);
     78                  }
     79              }
     80              else
     81              {
     82                  model = ds.getNamedModel(modelUri);// 没有则创建一个,model不会为null
     83                  model.begin();
     84                  RDFDataMgr.read(model, sourcePath);
     85                  model.commit();
     86              }
     87              // 已有,但是不覆盖,则直接返回
     88              ds.commit();
     89              logger.info("本体模型数据已经导入");
     90              return 1;
     91          }
     92          catch (Exception e)
     93          {
     94              return 0;
     95          }
     96          finally
     97          {
     98              if (model != null)
     99                  model.close();
    100              ds.end();
    101          }
    102      }
    103  
    104      /**
    105      * 导入本体。OntModel不支持事务。同时载入引用本体
    106      * 
    107      * @param modelUri 模型uri
    108      * @param sourcePath 本体文件(集成文件)地址
    109      * @param override 是否覆盖
    110      * @return
    111      * @Houzw at 2016年4月1日下午11:36:09
    112      */
    113      public int loadOntModel(String modelUri, String sourcePath, Boolean isOverride)
    114      {
    115          OntModel model = ModelFactory.createOntologyModel();// 不支持事务
    116          ds.begin(ReadWrite.WRITE);
    117          try
    118          {
    119              if (ds.containsNamedModel(modelUri))
    120              {
    121                  if (isOverride)// 覆盖
    122                  {
    123                      removeModel(modelUri);
    124                      loadOntModel(modelUri, sourcePath, false);
    125                  }
    126              }
    127              else
    128              {
    129                  model = OntFile.loadOntModelWithLocMapper(sourcePath);//导入本体文件
    130                  ds.addNamedModel(modelUri, model);
    131  
    132              }
    133              // 已有,但是不覆盖,则直接返回
    134              ds.commit();
    135              System.out.println(modelUri + " 已导入");
    136              logger.info(modelUri + " 已导入");
    137              return 1;
    138          }
    139          catch (Exception e)
    140          {
    141              System.out.println(e.getLocalizedMessage());
    142              logger.error(e.getLocalizedMessage());
    143              return 0;
    144          }
    145          finally
    146          {
    147              ds.end();
    148          }
    149      }
    150  
    151     
    152      public Model getDefaultModel()
    153      {
    154          ds.begin(ReadWrite.READ);
    155          Model model;
    156          try
    157          {
    158              model = ds.getDefaultModel();
    159              ds.commit();
    160          }
    161          finally
    162          {
    163              ds.end();
    164          }
    165          return model;
    166      }
    167  
    168      /**
    169       * 获取指定模型
    170       */
    171      public Model getModel(String modelUri)
    172      {
    173          Model model = null;
    174          ds.begin(ReadWrite.READ);
    175          try
    176          {
    177              model = ds.getNamedModel(modelUri);
    178          }
    179          finally
    180          {
    181              ds.end();
    182          }
    183          return model;
    184      }
    185  
    186      
    187      public void loadDefaultModel(String sourcePath)
    188      {
    189          Model model = null;
    190          ds.begin(ReadWrite.WRITE);
    191          try
    192          {
    193              model = ds.getDefaultModel();
    194              model.begin();
    195              if (!StringUtils.isBlank(sourcePath))
    196                  RDFDataMgr.read(model, sourcePath);
    197              model.commit();
    198              ds.commit();
    199          }
    200          finally
    201          {
    202              if (model != null)
    203                  model.close();
    204              ds.end();
    205          }
    206      }
    207  
    208      
    209      public void removeModel(String modelUri)
    210      {
    211          if (!ds.isInTransaction())
    212              ds.begin(ReadWrite.WRITE);
    213          try
    214          {
    215              ds.removeNamedModel(modelUri);
    216              ds.commit();
    217              System.out.println(modelUri + " 已被移除");
    218              logger.info(modelUri + " 已被移除");
    219          }
    220          finally
    221          {
    222              ds.end();
    223          }
    224      }
    225  
    226      /**
    227       * 列出所有模型的uri
    228       */
    229      public List<String> listModels()
    230      {
    231          ds.begin(ReadWrite.READ);
    232          List<String> uriList = new ArrayList<>();
    233          try
    234          {
    235              Iterator<String> names = ds.listNames();// DefaultModel没有name
    236              String name = null;
    237              while (names.hasNext())
    238              {
    239                  name = names.next();
    240                  uriList.add(name);
    241              }
    242          }
    243          finally
    244          {
    245              ds.end();
    246          }
    247          return uriList;
    248      }
    249  
    250      /**
    251       * 必须关闭TDB连接
    252       */
    253      
    254      public void close()
    255      {
    256          ds.close();
    257      }
    258  }

     以上简单介绍了基于Jena TDB的本体存储。目前我对AssemblerFile配置文件的配置还没有深入的研究,了解的朋友可以告诉我,O(∩_∩)O谢谢

     ——————————————————————————————————————

    补充:

    TDB 也提供了命令行的方式导入本体数据,具体参考官方文档或参考http://blog.csdn.net/rk2900/article/details/38342181

    水平有限,错误难免,多指教。TDB 的具体内容可查阅其官方文档


    [1] http://ontotext.com/products/graphdb/

    [2] http://www.openlinksw.com/

    [3] http://franz.com/

  • 相关阅读:
    栈解旋(unwinding)
    自定义异常
    异常的基本使用
    什么是跨域?
    Vue-Vue-router跳转页面时返回顶部
    jquery&vue backTop缓慢返回顶部的方法应用
    Windows 10下使用U盘安装Ubuntu双系统
    Windows下磁盘分配操作
    在双系统(Windows与Ubuntu)下删除Ubuntu启动项
    .net framework体系结构
  • 原文地址:https://www.cnblogs.com/yes-V-can/p/5526096.html
Copyright © 2011-2022 走看看