序列号的JPA映射错误

问题描述:

我一直在构建应用程序的一部分以坚持用户的仪表板对象,并且JPA一直在困扰我很久。序列号的JPA映射错误

我有一个抽象的Widget类,所有的仪表板对象将随着更多的开发而延伸。它们包含在通过JPA持久化的WidgetList类中。对我来说,代码看起来不错,但我仍然是Java EE 6和JPA的新手。当我尝试部署,我收到以下错误:

Exception [EclipseLink-41] (Eclipse Persistence Services - 2.0.1.v20100213-r6600): org.eclipse.persistence.exceptions.DescriptorException 
Exception Description: A non-read-only mapping must be defined for the sequence number field. 
Descriptor: RelationalDescriptor(ui.dashboard.widgetlist.WidgetList --> [DatabaseTable(WIDGETLIST)]) 
Runtime Exceptions: 
--------------------------------------------------------- 
     at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.initializeDescriptors(DatabaseSessionImpl.java:478) 
     at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.initializeDescriptors(DatabaseSessionImpl.java:406) 
     at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.postConnectDatasource(DatabaseSessionImpl.java:671) 
     at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.loginAndDetectDatasource(DatabaseSessionImpl.java:620) 
     at org.eclipse.persistence.internal.jpa.EntityManagerFactoryProvider.login(EntityManagerFactoryProvider.java:228) 
     at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:369) 
     at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.getServerSession(EntityManagerFactoryImpl.java:151) 
     at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManagerImpl(EntityManagerFactoryImpl.java:207) 
     at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:202) 
     at com.sun.enterprise.container.common.impl.EntityManagerWrapper._getDelegate(EntityManagerWrapper.java:197) 
     at com.sun.enterprise.container.common.impl.EntityManagerWrapper.createNamedQuery(EntityManagerWrapper.java:554) 
     at ca.comdev.cdip.mis.enterpriseportal.workflow.task.reminder.ReminderJpaDao.readAll(ReminderJpaDao.java:71) 
     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.glassfish.ejb.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1056) 
     at org.glassfish.ejb.security.application.EJBSecurityManager.invoke(EJBSecurityManager.java:1128) 
     at com.sun.ejb.containers.BaseContainer.invokeBeanMethod(BaseContainer.java:5292) 
     at com.sun.ejb.EjbInvocation.invokeBeanMethod(EjbInvocation.java:615) 
     at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:797) 
     at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:567) 
     at org.jboss.weld.ejb.SessionBeanInterceptor.aroundInvoke(SessionBeanInterceptor.java:57) 
     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 com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:858) 
     at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:797) 
     at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:567) 
     at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.doAround(SystemInterceptorProxy.java:157) 
     at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.aroundInvoke(SystemInterceptorProxy.java:139) 
     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 com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:858) 
     at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:797) 
     at com.sun.ejb.containers.interceptors.InterceptorManager.intercept(InterceptorManager.java:367) 
     at com.sun.ejb.containers.BaseContainer.__intercept(BaseContainer.java:5264) 
     at com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:5252) 
     at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:190) 
     at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:84) 
     at $Proxy188.readAll(Unknown Source) 
     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.jboss.weld.util.reflection.SecureReflections$13.work(SecureReflections.java:304) 
     at org.jboss.weld.util.reflection.SecureReflectionAccess.run(SecureReflectionAccess.java:54) 
     at org.jboss.weld.util.reflection.SecureReflectionAccess.runAsInvocation(SecureReflectionAccess.java:163) 
     at org.jboss.weld.util.reflection.SecureReflections.invoke(SecureReflections.java:298) 
     at org.jboss.weld.bean.proxy.EnterpriseBeanProxyMethodHandler.invoke(EnterpriseBeanProxyMethodHandler.java:127) 
     at org.jboss.weld.util.CleanableMethodHandler.invoke(CleanableMethodHandler.java:43) 
     at workflow.task.reminder.ReminderDao_$$_javassist_79.readAll(ReminderDao_$$_javassist_79.java) 
     at workflow.task.reminder.ReminderSchedulerImpl.retrieveAllReminders(ReminderSchedulerImpl.java:117) 
     at workflow.task.reminder.ReminderSchedulerImpl.initialize(ReminderSchedulerImpl.java:92) 
     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 com.sun.ejb.containers.interceptors.BeanCallbackInterceptor.intercept(InterceptorManager.java:1006) 
     at com.sun.ejb.containers.interceptors.CallbackChainImpl.invokeNext(CallbackChainImpl.java:61) 
     at com.sun.ejb.containers.interceptors.CallbackInvocationContext.proceed(CallbackInvocationContext.java:109) 
     at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.doCallback(SystemInterceptorProxy.java:133) 
     at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.init(SystemInterceptorProxy.java:115) 
     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 com.sun.ejb.containers.interceptors.CallbackInterceptor.intercept(InterceptorManager.java:961) 
     at com.sun.ejb.containers.interceptors.CallbackChainImpl.invokeNext(CallbackChainImpl.java:61) 
     at com.sun.ejb.containers.interceptors.InterceptorManager.intercept(InterceptorManager.java:390) 
     at com.sun.ejb.containers.interceptors.InterceptorManager.intercept(InterceptorManager.java:373) 
     at com.sun.ejb.containers.AbstractSingletonContainer.createSingletonEJB(AbstractSingletonContainer.java:521) 
     at com.sun.ejb.containers.AbstractSingletonContainer.access$100(AbstractSingletonContainer.java:74) 
     at com.sun.ejb.containers.AbstractSingletonContainer$SingletonContextFactory.create(AbstractSingletonContainer.java:696) 
     at com.sun.ejb.containers.AbstractSingletonContainer.instantiateSingletonInstance(AbstractSingletonContainer.java:444) 
     at org.glassfish.ejb.startup.SingletonLifeCycleManager.initializeSingleton(SingletonLifeCycleManager.java:213) 
     at org.glassfish.ejb.startup.SingletonLifeCycleManager.initializeSingleton(SingletonLifeCycleManager.java:174) 
     at org.glassfish.ejb.startup.SingletonLifeCycleManager.doStartup(SingletonLifeCycleManager.java:152) 
     at org.glassfish.ejb.startup.EjbApplication.start(EjbApplication.java:150) 
     at org.glassfish.internal.data.EngineRef.start(EngineRef.java:126) 
     at org.glassfish.internal.data.ModuleInfo.start(ModuleInfo.java:241) 
     at org.glassfish.internal.data.ApplicationInfo.start(ApplicationInfo.java:236) 
     at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:339) 
     at com.sun.enterprise.v3.server.ApplicationLoaderService.processApplication(ApplicationLoaderService.java:362) 
     at com.sun.enterprise.v3.server.ApplicationLoaderService.postConstruct(ApplicationLoaderService.java:185) 
     at com.sun.hk2.component.AbstractWombImpl.inject(AbstractWombImpl.java:174) 
     at com.sun.hk2.component.ConstructorWomb$1.run(ConstructorWomb.java:87) 
     at java.security.AccessController.doPrivileged(Native Method) 
     at com.sun.hk2.component.ConstructorWomb.initialize(ConstructorWomb.java:84) 
     at com.sun.hk2.component.AbstractWombImpl.get(AbstractWombImpl.java:77) 
     at com.sun.hk2.component.SingletonInhabitant.get(SingletonInhabitant.java:58) 
     at com.sun.hk2.component.LazyInhabitant.get(LazyInhabitant.java:107) 
     at com.sun.hk2.component.AbstractInhabitantImpl.get(AbstractInhabitantImpl.java:60) 
     at com.sun.enterprise.v3.server.AppServerStartup.run(AppServerStartup.java:236) 
     at com.sun.enterprise.v3.server.AppServerStartup.start(AppServerStartup.java:128) 
     at com.sun.enterprise.module.bootstrap.Main.launch(Main.java:457) 
     at com.sun.enterprise.module.bootstrap.Main.launch(Main.java:401) 
     at org.jvnet.hk2.osgiadapter.HK2Main.start(HK2Main.java:125) 
     at org.apache.felix.framework.util.SecureAction.startActivator(SecureAction.java:640) 
     at org.apache.felix.framework.Felix.activateBundle(Felix.java:1700) 
     at org.apache.felix.framework.Felix.startBundle(Felix.java:1622) 
     at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:915) 
     at org.jvnet.hk2.osgimain.Main.start(Main.java:140) 
     at org.apache.felix.framework.util.SecureAction.startActivator(SecureAction.java:640) 
     at org.apache.felix.framework.Felix.activateBundle(Felix.java:1700) 
     at org.apache.felix.framework.Felix.startBundle(Felix.java:1622) 
     at org.apache.felix.framework.Felix.setActiveStartLevel(Felix.java:1077) 
     at org.apache.felix.framework.StartLevelImpl.run(StartLevelImpl.java:264) 
     at java.lang.Thread.run(Thread.java:619) 

