设为首页 收藏本站
查看: 1037|回复: 0

[经验分享] Jena API使用详解(关注将本体持久化到MySQL后的操作及解决中文乱码等问题)

[复制链接]

尚未签到

发表于 2016-10-24 04:36:27 | 显示全部楼层 |阅读模式


关于Jena的简介在很多博客中都能看到,例如对Jena的简单理解和一个例子,使用Jena将本体存入MySQL,Jena进阶等。在入门的时候,看这些文章总是很疑惑,对于存入数据库后的操作一无所知。因此,在做毕设之余,把使用到的一些方法记录下来,供将来查阅。将本体持久化到数据库

首先,还是不能免俗,说说如何将本体持久化到数据库的方法。总体的操作流程是将本体从owl文件中读出,建立一个数据库的连接,将Model存入数据库。这个过程的操作比较简单,见如下代码。


private final static String driver = "com.mysql.jdbc.Driver";
private final static String url = "jdbc:mysql://localhost/dbname";
private final static String db = "MySQL";
private final static String user = "your user name";
private final static String pwd = "your password";
/**
* @param args
*/
public static void main(String[] args) {
try {
IDBConnection con = getConnection(url, user, pwd, db);
Class.forName(driver);
String path = "your owl file path";
createModel(con, "model name", path);
con.close();
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* get db connection
*
* @param dbUrl
* @param dbUser
* @param dbPwd
* @param dbName
* @return
*/
public static DBConnection getConnection(String dbUrl, String dbUser,
String dbPwd, String dbName) {
return new DBConnection(dbUrl, dbUser, dbPwd, dbName);
}
/**
* read owl file, create the ontModel, and store in db
*
* @param conn
* @param name
* @param filePath
* @return
*/
public static OntModel createModel(IDBConnection conn, String name,
String filePath) {
ModelMaker maker = ModelFactory.createModelRDBMaker(conn);
Model model = maker.createModel(name);
try {
File file = new File(filePath);
FileInputStream fis = new FileInputStream(file);
InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
model.read(isr, null);
isr.close();
fis.close();
model.commit();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
OntModelSpec spec = new OntModelSpec(OntModelSpec.OWL_MEM);
return ModelFactory.createOntologyModel(spec, model);
}执行了上面的代码,会发现在MySQL数据库中可以看见七张表。  

DSC0000.jpg

每张表存放的内容可以简单了解一下。主要关注的表是jena_g1t1_stmt,其存放了本体的数据,本体以三元组的形式存放在此表中。



  表名

  存储

  jena_g1t1_stmt

  本体数据

  jena_g1t0_reif

  经过处理的本体数据

  jena_sys_stmt

  系统元数据

  jena_graph

  每一个用户图的名字和唯一标志符

  jena_long_lit

  陈述表中不便于直接存储的长字符常量

  jena_long_uri

  陈述表中不便于直接存储的长URI

  jena_prefix

  URI的前缀




  
此时,完成了将本体的持久化,接下来想要对本体进行一些操作该怎么办?

将本体从数据库中读取成OntModel

对本体进一步的操作,需要完成的第一步工作是将本体以OntModel的形式从数据库中读出来。这一步的操作见下述代码。


private final static String driver = "com.mysql.jdbc.Driver";
private final static String url = "jdbc:mysql://localhost/dbname";
private final static String db = "MySQL";
private final static String user = "your user name";
private final static String pwd = "your password";
/**
* @param args
*/
public static void main(String[] args) {
try {
IDBConnection con = getConnection(url, user, pwd, db);
Class.forName(driver);
OntModel model = getModelFromDB(con,"test");
printModel(model);
con.close();
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* get db connection
*
* @param dbUrl
* @param dbUser
* @param dbPwd
* @param dbName
* @return
*/
public static DBConnection getConnection(String dbUrl, String dbUser,
String dbPwd, String dbName) {
return new DBConnection(dbUrl, dbUser, dbPwd, dbName);
}
/**
* get OntModel from db
*
* @param con
* @param name
* @return
*/
public static OntModel getModelFromDB(IDBConnection con, String name) {
ModelMaker maker = ModelFactory.createModelRDBMaker(con);
Model model = maker.getModel(name);
OntModel newmodel = ModelFactory.createOntologyModel(
getModelSpec(maker), model);
return newmodel;
}
/**
* get model spec
*
* @param maker
* @return
*/
public static OntModelSpec getModelSpec(ModelMaker maker) {
OntModelSpec spec = new OntModelSpec(OntModelSpec.OWL_MEM);
spec.setImportModelMaker(maker);
return spec;
}
/**
* print model
*
* @param model
*/
public static void printModel(OntModel model) {
for (Iterator<OntClass> i = model.listClasses(); i.hasNext();) {
OntClass oc = i.next();
System.out.println(oc.getLocalName());
}
}进行此步操作时,会遇到一个推理机的设置问题。这个问题稍后进行一个详细的解释。  
执行了将本体从数据库读出的操作,可以打印出本体中的所有类,直观看到本体的类。获得了OntModel,可以进行其他很多的操作,如读取本体中所有的类、属性及实例,读取本体类与类的关系,给本体增加实例等等操作。

读取本体的所有类及类的属性



/**
* get all classes and properties
*
* @param model
*/
public static void getClasses(OntModel model) {
for (ExtendedIterator<OntClass> ei = model.listClasses(); ei.hasNext();) {
OntClass oc = ei.next();
System.out.println(oc.getLocalName());
for (ExtendedIterator<OntProperty> eip = oc
.listDeclaredProperties(); eip.hasNext();) {
OntProperty op = eip.next();
System.out.println(op.getLocalName());
}
}
}
  

读取一个类的所有实例
  


/**
* get a individual
*
* @param model
* @param prefix
*/
public static void getIndivProperties(OntModel model, String prefix) {
OntClass w = model.getOntClass(prefix + "Writing");
for (ExtendedIterator<?> i = w.listInstances(); i.hasNext();) {
Individual individual = (Individual) i.next();
System.out.println(individual.getLocalName());
for (StmtIterator ei = individual.listProperties(); ei.hasNext();) {
StatementImpl iop = (StatementImpl) ei.next();
System.out.println(iop.getSubject().getLocalName() + "--"
+ iop.getPredicate().getLocalName() + "--"
+ iop.getObject());
}
}
}
  

获取两个类的关系
  获取两个类的关系时,使用了sparql语言查询。Jena API本身不提供直接的方法以获取两个类的关系。


/**
* Get relation (ObjectPropery) between two classes
*
* @param classname1
* @param classname2
* @return relationValue
*/
public static String getRelation(OntModel model, String classname1,
String classname2) {
// Get prefixes
String defaultPrefix = model.getNsPrefixURI("");
String rdfsPrefix = model.getNsPrefixURI("rdfs");
String owlPrefix = model.getNsPrefixURI("owl");
// Create a new query
String queryString = "PREFIX default: <" + defaultPrefix + ">\n"
+ "PREFIX rdfs: <" + rdfsPrefix + ">\n" + "PREFIX owl: <"
+ owlPrefix + ">\n" + "SELECT ?relation\n"
+ "WHERE { ?relation rdfs:domain default:" + classname1
+ ".?relation rdfs:range default:" + classname2 + "}";
// Create the query
Query query = QueryFactory.create(queryString);
// Execute the query and obtain results
QueryExecution qe = QueryExecutionFactory.create(query, model);
ResultSet results = qe.execSelect();
// Get property value
String relationValue;
if (results.hasNext()) {
QuerySolution result = results.nextSolution();
relationValue = result.get("relation").toString()
.substring(defaultPrefix.length());
} else {
relationValue = null;
}
// Important - free up resources used running the query
qe.close();
return relationValue;
}
  

创建一个实例
  


/**
* create a individual
*
* @param model
* @param prefix
*/
public static void createIndiv(OntModel model, String prefix) {
OntClass oc = model.getOntClass("classname");
Individual individual = oc.createIndividual("individualname");
OntProperty op = model.getOntProperty(prefix + "propertyname");
individual.addProperty(op, "propertyvalue");
}诸如此类的代码片段还有很多,在实际使用的时候,详细的内容可以查阅Jena的API文档,找到所需要的方法。不过在使用Jena API的时候,需要考虑效率问题。OntClass oc = model.getOntClass("classname");这行代码的效率出奇的差,如果能有其他方法根据类名获取一个类的方法,希望告知。


接下来说两个遇到的问题。  

中文乱码问题

一是在使用Jena API将本体持久化到数据库时出现的中文乱码的问题。
注意OWL文件的编码和在从文件读取时设置”UTF8“。
还有最重要的一点是在写数据库的URL时应该写成:


jdbc:mysql://localhost/dbname?useUnicode=true&characterEncoding=utf8
  



推理机设置问题

二是在查询类的属性时,需要使用Jena的推理机,否则使用listDeclaredProperties方法直接打印只能找到一个类的独有属性,而无法找到属于多个类的公有属性。


/**
* get model spec
*
* @param maker
* @return
*/
public static OntModelSpec getModelSpec(ModelMaker maker) {
OntModelSpec spec = new OntModelSpec(
OntModelSpec.OWL_MEM_MICRO_RULE_INF);
spec.setImportModelMaker(maker);
return spec;
}但是这样做还是会遇到新的问题,可参见这里。  
设置成OWL_MEM_MICRO_RULE_INF可以获取到一个类的所有属性,但在获取类的时候除了我们定义的类,还会得到系统的一些类。这个问题暂时不知道如何解决。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.iyunv.com/thread-290317-1-1.html 上篇帖子: mysql备份命令Windows环境下与Linux环境下的区别。报错: Couldn't find table: ">" 下篇帖子: Web Sites系列:使用Windows Azure的Web Sites和WebMatrix创建PHP和MySQL站点
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表