2

我的 EclipseLink 和 Spring(MVC 和 spring-data)版本 3.1.1 设置的另一个问题:

根据本文,我正在尝试在不使用 persistence.xml 文件的情况下让 JPA 工作。在文章中说:

通常,JPA 通过 META-INF/persistence.xml 文件定义一个持久化单元。从 Spring 3.1 开始,不再需要此 XML 文件 - LocalContainerEntityManagerFactoryBean 现在支持“packagesToScan”属性,可以指定要扫描 @Entity 类的包。

persistence.xml 文件是要删除的最后一个 XML 文件——现在,JPA 可以完全设置而无需 XML。

我知道如果使用persistence.xml 文件,这里的所有实体类都应该在这里声明。但是,我正在尝试使用该packagesToScan属性。下面是完整的启动日志和在向 servlet 发出一个请求后产生的错误,该 servlet 最终尝试在数据库中创建一个新用户。它似乎没有认识到该User对象是一个实体。由于我对 Spring 的经验很少,我想知道是否有人首先可以发现我正在犯的错误,但除此之外,知道调试它的最佳方法。我想知道 EntityManagerFactory 已经识别了哪些 Entity 对象。

我的备份选项是切换到使用 persistence.xml(实际上还没有尝试过),但如果可能的话,我想摆脱它(少一个 XML 文件需要担心)。

更新:根据 Sean Patrick Floyd 的回答,我在对 entityManagerFactory 进行了推荐的配置更改后更新了错误日志,但这并没有解决主要问题。我还尝试了另一种方法,通过创建一个 persistence.xml 文件(旧的和更常见的方法)并在我访问的 servlet 中添加一小段测试代码来启动它功能。所以现在我的 servlet 中有这段代码:

User user = new User();
user.setFirstName("John");
user.setLastName("Doe");
// user = userService.addUser(user);

EntityManagerFactory emf = Persistence.createEntityManagerFactory("proxiPU");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(user); 
em.getTransaction().commit();
em.close();
emf.close();

而这个 persistence.xml 文件:

<?xml version="1.0" encoding="UTF-8" ?>
<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" xmlns="http://java.sun.com/xml/ns/persistence">

    <persistence-unit name="proxiPU" transaction-type="RESOURCE_LOCAL">
        <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
        <class>com.proxi.user.User</class>
        <exclude-unlisted-classes>false</exclude-unlisted-classes>
        <properties>
            <property name="eclipselink.jdbc.driver" value="org.hsqldb.jdbcDriver"/>
            <property name="eclipselink.jdbc.url" value="jdbc:hsqldb:file:\Users\nly31175\hsqldb;shutdown=true"/>
            <property name="eclipselink.jdbc.user" value="proxi"/>
            <property name="eclipselink.jdbc.password" value=""/>
            <property name="eclipselink.target-database" value="org.eclipse.persistence.platform.database.HSQLPlatform"/>
            <property name="eclipselink.logging.level" value="FINEST"/>
            <property name="eclipselink.orm.throw.exceptions" value="true"/>
            <property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
            <property name="eclipselink.ddl-generation.output-mode" value="database"/>
        </properties>
    </persistence-unit>
</persistence>

这实际上有效,所以我现在想知道 EntityManagerFactory 的初始化方式是否存在问题或类似的问题。我已经包含了应该执行数据库相关工作的 UserService 类的代码。

这是完整的启动日志(包括错误):

INFO: Reloading Context with name [/proxi] is completed
INFO : com.proxi.controller.HomeController - Welcome home! The client locale is en_GB
[EL Info]: 2012-04-26 15:17:35.066--ServerSession(313687096)--Thread(Thread[http-bio-8980-exec-3,5,main])--EclipseLink, version: Eclipse Persistence Services - 2.2.0.v20110202-r8913
[EL Config]: 2012-04-26 15:17:35.079--ServerSession(313687096)--Connection(1182807222)--Thread(Thread[http-bio-8980-exec-3,5,main])--connecting(DatabaseLogin(
    platform=>HSQLPlatform
    user name=> ""
    connector=>JNDIConnector datasource name=>null
))
INFO : hsqldb.db.HSQLDB36EB6EA7CB.ENGINE - checkpointClose start
INFO : hsqldb.db.HSQLDB36EB6EA7CB.ENGINE - checkpointClose end
[EL Config]: 2012-04-26 15:17:36.016--ServerSession(313687096)--Connection(1257700692)--Thread(Thread[http-bio-8980-exec-3,5,main])--Connected: jdbc:hsqldb:file:\Users\nly31175\hsqldb;shutdown=true
    User: proxi
    Database: HSQL Database Engine  Version: 2.2.6
    Driver: HSQL Database Engine Driver  Version: 2.2.6
