Karaf教程第6部分-数据库访问

来源:互联网 发布:log4j 只输出sql 编辑:程序博客网 时间:2024/05/22 04:29

Karaf教程第6部分-数据库访问

本教程演示Karaf中的OSGi应用如何访问数据库,如何通过将DataSource安装为OSGi服务来抽象DB产品。一些新的Karaf命令行用于数据库操作。最后JDBCJPA示例演示如何从用户代码角度使用DataSource

前提条件

你需要安装karaf 3.0.3

示例源代码

示例工程位于githubKaraf-Tutorial/db.

DriverDataSource

在普通Java中,使用DriverManager来创建数据库连接是相当普遍的。在OSGi中, DriverManager就无法工作了,因为bundle的类加载器看不到数据库驱动。所以在OSGi中,最佳实践是在某个知道驱动的地方创建DataSource,并将其发布为OSGi服务。用户bundle应该只使用DataSource,而无需知道驱动细节。这非常类似于应用服务器的最佳实践,那里DataSource是由服务器管理,并发布到jndi

所以首先我们需要学习如何创建和使用DataSource

DataSourceFactory服务

为了在OSGi中更容易地创建DataSource,规范定义了DataSourceFactory接口。它允许使用属性指定的驱动创建DataSource。每一个数据库驱动都应该实现这个接口,并用驱动类名和驱动名属性发布为OSGi服务。

pax-jdbc介绍

pax-jdbc工程的目标就是在OSGi环境中使用数据库变得更加容易。它做了以下几件事情:

  • 实现数据库的DataSourceFactory服务,而不直接创建服务。
  • 实现XADataSource的池子和包装(the pax jdbc docs中描述)
  • 提供了从config admin配置创建DataSource服务的便利。
  • 除了上面额外的功能,还提供了许多数据库的karaf特性。

所以它覆盖了你创建产品级的DataSource需要的驱动安装的方方面面。

安装数据库驱动

第一步为karaf中的数据库系统安装驱动bundle。大多数的驱动都已经是合法的bundle,并且可以在maven仓库找到。

对于一些数据库,pax-jdbc已经提供了karafdf特性,来安装当前版本的数据库驱动。

对于H2,下面的命令是有效的:

feature:repo-add mvn:org.ops4j.pax.jdbc/pax-jdbc-features/0.8.0/xml/features

feature:install transaction jndi pax-jdbc-h2 pax-jdbc-pool-dbcp2 pax-jdbc-config

service:list DataSourceFactory

严格地讲,我们只需要pax-jdbc-h2特性,但是我们依然需要安装后续步骤会用到的其它特性。

这些命令会安装pax-jdbc特性仓库和h2数据库驱动。H2数据库驱动已经实现了DataSourceFactory,所以最后一个命令将会显示这个服务。

DataSourceFactory

[org.osgi.service.jdbc.DataSourceFactory]

-----------------------------------------

 osgi.jdbc.driver.class = org.h2.Driver

 osgi.jdbc.driver.name = H2

 osgi.jdbc.driver.version = 1.3.172

 service.id = 691

Provided by :

 H2 Database Engine (68)

pax-jdbc-pool-dbcp2特性包装了DataSourceFactory,以提供数据库连接池和XA支持。

支持数据库池和 XADataSourceFactory

[org.osgi.service.jdbc.DataSourceFactory]

-----------------------------------------

 osgi.jdbc.driver.class = org.h2.Driver

 osgi.jdbc.driver.name = H2-pool-xa

 osgi.jdbc.driver.version = 1.3.172

 pooled = true

 service.id = 694

 xa = true

Provided by :

 OPS4J Pax JDBC Pooling support using Commons-DBCP2 (73)

从技术上说,这个DataSourceFactory也创建DataSource对象,但是它内部会管理XA支持和数据库连接池。所以我们想要在后面的代码示例中使用这个。

创建DataSource

现在我们只需要创建一个带有正确的工程pid的配置来创建DataSource服务。

所以创建了文件etc/org.ops4j.datasource-tasklist.cfg,内容为:

DataSource配置

osgi.jdbc.driver.name=H2-pool-xa

url=jdbc:h2:mem:person

dataSourceName=person

这个配置会自动触发pax-jdbc-config模块创建DataSource

  • 名字osgi.jdbc.driver=H2-pool-xa会选择之前安装的H2的支持数据库连接池和XADataSourceFactory
  • url配置了H2创建一个简单的内存数据库,名字为test
  • dataSourceName将会反映到DataSource的服务属性里,稍后我们会找到它。
  • 你也可以配置数据库池子,但是我们这里只使用默认配置。

DataSource

karaf@root()> service:list DataSource

[javax.sql.DataSource]

----------------------

 dataSourceName = person

 osgi.jdbc.driver.name = H2-pool-xa

 osgi.jndi.service.name = person

 service.factoryPid = org.ops4j.datasource

 service.id = 696

 service.pid = org.ops4j.datasource.83139141-24c6-4eb3-a6f4-82325942d36a

 url = jdbc:h2:mem:person