我的widgetList代码是在这里:

package ui.dashboard.widgetlist; 

import principals.Principal; 
import ui.dashboard.widgets.Widget; 
import java.io.Serializable; 
import java.util.LinkedHashSet; 
import java.util.Set; 
import javax.persistence.CascadeType; 
import javax.persistence.Column; 
import javax.persistence.Entity; 
import javax.persistence.FetchType; 
import javax.persistence.GeneratedValue; 
import javax.persistence.Id; 
import javax.persistence.MapsId; 
import javax.persistence.NamedQueries; 
import javax.persistence.NamedQuery; 
import javax.persistence.OneToMany; 
import javax.persistence.OneToOne; 
import javax.persistence.Table; 

/** 
* The storage class for the Widgets that a user has saved to their 
* profile. 
* @author mtatham 
*/ 
@Entity 
@Table(name="WIDGETLIST") 
@NamedQueries({ 
    @NamedQuery(name="widgetlist.byOwner",query="select w from WidgetList w where w.owner = :owner") 
}) 
public class WidgetList implements Serializable { 

    /** 
    * The system generated ID 
    */ 

    @Id 
    @GeneratedValue 
    @Column(name="WIDGETLIST_ID", nullable = false, insertable=true,updatable=true) 
    private Integer id; 

    /** 
    * The user principal used for the lookup on the database 
    */ 
    @OneToOne @MapsId 
    private Principal owner; 

