1

我已经搜索了整个 SO,虽然存在具有相似标题的帖子,但这是一个不同的场景。

我的 Eclipse 中有两个项目 1) 一个 JPA 项目 2) 一个使用 JPA 项目中的实体的 Web 项目。两者都启用了 OSGi 和 Maven。我正在使用最新的 SpringFramework (3.1.1) 在 Web 项目中创建 RESTful Web 服务。

项目布局如下:

1) JPA 项目

com.demo.persistence 
|-src
  |-com.demo.persistence
    |-User
|-META-INF
    |-MANIFEST.MF
    |-persistence.xml
|-pom.xml

2) 网络项目

com.demo.web
|-src
  |-com.demo.web.controller
    |-Controller.java
  |-com.demo.web.dao
    |-UserDAO.java
    |-UserListDAO.java
  |-com.demo.web.model
    |-UserBean.java
  |-com.demo.web.interfaces
    |-UserDAOIntf.java
|-WebContent
  |-META-INF
    |-MANIFEST.MF
  |-WEB-INF
    |-classes
      |-log4j.properties
    |-rest-context.xml
    |-rest-context-osgi.xml
    |-rest-servlet.xml
    |-web.xml
  |-pom.xml

com.demo.persistence.User.java

@Entity
@XmlRootElement(name="user")
@Table(name = "T_USER")
@NamedQuery(name = "AllUsers", query = "select u from User u")
public class User {

@Id
@GeneratedValue
@Column(nullable = false)
private long id;

@Basic
@Column(nullable = false)
private String userName;

public void setUserName(String param) {
    this.userName = param;
}

public String getUserName() {
    return userName;
}
}

com.demo.web.dao.UserDAO

public class UserDAO implements UserDAOInterface {  
@PersistenceContext
private EntityManager em;

public User getUser(Long id) {
  try{
      return em.find(User.class, id);
  } finally {
      if(em != null)
      em.close();
   }
}

public List<User> getAllUsers() {
  try {
    List<User> users = em.createNamedQuery("AllUsers", User.class).getResultList();
    return users;
  } finally {
          if(em != null)
          em.close();
  }
}

@Transactional
public User addUser(User user) {
  try {
    em.persist(user);
        em.flush();
    return user;
        } finally {
        if(em != null)
    em.close();
        }
  }
}

com.demo.web.model

public class UserBean {
  private UserDAO userDAO;
    public void addUserDetails( String userName ) {
    User user = new User();
    user.setUserName(userName);
    this.userDAO.addUser(user);
}

public List<User> getAllUsers() {
    return this.userDAO.getAllUsers();
}

public User getUser(Long id) {
    return this.userDAO.getUser(id);
}

public User addUser(User user) {    
    return this.userDAO.addUser(user);
}
}

com.demo.web.controller.Controller

@Controller
public class Controller {

    private Jaxb2Marshaller jaxb2Marshaller;
    private UserBean userBean;

    public Jaxb2Marshaller getJaxb2Mashaller() {
        return jaxb2Marshaller;
    }

    public void setJaxb2Mashaller(Jaxb2Marshaller jaxb2Marshaller) {
        this.jaxb2Marshaller = jaxb2Marshaller;
    }
    @RequestMapping(method=RequestMethod.GET, value="/rest/users", headers="Accept=application/xml, application/json")
    public @ResponseBody UserListDAO getUserList() { 
        return new UserListDAO(userBean.getAllUsers());
    }

    @RequestMapping(method=RequestMethod.GET, value="rest/user/{id}", headers="Accept=application/xml, application/json")
    public @ResponseBody User getUser(@PathVariable Long id) {
        return userBean.getUser(id);
    }

