對於我的EclipseLink和Spring(MVC和spring-data)版本3.1.1設置的另一個問題:Spring實體bean未知。使用新的Spring 3.1 packagesToScan屬性並且沒有persistence.xml
我試圖讓JPA無需使用根據this article的persistence.xml文件。在文章中它說:
通常,JPA通過META-INF/persistence.xml文件定義了一個持久單元。從Spring 3.1開始,不再需要此XML文件 - LocalContainerEntityManagerFactoryBean 現在支持'packagesToScan'屬性,其中可以指定用於掃描 for @Entity類的包。
persistence.xml文件是要刪除的最後一塊XML - 現在,JPA可以完全沒有XML設置。
我知道如果有人使用persistence.xml文件,這裏所有的實體類都應該在這裏聲明。但是,我試圖使用packagesToScan
屬性來代替。下面是完整的啓動日誌和向servlet發出一個請求後產生的錯誤,最終嘗試在數據庫中創建一個新用戶。它似乎沒有認識到User
對象是一個實體。由於我對Spring沒有多少經驗,所以我想知道是否有人首先會發現我正在犯的錯誤,但除此之外,我知道調試它的最好方法。我想知道什麼實體對象已被EntityManagerFactory識別。我的備份選項是切換到使用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: [email protected] is not a known entity type.] with root cause
java.lang.IllegalArgumentException: Object: [email protected] 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)
根-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;
}
}
這確實消除了內部異常,但主要問題依然存在。 – chrisjleu 2012-04-26 12:48:21