java - Spring 实体 bean 未知。使用新的 Spring 3.1 packagesToScan 属性并且没有 persistence.xml

标签 java spring jpa spring-data-jpa

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

我正在尝试根据 this article 在不使用 persistence.xml 文件的情况下让 JPA 工作。文章中写道:

Usually, JPA defines a persistence unit through the META-INF/persistence.xml file. Starting with Spring 3.1, this XML file is no longer necessary – the LocalContainerEntityManagerFactoryBean now supports a ‘packagesToScan’ property where the packages to scan for @Entity classes can be specified.

The persistence.xml file was the last piece of XML to be removed – now, JPA can be fully set up with no XML.

据我了解,如果要使用 persistence.xml 文件,则应在此处声明所有实体类。但是,我尝试改用 packagesToScan 属性。下面是完整的启动日志以及向 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)

root-context.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>

User.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;
    }
}

最佳答案

Internal Exception: java.sql.SQLSyntaxErrorException: object name already exists: USER in statement [CREATE TABLE user (id BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1) NOT NULL, first_name VARCHAR(255), last_name VARCHAR(255), PRIMARY KEY (id))]

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

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

<property name="generateDdl" value="true" />

关于java - Spring 实体 bean 未知。使用新的 Spring 3.1 packagesToScan 属性并且没有 persistence.xml,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10331490/

相关文章:

java - 如何在 Java Netbeans 平台模块化项目中设置 VM 选项?

spring - BCryptPasswordEncoder.matches() 方法的签名不适用于参数类型 : (java. lang.String, java.lang.String)

java - Spring数据JPA : InvalidDataAccessApiUsageException for @Transactional

java - 如何访问 Hibernate 统计信息

java - Spring关系获取子id而不加载子类

java - JPA:应用程序必须提供 JDBC 连接

java - 加载相关主页但不登录该网站

java - MeCab 路径参数在 Windows 上不接受空格

java - 在 Apache FOP 中,如何将自定义目录中的字体优先于系统字体?

Spring Data Neo4j 4 - 找不到类的标识字段