    @RequestMapping(method=RequestMethod.POST, value="rest/user/add", headers="Accept=application/xml, application/json")
    public @ResponseBody User addUser(@RequestBody String userString) {
        Source source = new StreamSource(new StringReader(userString));
        User user = (User) jaxb2Marshaller.unmarshal(source);
        return userBean.addUser(user);
    }

web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns="http://java.sun.com/xml/ns/javaee" 
      xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
      xsi:schemaLocation=
          "http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
        id="WebApp_ID" version="2.5">

    <display-name>com.demo.web</display-name>

    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
    </welcome-file-list>

<context-param>
    <param-name>log4jConfigLocation</param-name>
    <param-value>
        /WEB-INF/classes/log4j.properties
    </param-value>
    </context-param>

    <listener>
    <listener-class>
        org.springframework.web.util.Log4jConfigListener
    </listener-class>
    </listener>

    <!-- The context params that read by ContextLoaderListener  -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/rest-context.xml
        </param-value>
    </context-param>

    <!-- This listener will load other application context file in addition to springweb-servlet.xml -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <servlet>
        <servlet-name>rest</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>rest</servlet-name>
        <url-pattern>/service/*</url-pattern>
    </servlet-mapping>
</web-app>

休息上下文.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">

    <context:annotation-config />
    <context:component-scan base-package="com.demo.web.controller" />
    <tx:annotation-driven transaction-manager="transactionManager" /> 

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="com.demo.persistence" />
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>   

    <!-- Bean - DAO Mapping -->
    <bean id="userDAO" class="com.demo.dao.UserDAO">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>

    <!-- Bean Declarations -->
    <bean id="userBean" class="com.demo.web.model.UserBean">
        <property name="userDAO" ref="userDAO" />
    </bean>

</beans>

休息上下文osgi.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans 
    xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:osgi="http://www.springframework.org/schema/osgi"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/osgi  
        http://www.springframework.org/schema/osgi/spring-osgi-1.0.xsd">

    <osgi:service interface="javax.persistence.EntityManager" ref="entityManagerFactory" />

</beans>

休息-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

    <!-- To enable @RequestMapping process on type level and method level -->
    <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
        <property name="messageConverters">
            <list>
                <ref bean="marshallingConverter" />
                <ref bean="jsonConverter" />
            </list>
        </property>
    </bean>

    <bean id="marshallingConverter" class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
        <constructor-arg ref="jaxbMarshaller" />
        <property name="supportedMediaTypes" value="application/xml"/>
    </bean>

    <bean id="jsonConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
        <property name="supportedMediaTypes" value="application/json" />
    </bean>

    <bean id="jaxbMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
        <property name="classesToBeBound">
            <list>
                <value>com.demo.persistence.User</value>
                <value>com.demo.dao.UserListDAO</value>
            </list>
        </property>
    </bean>

    <bean id="users" class="org.springframework.web.servlet.view.xml.MarshallingView">
        <constructor-arg ref="jaxbMarshaller" />
    </bean>

    <!--bean id="viewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver" /-->

    <bean id="userController" class="com.demo.web.controller.Controller">
        <property name="userDAO" ref="userDAO" />
        <property name="jaxb2Mashaller" ref="jaxbMarshaller" />
    </bean>
</beans>

控制台 - log4j

ERROR [org.springframework.web.context.ContextLoader] - Context initialization failed

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in ServletContext resource [/WEB-INF/rest-context.xml]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: No Persistence provider for EntityManager named com.demo.persistence

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1455)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)

    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)

    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)

    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)

    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)

    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:567)

    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:913)

    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464)

    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:385)

    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:284)

    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:111)

    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4779)

    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5273)

    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)

    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:897)

    at org.apache.catalina.core.ContainerBase.access$000(ContainerBase.java:131)

    at org.apache.catalina.core.ContainerBase$PrivilegedAddChild.run(ContainerBase.java:154)

    at org.apache.catalina.core.ContainerBase$PrivilegedAddChild.run(ContainerBase.java:143)

    at java.security.AccessController.doPrivileged(Native Method)

    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:871)

    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:615)

    at org.eclipse.gemini.web.tomcat.internal.TomcatServletContainer.startWebApplication(TomcatServletContainer.java:122)

    at org.eclipse.gemini.web.internal.StandardWebApplication.start(StandardWebApplication.java:91)

    at org.eclipse.gemini.web.extender.WebContainerBundleCustomizer.addingBundle(WebContainerBundleCustomizer.java:45)

    at org.osgi.util.tracker.BundleTracker$Tracked.customizerAdding(BundleTracker.java:482)

    at org.osgi.util.tracker.BundleTracker$Tracked.customizerAdding(BundleTracker.java:1)

    at org.osgi.util.tracker.AbstractTracked.trackAdding(AbstractTracked.java:262)

    at org.osgi.util.tracker.AbstractTracked.track(AbstractTracked.java:234)

    at org.osgi.util.tracker.BundleTracker$Tracked.bundleChanged(BundleTracker.java:457)

    at org.eclipse.osgi.framework.internal.core.BundleContextImpl.dispatchEvent(BundleContextImpl.java:847)

    at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:230)

    at org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:148)

    at org.eclipse.osgi.framework.internal.core.Framework.publishBundleEventPrivileged(Framework.java:1522)

    at org.eclipse.osgi.framework.internal.core.Framework$7.run(Framework.java:1462)

    at java.security.AccessController.doPrivileged(Native Method)

    at org.eclipse.osgi.framework.internal.core.Framework.publishBundleEvent(Framework.java:1460)

    at org.eclipse.osgi.framework.internal.core.Framework.publishBundleEvent(Framework.java:1453)

    at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(BundleHost.java:391)

    at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(AbstractBundle.java:299)

    at org.eclipse.osgi.framework.internal.core.PackageAdminImpl.resumeBundles(PackageAdminImpl.java:311)

    at org.eclipse.osgi.framework.internal.core.PackageAdminImpl.processDelta(PackageAdminImpl.java:555)

    at org.eclipse.osgi.framework.internal.core.PackageAdminImpl.doResolveBundles(PackageAdminImpl.java:251)

    at org.eclipse.osgi.framework.internal.core.PackageAdminImpl$1.run(PackageAdminImpl.java:173)

    at java.lang.Thread.run(Thread.java:722)

Caused by: javax.persistence.PersistenceException: No Persistence provider for EntityManager named com.demo.persistence

    at javax.persistence.Persistence.createEntityManagerFactory(Unknown Source)

    at org.springframework.orm.jpa.LocalEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalEntityManagerFactoryBean.java:92)

    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:310)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$6.run(AbstractAutowireCapableBeanFactory.java:1504)

    at java.security.AccessController.doPrivileged(Native Method)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1502)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1452)

    ... 45 more

很抱歉这个巨大的帖子。但是我在 Manifest 文件中导出了我的持久性包,并在我的 Web 应用程序中导入了相同的包。

使用的持久性提供程序是org.eclipse.persistence.jpa.PersistenceProvider. 这已经停止了我的项目一个月.. :(请帮忙。

提前致谢。


编辑

持久性.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.demo.persistence"
        transaction-type="RESOURCE_LOCAL">
        <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
        <class>com.demo.persistence.Person</class>
        <properties>
            <property name="eclipselink.weaving" value="false" />
            <property name="eclipselink.ddl-generation" value="create-tables" />
        </properties>
    </persistence-unit>
</persistence>
4

1 回答 1

1

您正在指示您的容器为您管理和初始化持久性上下文:

@PersistenceContext
private EntityManager em;

但只有当它可以访问与您执行实体管理器初始化相同的存档中的 persistence.xml 文件时,它才能执行此操作。在这种情况下,您可能应该将所有持久性逻辑移动到持久性项目中(毕竟这就是您创建它的目的)。或者,您可以将 persistence.xml 复制到 Web 项目中(不推荐)。

于 2012-04-20T19:01:15.517 回答