    /** 
    * The Set of Widgets associated with the owner. 
    */ 
    @OneToMany(mappedBy="currentWidgetList", cascade=CascadeType.ALL, orphanRemoval=true,fetch=FetchType.LAZY) 
    private Set<Widget> widgetList = new LinkedHashSet<Widget>(); 

    public Integer getId() { 
     return id; 
    } 

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

    public Principal getOwner() { 
     return owner; 
    } 

    public void setOwner(Principal owner) { 
     this.owner = owner; 
    } 

    public Set<Widget> getWidgetList() { 
     return this.widgetList; 
    } 

    public void setWidgetList(Set<Widget> widgetList) { 
     this.widgetList = widgetList; 
    } 

    /** 
    * Adds a new Widget to the Set. If the set already contains the 
    * unique Widget being added, the method will end gracefully. 
    * @param widget 
    */ 
    public void addWidget(Widget widget) { 
     if(this.widgetList.contains(widget)){ 
      return; 
     }else { 
      widget.setCurrentWidgetList(this); 
      this.widgetList.add(widget); 
     } 
    } 

    @Override 
    public String toString() { 
     if(getOwner()!=null){ 
      return getId() + " - " + getOwner().getName(); 
     } else{ 
      return getId().toString(); 
     } 
    } 



    public boolean equals(WidgetList wl) { 
     return true; 
    } 

而且,为了完整起见,的widgetList被存储抽象的Widget类:

import ui.dashboard.widgetlist.WidgetList; 
import java.io.Serializable; 
import javax.persistence.Column; 
import javax.persistence.DiscriminatorColumn; 
import javax.persistence.Entity; 
import javax.persistence.GeneratedValue; 
import javax.persistence.GenerationType; 
import javax.persistence.Id; 
import javax.persistence.Inheritance; 
import javax.persistence.InheritanceType; 
import javax.persistence.JoinColumn; 
import javax.persistence.ManyToOne; 
import javax.persistence.Table; 

/** 
* This is the class used as the template for all of the customized widgets 
* that will be included on the Enterprise Portal dashboard. This abstract 
* class will contain the generic information required for the user's 
* customized dashboard. 
* 
* Any new widgets for the dashboard must extend this class and add their 
* custom data elements. 
* @author mtatham 
*/ 
@Entity 
@Table(name = "WIDGETS") 
@Inheritance(strategy = InheritanceType.JOINED) 
@DiscriminatorColumn(name = "TYPE") 
public abstract class Widget implements Serializable{ 

    /** 
    * The ID of the Widget. Generated programmatically. 
    */ 
    @Id 
    @GeneratedValue 
    @Column(name="WIDGET_ID") 
    private int id; 
    /** 
    * The id name used on the JSF page to identify the object 
    */ 
    @Column(name = "IDNAME") 
    private String idName; 

    /** 
    * The WidgetList this Widget is currently assigned to. 
    */ 
    @ManyToOne(optional=false) 
    @JoinColumn(name = "CURRENT_WIDGETLIST_ID", nullable=false) 
    private WidgetList currentWidgetList; 
    /** 
    * Header name that is visible on the widget menu 
    */ 
    @Column(name = "HEADER") 
    private String headerName; 
    /** 
    * JSF property that determines if a user can hide the widget. This will 
    * be defaulted to 'true'. The only other value acceptable is 'false'. 
    * 
    * This is a String element even though there are only boolean values 
    * due to the data being used in the xhtml pages. 
    */ 
    @Column(name = "TOGGLEABLE") 
    private String toggleable = "true"; 
    /** 
    * JSF property that determines if a user can close a widget to remove it 
    * from the dashboard. This will be defaulted to 'true'. The only other 
    * value acceptable is 'false'. 
    * 
    * This is a String element even though there are only boolean values 
    * due to the data being used in the xhtml pages. 
    */ 
    @Column(name = "CLOSABLE") 
    private String closable = "true"; 
    /** 
    * This is an override to change the CSS style on the widget. 
    */ 
    @Column(name = "STYLE") 
    private String style; 
    /** 
    * Determines what part of the widget can be grabbed with the cursor to 
    * move it around. The default will be the header of the widget. 
    */ 
    @Column(name = "HANDLE") 
    private String handle = ".ui-panel-titlebar"; 
    /** 
    * Determines the transparency of the widget while it is being dragged. 
    * This is a decimal number between 0 and 1. The default will be 1. 
    */ 
    @Column(name = "OPACITY") 
    private String opacity = "1"; 