INFO : hsqldb.db.HSQLDB36EB6EA7CB.ENGINE - Database closed
[EL Config]: 2012-04-26 15:17:36.365--ServerSession(313687096)--Connection(385835848)--Thread(Thread[http-bio-8980-exec-3,5,main])--connecting(DatabaseLogin(
    platform=>HSQLPlatform
    user name=> ""
    connector=>JNDIConnector datasource name=>null
))
INFO : hsqldb.db.HSQLDB36EB6EA7CB.ENGINE - checkpointClose start
INFO : hsqldb.db.HSQLDB36EB6EA7CB.ENGINE - checkpointClose end
[EL Config]: 2012-04-26 15:17:36.877--ServerSession(313687096)--Connection(603544782)--Thread(Thread[http-bio-8980-exec-3,5,main])--Connected: jdbc:hsqldb:file:\Users\nly31175\hsqldb;shutdown=true
    User: proxi
    Database: HSQL Database Engine  Version: 2.2.6
    Driver: HSQL Database Engine Driver  Version: 2.2.6
INFO : hsqldb.db.HSQLDB36EB6EA7CB.ENGINE - Database closed
[EL Info]: 2012-04-26 15:17:37.328--ServerSession(313687096)--Thread(Thread[http-bio-8980-exec-3,5,main])--file:/C:/Users/nly31175/workspace/spring/.metadata/.plugins/org.eclipse.wst.server.core/tmp1/wtpwebapps/proxi/WEB-INF/classes/_default login successful
Apr 26, 2012 3:17:37 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [appServlet] in context with path [/proxi] threw exception [Request processing failed; nested exception is java.lang.IllegalArgumentException: Object: com.proxi.user.User@5ca3ce3f is not a known entity type.] with root cause
java.lang.IllegalArgumentException: Object: com.proxi.user.User@5ca3ce3f is not a known entity type.
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.registerNewObjectForPersist(UnitOfWorkImpl.java:4128)
    at org.eclipse.persistence.internal.jpa.EntityManagerImpl.persist(EntityManagerImpl.java:406)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:365)
    at $Proxy23.persist(Unknown Source)
    at com.proxi.user.UserService.save(UserService.java:27)
    at com.proxi.user.UserService.addUser(UserService.java:39)
    at com.proxi.controller.HomeController.home(HomeController.java:51)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:213)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:126)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:96)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:617)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:578)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:405)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:964)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:515)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:302)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:662)

根上下文.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:beans="http://www.springframework.org/schema/beans"
    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.1.xsd">

    <!-- Root Context: defines shared resources visible to all other web components -->
    <bean id="userService" class="com.proxi.user.UserService" >
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>

    <!-- Starting with Spring 3.1, the persistence.xml XML file is no longer 
        necessary. The LocalContainerEntityManagerFactoryBean now supports a ‘packagesToScan’ 
        property where the packages to scan for @Entity classes can be specified. -->
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="jpaDialect" ref="jpaDialect" />
        <property name="dataSource" ref="dataSource" />
        <property name="packagesToScan" value="com.proxi.user" />
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
                <property name="showSql" value="true" />
                <property name="generateDdl" value="true" />
                <property name="databasePlatform" value="org.eclipse.persistence.platform.database.HSQLPlatform" />
            </bean>
        </property>
        <property name="loadTimeWeaver">
            <bean class="org.springframework.instrument.classloading.SimpleLoadTimeWeaver" />
        </property>
    </bean>

    <bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect " />

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="org.hsqldb.jdbcDriver" />
        <property name="url" value="jdbc:hsqldb:file:\Users\nly31175\hsqldb;shutdown=true" />
        <property name="username" value="proxi" />
        <property name="password" value="" />
    </bean>

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

</beans>

用户.java 类:

/**
 * 
 */
package com.proxi.user;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Table;

import javax.persistence.Id;

    /**
     * Represents an application user.
     */
    @Entity
    @Table(name = "user")
    public class User {

        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "id")
        private Long id;

        @Column(name = "first_name")
        private String firstName;

        @Column(name = "last_name")
        private String lastName;

        // /////// GETTERS AND SETTERS ///////////

        public String getFirstName() {
            return firstName;
        }

        public void setFirstName(String firstName) {
            this.firstName = firstName;
        }

        public String getLastName() {
            return lastName;
        }

        public void setLastName(String lastName) {
            this.lastName = lastName;
        }

        public Long getId() {
            return id;
        }

        public void setId(Long id) {
            this.id = id;
        }
    }

