一个常见的OSGI JPA应用可以是这样的:若干个用JPA的规范编写的实体(Entity),集合在一个Bundle里,并用persistence.xml描述成一个持久化单元(persistence unit)。而persistence.xml里则通过JNDI将JDBC DataSource与该域绑定。最后,Aries JPA container就能将持久化单元的EntityManagerFactory或EntityManager提供给应用来引用。
以下是一个例子:
persistence.xml:
<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <persistence-unit name="com.ponder.examples.jpa01PU" transaction-type="RESOURCE_LOCAL"> <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider> <non-jta-data-source>osgi:service/javax.sql.DataSource/(osgi.jndi.service.name=jdbc/jpa01DS)</non-jta-data-source> <class>com.ponder.examples.jpa01.CustomerEntity</class> <exclude-unlisted-classes>true</exclude-unlisted-classes> <properties> <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/> </properties> </persistence-unit> </persistence>
blueprint.xml:
<?xml version="1.0" encoding="UTF-8"?> <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.0.0"> <cm:property-placeholder persistent-id="com.ponder.examples.jpa01"> <cm:default-properties> <cm:property name="DS.DriverName" value="com.mysql.jdbc.Driver" /> <cm:property name="DS.Url" value="jdbc:mysql://192.168.0.1:3306/mydb" /> <cm:property name="DS.User" value="user" /> <cm:property name="DS.Password" value="password" /> <cm:property name="DS.InitialSize" value="5" /> <cm:property name="DS.MinIdle" value="5" /> <cm:property name="DS.MaxIdle" value="20" /> <cm:property name="DS.MaxWait" value="1000" /> <!-- 1000毫秒 --> <cm:property name="DS.MaxActive" value="30" /> <cm:property name="DS.LogAbandoned" value="true"/> <cm:property name="DS.RemoveAbandoned" value="true"/> <cm:property name="DS.RemoveAbandonedTimeout" value="180"/> <!-- 180秒 --> <cm:property name="DS.TestWhileIdle" value="true"/> <cm:property name="DS.TestOnBorrow" value="false"/> <cm:property name="DS.TestOnReturn" value="false"/> <cm:property name="DS.ValidationQuery" value="SELECT COUNT(0) FROM DUAL"/> <cm:property name="DS.ValidationQueryTimeout" value="1"/> <cm:property name="DS.TimeBetweenEvictionRunsMillis" value="30000"/> <cm:property name="DS.NumTestsPerEvictionRun" value="30"/> </cm:default-properties> </cm:property-placeholder> <bean id="jpa01DS" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${DS.DriverName}" /> <property name="url" value="${DS.Url}" /> <property name="username" value="${DS.User}" /> <property name="password" value="${DS.Password}" /> <property name="initialSize" value="${DS.InitialSize}"/> <property name="minIdle" value="${DS.MinIdle}"/> <property name="maxIdle" value="${DS.MaxIdle}"/> <property name="maxWait" value="${DS.MaxWait}"/> <property name="maxActive" value="${DS.MaxActive}"/> <property name="logAbandoned" value="${DS.LogAbandoned}"/> <property name="removeAbandoned" value="${DS.RemoveAbandoned}"/> <property name="removeAbandonedTimeout" value="${DS.RemoveAbandonedTimeout}"/> <property name="testWhileIdle" value="${DS.TestWhileIdle}"/> <property name="testOnBorrow" value="${DS.TestOnBorrow}"/> <property name="testOnReturn" value="${DS.TestOnReturn}"/> <property name="validationQuery" value="${DS.ValidationQuery}"/> <property name="validationQueryTimeout" value="${DS.ValidationQueryTimeout}"/> <property name="timeBetweenEvictionRunsMillis" value="${DS.TimeBetweenEvictionRunsMillis}"/> <property name="numTestsPerEvictionRun" value="${DS.NumTestsPerEvictionRun}"/> </bean> <service ref="jpa01DS" interface="javax.sql.DataSource"> <service-properties> <entry key="osgi.jndi.service.name" value="jdbc/jpa01DS"/> </service-properties> </service> </blueprint>
其中的关键点如下:
1、持久化单元(PU)定义(persistence.xml);
2、数据源(Datasource):采用apache的dbcp;
3、blueprint通过placeholder配置DataSource,并发布DataSource服务,并注册到JNDI ;
4、PU通过jndi引用Datasource;
5、部署时,karaf通过configAdmin服务将etc/com.ponder.examples.jpa01.cfg的配置信息读入到blueprint的placeholder处。