jpa 2.0 不注入 EntityManager

jpa 2.0 not injecting EntityManager

我有一个 JPA 2.0 注释的简单实现,但它不起作用。这是作为服务器的 karaf 4.0.5 中的 运行。下面列出了 persistence.xml、blueprint.xml 和 class 的相关摘录。异常列在底部。

问题是 EntityManager em 始终为空。我预计这是由蓝图注入的。

谁能指出我哪里出错了?

Class

import javax.persistence.PersistenceContext;
import javax.transaction.Transactional;

@Transactional
public class LookupMfgService implements ILookupMfgService {
    private static Logger logger = LoggerFactory.getLogger(LookupMfgService.class);
    @PersistenceContext(unitName = "pu_motordb3")
    private EntityManager em;

    @Override
    public List<String> getPreferredMfgNames() throws BusinessException {
        List<String> list = new ArrayList<>();

        try {
    // em is null here so NPE thrown
            TypedQuery<String> q = em.createNamedQuery("listMfgPreferredNames", String.class);
            list = q.getResultList();
        } catch (Throwable t) {
            logger.error("Error selecting list of manufacturers", t);
            throw JpaExceptionFactory.createGeneralError(t, this.getClass().getName());
        }

        return list;
    }

    public void setEm(EntityManager entityManager) {
        logger.debug(this.getClass().getName() + ".setEntityManager()");
        logger.debug("setEntityManager called with " + (entityManager == null ? "null" : entityManager.toString()));
        this.em = entityManager;
    }
}

DataSource.xml

<blueprint default-activation="eager"
    xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"

    xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0 
            http://www.w3.org/2001/XMLSchema-instance http://www.w3.org/2001/XMLSchema-instance 
            http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0 http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0 ">

   <bean id="dataSource" class="org.postgresql.ds.PGPoolingDataSource" destroy-method="close">
      <property name="serverName" value="XXX"/>
      <property name="user" value="XXX"/>
      <property name="password" value="XXX"/>
      <property name="dataSourceName" value="pgConnectionPool"/>
      <property name="initialConnections" value="5"/>
      <property name="maxConnections" value="50" />
  </bean>

  <service interface="javax.sql.DataSource" ref="dataSource">
    <service-properties>
            <entry key="osgi.jndi.service.name" value="MotorDB"/>
    </service-properties>
  </service>
</blueprint>

Blueprint.xml

<blueprint default-activation="eager"
    xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0"
    xmlns:tx="http://aries.apache.org/xmlns/transactions/v2.0.0" xmlns:jpa="http://aries.apache.org/xmlns/jpa/v2.0.0"
    xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
    xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 https://osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
        http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0 http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0
        http://aries.apache.org/xmlns/transactions/v2.0.0 http://aries.apache.org/xmlns/transactions/v2.0.0
        http://aries.apache.org/xmlns/jpa/v2.0.0 http://aries.apache.org/xmlns/jpa/v2.0.0
        http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0 http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0">

    <jpa:enable />
    <tx:enable />

    <service id="mfgLookupService" ref="mfgLookupEntityImpl" interface="ILookupMfgService"/>

</blueprint>

Persistence.xml

<?xml version="1.0" encoding="UTF-8" ?>
<persistence 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"
    version="2.0">

    <persistence-unit name="pu_motordb3" transaction-type="JTA">
    <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
    <jta-data-source>osgi:service/javax.sql.DataSource/(osgi.jndi.service.name=MotorDB)</jta-data-source>
        Classes listed here
    </persistence-unit>
</persistence> 

卡拉夫日志

2016-09-01 09:45:48,689 | INFO  | PersistenceBundleTracker | 90 - org.apache.aries.jpa.container - 2.3.0 | Found persistence unit reference3 in bundle entity with provider org.apache.openjpa.persistence.PersistenceProviderImpl.
2016-09-01 09:45:48,695 | INFO  | PersistenceBundleTracker | 90 - org.apache.aries.jpa.container - 2.3.0 | Found persistence unit pu_motordb3 in bundle entity with provider org.apache.openjpa.persistence.PersistenceProviderImpl.
2016-09-01 09:45:48,695 | INFO  | PersistenceBundleTracker | 90 - org.apache.aries.jpa.container - 2.3.0 | Persistence units added for bundle com.easa.server.entity event 128

异常

2016-08-31 18:42:49,286 | ERROR | nelWorkerThread0 | LookupMfgService                 | Error selecting list of manufacturers
java.lang.NullPointerException
        at LookupMfgService.getPreferredMfgNames(LookupMfgService.java:93)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)[:1.8.0_91]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)[:1.8.0_91]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)[:1.8.0_91]
        at java.lang.reflect.Method.invoke(Method.java:498)[:1.8.0_91]
        at ch.ethz.iks.r_osgi.impl.ChannelEndpointImpl.handleMessage(ChannelEndpointImpl.java:1265)[69:ch.ethz.iks.r_osgi.remote:1.0.8.RC1_v20160823-2221]
        at ch.ethz.iks.r_osgi.impl.ChannelEndpointImpl.run(ChannelEndpointImpl.java:315)[69:ch.ethz.iks.r_osgi.remote:1.0.8.RC1_v20160823-2221]
        at ch.ethz.iks.r_osgi.impl.ChannelEndpointImpl.run(ChannelEndpointImpl.java:280)[69:ch.ethz.iks.r_osgi.remote:1.0.8.RC1_v20160823-2221]

您的数据源配置似乎丢失了。您正在使用未在任何地方声明的 osgi.jndi.service.name=MotorDB。所以没有服务实现 javax.sql.DataSource

必须有类似于以下使用 Oracle 的示例的内容。 对其他 DBMS 进行相应更改:

...
<bean id="dataSourceBeanMfgLookupService" class="oracle.jdbc.pool.OracleDataSource">
  <property name="URL" value="???"/>
  <property name="user" value="???"/>
  <property name="password" value="???"/>
</bean>

<service id="dataSourceMfgLookupService" interface="javax.sql.DataSource" ref="dataSourceBeanMfgLookupService">
  <service-properties>
     <entry key="osgi.jndi.service.name" value="MotorDB" />
  </service-properties>
</service>
...

此外,您可能必须在 persistence.xml 中指定持久性提供程序。如果您将 hibernate 与 Oracle 10g 一起使用,它看起来会像这样:

<persistence xmlns="http://java.sun.com/xml/ns/persistence" ...>

   <provider>org.hibernate.ejb.HibernatePersistence</provider>

   ...

   <properties>
      <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect" />
      <property name="hibernate.temp.use_jdbc_metadata_defaults" value="false" />
   ...

然后您可以link您的数据源到您的服务:

<bean id="mfgLookupEntityImpl" class="LookupMfgService">
  <jpa:context property="em" unitname="pu_motordb3" />
  <tx:transaction method="*" value="Required" />
</bean>

如果仍然无法注入 EM,请提供 setter:

public void setEm(EntityManager entityManager) {
  this.em = entityManager;
}

AFAIK was/is 一个错误,即 属性 注入仅在 setter 可用时才有效。

原因是 karaf 4.0.5 和 openjpa 2.4.1 存在问题。已在 karaf 4.0.6

中解决