这是 UserService.java

package com.proxi.user;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceUnit;

import org.springframework.transaction.annotation.Transactional;

/**
 * Performs user related operations.
 * 
 */
public class UserService {

    @PersistenceUnit
    private EntityManagerFactory entityManagerFactory;

    @Transactional
    public User save(User user) {
        EntityManager entityManager = entityManagerFactory.createEntityManager();

        if (user.getId() == null) {
            entityManager.persist(user);
            return user;
        } else {
            return entityManager.merge(user);
        }
    }

    public User findUser(String userid) {
        return null;
    }

    public User addUser(User user) {
        return save(user);
    }

    // /////////////////////// GETTERS AND SETTERS //////////////////////

    public EntityManagerFactory getEntityManagerFactory() {
        return entityManagerFactory;
    }

    public void setEntityManagerFactory(EntityManagerFactory entityManagerFactory) {
        this.entityManagerFactory = entityManagerFactory;
    }
}
4

4 回答 4

1

内部异常:java.sql.SQLSyntaxErrorException:对象名称已经存在:USER 在语句 [CREATE TABLE 用户(id BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 1,INCREMENT BY 1)NOT NULL,first_name VARCHAR(255),last_name VARCHAR( 255), 主键 (id))]

这似乎是问题所在:Spring / EclipseLink 正在尝试创建一个已经存在的表。

尝试从您的 xml 上下文中删除此行:

<property name="generateDdl" value="true" />
于 2012-04-26T12:18:56.527 回答
1

我已经在这个问题上搜索了好几天,我能想到的最好的结果是在本教程中对 JPA 的限制做一个小注释,标题为:EclipseLink JPA Deployed on Tomcat 6 using Eclipse WTP。相关部分说:

由于 Tomcat 不是与 Java EE 5 兼容的服务器,因此 JPA 存在一些限制。

  • 没有动态编织(仪器)——实体的静态编织仍然可以通过 EclipseLink 获得。
  • 无法@EJB注入会话 bean(包含EntityManager) - 直接使用持久性工厂和管理器。
  • 没有@PersistenceContext注入容器管理的持久性单元可用 - 使用 Persistence.createEntityManagerFactory(JTA_PU_NAME)

我认为后两点适用于我遇到的问题。正如我所说,我可以让它与测试代码片段一起工作,但是当我尝试正确连接它时,我遇到了问题。因此,没有任何其他答案,我认为这是我将不得不接受的答案。欢迎任何进一步的见解,因为我不觉得这是一个非常令人满意的答案。

于 2012-04-29T22:51:16.443 回答
0

@chrisjleu 你非常接近。我通过将 eclipse 链接设置为使用静态编织来使其工作:

private static final Properties jpaProperties = new Properties();
static {
    jpaProperties.put("eclipselink.logging.level", "INFO");
    jpaProperties.put("eclipselink.weaving", "static");
}

并将其添加到LocalContainerEntityManagerFactoryBean.setJpaProperties(jpaProperties)

为了让静态编织工作,我正在使用 AspectJ。我的项目在 Maven 中,所以我使用以下插件:

            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>aspectj-maven-plugin</artifactId>
                <version>1.2</version>
                <!-- NB: do not use 1.3 or 1.3.x due to MASPECTJ-90 and do not use 1.4 
                    due to declare parents issue -->
                <dependencies>
                    <!-- NB: You must use Maven 2.0.9 or above or these are ignored (see 
                        MNG-2972) -->
                    <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>aspectjrt</artifactId>
                        <version>${version.aspectj}</version>
                    </dependency>
                    <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>aspectjtools</artifactId>
                        <version>${version.aspectj}</version>
                    </dependency>
                </dependencies>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>test-compile</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <outxml>true</outxml>
                    <aspectLibraries>
                        <aspectLibrary>
                            <groupId>org.springframework</groupId>
                            <artifactId>spring-aspects</artifactId>
                        </aspectLibrary>
                    </aspectLibraries>
                    <source>${version.java}</source>
                    <target>${version.java}</target>
                </configuration>
            </plugin>
于 2013-04-02T15:47:45.023 回答
0

您的persistence.xml文件是否存在于项目中?
如果是这种情况persistence.xml,请从项目中完全删除。该文件在某种程度上与packagesToScan属性冲突,即使您没有在配置中的任何地方明确提及它。我自己也遇到过这种特殊情况。

于 2013-02-21T10:14:15.613 回答