mysql api 读取与设置_Jena API使用详解(关注将本体持久化到MySQL后的操作及解决中文乱码等问题)...

本文介绍了如何使用Jena API将本体持久化到MySQL数据库,并详细讲解了从数据库中读取本体为OntModel的过程,包括读取所有类、属性及实例的方法。同时,文中提到了中文乱码问题的解决方案和推理机设置问题。
摘要由CSDN通过智能技术生成

关于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数据库中可以看见七张表。

a681dd4d84b419ce06e76847f4786c80.png

每张表存放的内容可以简单了解一下。主要关注的表是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 (Iteratori = 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 ei = model.listClasses(); ei.hasNext();) {

OntClass oc = ei.next();

System.out.println(oc.getLocalName());

for (ExtendedIterator 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: \n"

+ "PREFIX rdfs: \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可以获取到一个类的所有属性,但在获取类的时候除了我们定义的类,还会得到系统的一些类。这个问题暂时不知道如何解决。

分享到:

18e900b8666ce6f233d25ec02f95ee59.png

72dd548719f0ace4d5f9bca64e1d7715.png

2013-11-15 13:12

浏览 459

评论

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值