使用 Gilead 持久化具有继承的类

Posted

技术标签:

【中文标题】使用 Gilead 持久化具有继承的类【英文标题】:Persist classes with inheritance using Gilead 【发布时间】:2009-08-21 20:54:37 【问题描述】:

我正在使用 Gilead 将我的实体持久保存在我的 GWT 项目中,但我遇到了一个问题。我想创建一个父类来保存一些在我的实体中通用的属性(id 等)。持久化时出现空指针异常。

父类:

public abstract class Entity extends LightEntity implements Serializable 
    protected Long id;
    public Entity()

儿童班:

public class Person extends Entity  
    private String firstName;
    private String lastName;
    public Person()

休眠映射文件:

<hibernate-mapping>
    <class name="com.domain.Entity" abstract="true" >
        <id name="id" type="long">
                <column name="ID"/>
                <generator class="native" />
            </id>
        <union-subclass name="com.domain.Person" table="PERSON">
            <property name="id" type="long" />
            <property name="firstName" type="string">
                <column name="FIRST_NAME" length="45" not-null="true" />
            </property>
            <property name="lastName" type="string">
                <column name="LAST_NAME" length="45" not-null="true" />
            </property>
        </union-subclass>
    </class>
</hibernate-mapping>

持久化时的堆栈跟踪:

java.lang.NullPointerException 在 net.sf.gilead.gwt.PersistentRemoteService.processCall(PersistentRemoteService.java:170) 在 com.google.gwt.user.server.rpc.RemoteServiceServlet.doPost(RemoteServiceServlet.java:86) 在 javax.servlet.http.HttpServlet.service(HttpServlet.java:754) 在 javax.servlet.http.HttpServlet.service(HttpServlet.java:847) 在 org.apache.catalina.core.ApplicationFilterChain.servletService(ApplicationFilterChain.java:427) 在 org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:315) 在 org.apache.catalina.core.StandardContextValve.invokeInternal(StandardContextValve.java:287) 在 org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:218) 在 org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:648) 在 org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:593) 在 com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:94) 在 com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:98) 在 org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:222) 在 org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:648) 在 org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:593) 在 org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:587) 在 org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1096) 在 org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:166) 在 org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:648) 在 org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:593) 在 org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:587) 在 org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1096) 在 org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:288) 在 com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.invokeAdapter(DefaultProcessorTask.java:647) 在 com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.doProcess(DefaultProcessorTask.java:579) 在 com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.process(DefaultProcessorTask.java:831) 在 com.sun.enterprise.web.connector.grizzly.DefaultReadTask.executeProcessorTask(DefaultReadTask.java:341) 在 com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:263) 在 com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:214) 在 com.sun.enterprise.web.portunif.PortUnificationPipeline$PUTask.doTask(PortUnificationPipeline.java:380) 在 com.sun.enterprise.web.connector.grizzly.TaskBase.run(TaskBase.java:265) 在 com.sun.enterprise.web.connector.grizzly.ssl.SSLWorkerThread.run(SSLWorkerThread.java:106)

【问题讨论】:

【参考方案1】:

您使用的是吉利德 1.2.2 吗?

如果是,升级吉利德。然后再次运行并检查新的异常消息。很可能只是某种错误配置。

完整解释:

如果查看1.2.1版本的PersistentRemoteService.java的源代码

PersistentRemoteService.java v1.2.1

在第 170 行,您会看到以下行

return RPCCopy.getInstance().encodeResponseForFailure(null, ex, rpcRequest.getSerializationPolicy());

如果rpcRequest 为空,这显然会失败并显示NullPointerException

在第 143 行时会发生这种情况

// Decode request
rpcRequest = RPCCopy.getInstance().decodeRequest(payload, this.getClass(), this);

decodeRequest-方法抛出一个IncompatibleRemoteServiceException。在你的情况下它会做什么。

从版本 1.2.2 开始,第 170 行更改为

if (rpcRequest != null)

  return RPCCopy.getInstance().encodeResponseForFailure(null, ex, rpcRequest.getSerializationPolicy());

else

    return RPCCopy.getInstance().encodeResponseForFailure(null, ex);

现在您应该得到正确的异常 (IncompatibleRemoteServiceException),它指出了真正的问题。

你也可以在SVN中查看对应的commit/fix

Bad exception fix (issue 2663344)

以及Bug-Tracker for Gilead中对应的问题条目

Wrong exception

所以这个问题自 2009 年 2 月 7 日或 Gilead 版本 1.2.2(2009 年 3 月 13 日)起在 SVN 中得到解决

【讨论】:

【参考方案2】:

不确定是否有帮助。只是一种猜测。您是否尝试过非抽象超类?有时在序列化之前手动取消/急切加载惰性对象引用或列表(当然在当前事务范围之外)是可行的,并且不需要 Gilead。

【讨论】:

以上是关于使用 Gilead 持久化具有继承的类的主要内容,如果未能解决你的问题,请参考以下文章

如何将目录设置为具有持久组权限?

有没有办法在继承期间持久化装饰器?

递归python函数中的持久对象

传递给持久化的分离实体:JPA 继承

Hibernate之集合映射

Java 持久性继承中的序列号