    /** 
    * This is the form object that the widget will be loaded into. This will 
    * be defaulted to widgetTemplate.xhtml. It can be overwritten in the 
    * extended classes. 
    */ 
    @Column(name="FORM") 
    private String xhtmlForm = ""; 

    public WidgetList getCurrentWidgetList() { 
     return currentWidgetList; 
    } 

    public void setCurrentWidgetList(WidgetList widgetList) { 
     this.currentWidgetList = widgetList; 
    } 

    public String getClosable() { 
     return closable; 
    } 

    public String getHandle() { 
     return handle; 
    } 

    public String getHeaderName() { 
     return headerName; 
    } 

    public int getId() { 
     return id; 
    } 

    public String getIdName() { 
     return idName; 
    } 

    public String getOpacity() { 
     return opacity; 
    } 

    public String getStyle() { 
     return style; 
    } 

    public String getToggleable() { 
     return toggleable; 
    } 

    public String getXhtmlForm() { 
     return xhtmlForm; 
    } 

    public void setClosable(String closable) { 
     this.closable = closable; 
    } 

    public void setHandle(String handle) { 
     this.handle = handle; 
    } 

    public void setHeaderName(String headerName) { 
     this.headerName = headerName; 
    } 

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

    public void setIdName(String idName) { 
     this.idName = idName; 
    } 

    public void setOpacity(String opacity) { 
     this.opacity = opacity; 
    } 

    public void setStyle(String style) { 
     this.style = style; 
    } 

    public void setToggleable(String toggleable) { 
     this.toggleable = toggleable; 
    } 

    public void setXhtmlForm(String xhtmlForm) { 
     this.xhtmlForm = xhtmlForm; 
    } 

} 

这是用Java EE 6编写的,使用JPA,使用MySQL数据库部署到Glassfish 3.0.1服务器。我使用NetBeans 6.9.1作为我的开发环境,并在我的机器上安装了jdk 1.6.0_20。我们使用这个版本是因为我们依赖于我们仍在维护的较老的软件。

我对该问题的理解是,WidgetList类上的@Id注释字段“id”被标识为只读。我试图手动强制它通过使用@Column注释将其识别为非只读字段,但无济于事。

我一直在通过oracle论坛,在这里在*和任何地方谷歌可以带我,但我已经绝对没有找到解决方案的运气。我对EclipseLink wiki page抱有很高的期望,但事实证明它也是一个破产。实际的错误描述告诉我什么都没有。

如果任何人有任何想法,他们将不胜感激。

谢谢, 马特泰胜

我的避风港“T使用的EclipseLink自己,但也许你必须定义序列使用?看看@Specifying a Sequence。不知道,错误信息没有意义。

+0

我知道我忘了添加一些东西。我曾尝试向@Id添加序列。策略= GenerationType.SEQUENCE本身并添加手动创建的生成器。但那是一个早期尝试,我忘记了。 – mtatham 2011-03-16 21:07:10

+0

现在它在工作吗? – Behrang 2011-03-17 02:42:03

我不完全理解为什么会出现此特定错误,但似乎我错误地使用了@MapsId注释。从我已经能够找到的文档中,注释应该被用来链接到另一个类中的@EmbeddedId主键。我正在使用它来映射到我的课程的一部分,这个JPA将隐式地做,而不必被告知。

删除@MapsId标签解决了这个问题,并允许JPA创建我的数据库表而没有问题。

+0

不要忘记将答案标记为答案! – Patricia 2011-03-21 11:52:43

我最近有同样的错误。在我看来,这可能是由于使用InheritanceType.JOINED策略为基础摘要实体造成的。

在抽象超类上使用SINGLE_TABLE(缺省值),在子类上使用JOINED适用于我。

古老的问题,我知道,但是,简要地说:这个不可思议的消息只表明你有一个抽象的实体,没有具体的后代实体定义或可发现任何地方。而已。它与序列或只读映射无关,或类似的东西。添加一个虚拟的具体实体,从Widget延伸,你会没事的。

我面临同样的问题。

当涉及到@Id时,EclipseLink根本不喜欢updatable = true@Column中。