序列号的JPA映射错误

时间:2011-03-16 18:55:24

标签: jpa eclipselink java-ee-6

我一直在构建一个应用程序的一部分来持久保存用户的仪表板对象,并且JPA一直困扰着我。

我有一个抽象的Widget类,所有的仪表板对象都会随着更多的开发而扩展。它们包含在WidgetList类中,该类通过JPA持久化。对我来说,代码看起来不错,但我仍然是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论坛,在stackoverflow和谷歌可以带我的任何地方,但我找到一个解决方案绝对没有运气。我对EclipseLink wiki page寄予厚望,但事实证明它也是一个半身像。实际的错误描述什么也没告诉我。

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

谢谢, 马特塔特姆

5 个答案:

答案 0 :(得分:2)

我不完全理解为什么会发生这种特殊错误,但似乎我错误地使用了@MapsId注释。从我能够找到的文档中,注释应该用于链接到另一个类中的@EmbeddedId主键。我正在使用它来映射到我班级的id,JPA将隐式执行而不必被告知。

删除@MapsId标记解决了该问题,并允许JPA无问题地创建我的数据库表。

答案 1 :(得分:1)

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

答案 2 :(得分:0)

我自己没有使用过EclipseLink,但也许您必须定义要使用的Sequence?看看@ Specifying a Sequence。不确定,错误信息确实没有意义。

答案 3 :(得分:0)

我最近有同样的错误。在我看来,它可能是由基础抽象实体使用InheritanceType.JOINED策略引起的。

在抽象超类上使用SINGLE_TABLE(默认值),在子类上使用JOINED对我有用。

答案 4 :(得分:0)

我遇到了同样的问题。

对于updatable = true,EclipseLink根本不喜欢@Column中的@Id