Provided by :

 OPS4J Pax JDBC Config (69)

所以当我们搜索实现了DataSource接口的服务时,我们找到了我们刚刚创建的那个DataSource实例person

当我们安装上面的特性时,我们也安装了aries jndi特性。这个模块将OSGi服务映射到jndi对象上。所以我们也可以使用jndi来获取DataSource,这个DataSource稍后用于jpapersistence.xml

DataSourcejndi url

osgi:service/person

Karaf jdbc命令

Karaf包含一些管理DataSource和查询数据库的命令行。Karaf3.x中的管理DataSource的命令行仍然对使用blueprint创建DataSource的老方法有效。所以我们不会使用这些命令行,但是我们使用list DataSourcelist数据库表和执行查询等功能。

jdbc commands

feature:install jdbc

jdbc:datasources

jdbc:tables person

我们要首先按照karaf jdbc特性,jdbc特性提供了jdbc命令行。然后我们列出所有的DataSource,显示person DataSource能访问的所有数据表。

jdbc:execute person "create table person (name varchar(100), twittername varchar(100))"

jdbc:execute person "insert into person (name, twittername) values ('Christian Schneider', '@schneider_chris')"

jdbc:query person "select * from person"

这些命令创建了一个数据表person,添加了一行记录,并显示数据表。输出应该类似于下面这样:

select * from person

NAME                | TWITTERNAME    

--------------------------------------

Christian Schneider | @schneider_chris

使用JDBC访问数据库

db/examplejdbc示例工程演示了如何使用我们安装的DataSource服务,在这个工程中安装和执行jdbc命令行。这个例子使用blueprint.xml引用OSGi服务DataSource,并将其注入到类DbExample中。然后test方法被作为init方法调用,演示DataSource上的一些jdbc语句。DbExample类完全独立于OSGi DbExampleTest很容易地单独测试。这个test方法演示了在OSGi外部如何手动设置DataSource

构建和安装

使用下面的命令构建:mvn clean install

Karaf中,我们只需要安装我们自己的bundle,因为我们没有特殊的依赖。

> install -s mvn:net.lr.tutorial.karaf.db/db-examplejdbc/1.0-SNAPSHOT

Using datasource H2, URL jdbc:h2:~/test

Christian Schneider, @schneider_chris,

在安装完成之后,这个bundle应该直接打印数据库信息和持久化的person

使用JPA访问数据库

对于更大的工程,经常使用的是JPA,而不是手动创建SQL。相对于JDBC,使用JPA有两大优势:

  1. 你维护的SQL代码更少;
  2. JPA提供了方言,以屏蔽数据库的微妙区别,否则你需要自己编写代码。

在这个例子中,我们使用Hibernate作为JPA的实现。在此基础上,我们增加了 Apache Aries JPA,以提供OSGi JPA服务规范的实现,和JPA集成blueprint

examplejpa演示了一个实现Person对象管理的PersonService服务的简单工程。Person只是一个用JPA @Entity注解了的JavaBean

另外,这个工程还实现了两个Karaf命令行:person:addperson:list,这两个命令行允许简单地测试这个工程。

persistence.xml

和通常的JPA工程一样,peristence.xml文件定义了DataSource查找,数据库设置和持久类的列表。DataSource使用jndi名字"osgi:service/person"引用。

OSGi JPA服务规范定:Manifest文件应该包含属性"Meta-Persistence",这个属性指向persistence.xml。所以这个需要在maven bundle plugin中的配置中进行定义。Aries JPA容器将会扫描这些属性,将初始化的EntityMangerFactory注册为OSGi服务供用户bundle使用。

blueprint.xml

我们使用blueprint.xml上下文将EntityManager注入到我们的服务事项中,并提供了自动事务支持。下面的片段是我们感兴趣的部分:

<bean id="personService" class="net.lr.tutorial.karaf.db.examplejpa.impl.PersonServiceImpl">

    <jpa:context property="em" unitname="person" />

    <tx:transaction method="*" value="Required"/>

</bean>

这个配置会查找适用于持久单元personEntityManagerFactory OSGi服务 ,并注入线程安全的EnityManager (底层使用ThreadLocal)PersonServiceImpl。另外,它包装了每一个PersonServiceImpl方法调用,在方法调用之前增加打开事务的代码,并提交,如果抛出了任何异常,则执行回滚。

构建和安装

构建:

mvn clean install

前提是已经安装了derby datasource。然后我们必须安装hibernatearies jpa transactionjndi和我们自己的db-examplejpabundle。参见ReadMe.txt了解命令行的使用。

测试

person:add 'Christian Schneider' @schneider_chris

然后列出所有的持久person

karaf@root> person:list

Christian Schneider, @schneider_chris

总结

在这个教程里,我们学习了如何在Karaf使用使用数据库。我们安装了数据库驱动和DataSource服务。我们能够使用jdbc:*命令行检查和操作DataSource。在examplejdbc示例中,我们学习了如何获取datasource,并用普通的jdbc和它一起工作。最后我们使用jpa访问我们的数据库。