如何将 JPA 对象从 AppEngine 发送到 GWT?类型 'org.datanucleus.store.types.sco.simple.Date'



我正在尝试使用 AppEngine 和 JPA 持久性保存和加载带有日期的对象。但是,当我加载对象并尝试将其发送到 GWT 时,它会引发以下异常:

SEVERE: javax.servlet.ServletContext log: 调度传入 RPC 调用时的异常 com.google.gwt.user.client.rpc.SerializationException:类型'org.datanucleus.store.types.sco.simple.Date'未包含在此序列化策略可以序列化的类型集中,或者无法加载其类对象。出于安全目的,此类型不会被序列化。: 实例 = 2013 年 10 月 9 日星期三 22:47:22 EDT

这是我的服务器查询:

        Query q = em.createQuery("select ee from EmailEvent ee");
        al.addAll( q.getResultList() );
        for (EmailEvent row: al) {
            log.info(row.getSenderEmail() + ", " + row.getSendDate());
        }
    return al;

这是一些日志:

Oct 09, 2013 10:47:43 PM com.onixnet.sdm.server.SDMServiceImpl getSentItems
INFO: chloe@domain.com, Wed Oct 09 22:47:21 EDT 2013

这是有问题的类:

package com.onixnet.sdm.shared;
import java.util.Date;
@Entity
public class EmailEvent implements Serializable {
...
private Date sendDate;

我尝试过java.util.Date和java.sql.Date。我尝试在 AppEngine 管理界面中删除实体的所有行。两次它都会正确保存和加载,但不会序列化。(另一个错误是"org.datanucleus.store.types.sco.simple.SqlDate"无法序列化。当它是java.sql.date时,它作为长文件保存到数据存储中。

AppEngine SDK v1.8.5, Java 7, GWT 2.5.1.

找到了:http://bpossolo.blogspot.com/2013/03/upgrading-gae-app-from-jpa1-to-jpa2.html

增强的日期属性

我首先要说的是,这种差异被证明是极其 烦人。

在 JPA1 中,具有 java.util.Date 属性的实体的功能与 人们会期待。您可以使用新的 Date(( 设置属性,持久 实体,正常加载它,属性始终是真实的 java.util.Date.

在 JPA2 中,这种情况发生了变化。现在,当一个带有java.util.Date的实体 属性持久化到数据存储,数据核心替换日期 具有 org.datanucleus.store.types.sco.simple.Date 的实例。

问题是org.datanucleus.store.types.sco.simple.Date 不能通过 GWT-RPC 序列化。这意味着任何具有日期的实体 必须分离已从数据存储检索的属性 从 GWT-RPC 之前的实体管理器持久性上下文 发生序列化。在分离期间,所有那些特殊的日期 对象被转换回java.util.Date对象。

有几种方法可以做到这一点。

第一个选项是显式分离持久对象 叫

entityManager.detach(obj(.

还有一种方法可以将分离级联到子实体,尽管 您可能不需要担心这一点,因为您的 GAE 数据存储实体可能没有嵌套对象图。

第二个选项是设置一个数据核心属性,该属性自动 在实体管理器关闭时分离所有对象。这是 如果您可以确保您的实体经理已关闭,则建议使用 在 GWT-RPC 序列化发生之前。在持久性.xml文件中,添加

True 是默认行为,但最好是明确的。

如果您使用的是"在视图中打开会话"样式模式(其中 在 servlet 过滤器中创建实体管理器,并将其存储在 在 HTTP 请求期间使用的线程局部变量(,然后 "关闭时分离"将不起作用,因为 GWT-RPC 序列化将 在您的实体管理器关闭之前发生。

第三个选项是设置一个数据核心属性,该属性自动 在提交时分离所有对象。如果您使用的是 "在视图中打开会话"模式。在持久性.xml文件中,添加

您可以在此处阅读有关分离的更多信息。当心数据核泄漏 日期

想象一下以下场景。

@Entity公共类用户 { @Id 长键; 日期成员自;}

public class ProfileViewDTO { Date userJoinDate; }

/

/in GWT-RPC servlet User user = (User(entityManager.find(User.class, 用户密钥(;

ProfileViewDTO

dto = new ProfileViewDTO((; dto.userJoinDate = user.memberSince;日期泄漏!

entityManager.detach(user(; entityManager.close((;

返回 DTO;//发生序列化错误!

如您所见,数据核心日期对象已泄漏,将导致 序列化错误。若要避免这种情况,请在之前分离用户 设置 DTO 的属性或显式复制日期。它也是 在 GAE 内存缓存中缓存对象之前执行此操作很重要。

到处都有"日期泄漏",这就是为什么我发现了这个新的JPA2 行为真的很烦人。我花了一段时间才找到他们 并修复它们。

我用了

for (EmailEvent row: al) {
        em.detach(row);
        log.info(row.getSenderEmail() + ", " + row.getSendDate());
}

我还设置了属性(但这似乎没有帮助(。

相关内容

最新更新