`
iamxiaole
  • 浏览: 19306 次
  • 性别: Icon_minigender_1
  • 来自: 广州
最近访客 更多访客>>
社区版块
存档分类
最新评论

Part5 - Serialized Fields

阅读更多
你好,欢迎来到第5part的“JDO/JPA Snippets That Work”,今天我们将讨论的是...

Serialized Fields

假设你有个model objects拥有一个非native datastore的(例如String或者Date)同时也不是一个有主,一对一关系的model object的字段。通常你可以在一条记录里用一个Embedded class包含住些record来保存这个字段的子字段。但如果Embedded class不够用的时候呢?

这时就可以用Serialized Fields了。

用jdo和jpa可以保存任何实现了java.io.Serializable接口的single prperty。

为了我们的例子程序,我们建立一个Person,一个ContactProfiles,一个ContactProfile, 和一个PhoneNumber的模型。一个Person只用一个ContactProfiles实例,而,一个ContactProfiles有多个ContactProfile实例,同时,一个ContactProfile有多个PhoneNumber实例。

现在我们程序要求是这样:当我们从datastore里retrieve一个Person时,需要同时load入这个Person的ContactProfiles.我们首先先用jdo或jpa来定义ContactProfiles,ContactProfile和PhoneNumber类先。
public static class ContactProfiles implements Serializable { 
    private final List<ContactProfile> profiles; 
    public ContactProfiles(List<ContactProfile> profiles) { 
      this.profiles = profiles; 
    } 
    public List<ContactProfile> get() { 
      return profiles; 
    } 
} 

public class ContactProfile implements Serializable { 
    private String profileName; 
    private List<PhoneNumber> phoneNumbers; 
    // getters and setters 
} 

public class PhoneNumber implements Serializable { 
    private String type; 
    private String number; 
    // getters and setters 
} 

JPA方式定义的Person类如下:
@Entity 
public class Person { 
    @Id 
    @GeneratedValue(strategy=GenerationType.IDENTITY) 
    private Key id; 
    @Lob 
    private ContactProfiles contactProfiles; 
    // getters and setters 
} 

JDO方式定义的Person类如下:
@PersistenceCapable(identityType = IdentityType.APPLICATION, detachable = 
"true") 
public class Person { 
    @PrimaryKey 
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) 
    private Key id; 
    @Persistent(serialized = "true") 
    private ContactProfiles contactProfiles; 
    // getters and setters 
} 


在这个例子里面,App Engine实现将Person.contactProfiles字段转换为一个实现了标准Java
serialization接口的com.google.appengine.api.datastore.Blobusing类。
这个Blob将以single property的形式存储在Person Entity里面。当你fetch一个Person的时候,相应的Blob将会经过一个独立的datastore rpc请求被反序列化,你将得到一个ContactProfiles实例和全部他关联的子对象。

当用这种做法时,有一些缺点你是应该意识到的。

第一,虽然你的应用知道ContactProfiles的结构,但datastroe并不知道,这导致你不能过滤或排序ContactProfile和PhoneNumber.第二,所有已知java serialization存在的问题都适用在这里。当你改进你的Serializable classes的时候,请必须考虑向后兼容。第三,你可能在观察ContactProfiles这个类的时候已经发现,为什么我们要用一个这么麻烦的ContactProfiles类而不直接用一个List<ContactProfile>呢?其原因就是update一个serialized field并不是好像update其他字段类型那么简单。DataNucleus并没有办法“看”得见你修改了serialized field,这就意味着他不会更新数据到datastore。然而,DataNucleus可以看到顶层的serialized field的改变。给Person类一个ContactProfiles一个引用可以便利我们去修改ConactProfiles而DataNucles又保证能意识到。
public void addContactProfile(Person p, ContactProfile cp) { 
    // update our serialized field 
    p.getContactProfiles().get().add(cp); 
    // give the person a new ContactProfiles reference so the update is 
detected 
    p.setContactProfiles(new ContactProfiles(p.getContactProfiles().get())); 
} 

最后一行我们设回一个新的ContactProfiles实例给Person是关键,同时也容易忘记的,所以请小心!如果你忘记这一步,你的更新将被忽略。

尽管我列出了以上的不足,但Serialized fields是一个保存structured data到一个记录到containing Entity的好方法。只要你不需要过滤和排序serialized fields,同时你记得这个特别的更新数据的要求,在某些时候serialized fields也无疑是一个方便的方法。


以下是原文
Hello hello and welcome to Episode 5 of JDO/JPA Snippets That Work.  Today
we'll be discussing....

Serialized Fields

Suppose one of your model objects has a field that isn't a native datastore
type like String or Date and isn't another model object, like the child of
an owned OneToOne relationship.  Oftentimes you can use an Embedded
class<http://code.google.com/appengine/docs/java/datastore/dataclasses.html...>to
store that field's sub-fields in the same record as the containing
record, but what if an Embedded class isn't sufficient?  This is where
Serialized Fields come in.  With JDO and JPA it's possible to store any
class that implements java.io.Serializable in a single property.
For our example lets model Person, ContactProfiles, ContactProfile, and
PhoneNumber.  A Person has exactly one ContactProfiles instance, a
ContactProfiles has some number of ContactProfile instances, and a
ContactProfile has some number of PhoneNumber instances.  Our application is
such that when we retrieve a Person from the datastore it always makes sense
to load their ContactProfiles as well.  We'll define ContactProfiles,
ContactProfile, and PhoneNumber first since they're the same whether we're
using JPA or JDO:

public static class ContactProfiles implements Serializable { 
    private final List<ContactProfile> profiles; 
    public ContactProfiles(List<ContactProfile> profiles) { 
      this.profiles = profiles; 
    } 
    public List<ContactProfile> get() { 
      return profiles; 
    } 
} 

public class ContactProfile implements Serializable { 
    private String profileName; 
    private List<PhoneNumber> phoneNumbers; 
    // getters and setters 
} 

public class PhoneNumber implements Serializable { 
    private String type; 
    private String number; 
    // getters and setters 
} 


The JPA Person definition:

@Entity 
public class Person { 
    @Id 
    @GeneratedValue(strategy=GenerationType.IDENTITY) 
    private Key id; 
    @Lob 
    private ContactProfiles contactProfiles; 
    // getters and setters 
} 


The JDO Person definition:

@PersistenceCapable(identityType = IdentityType.APPLICATION, detachable = 
"true") 
public class Person { 
    @PrimaryKey 
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) 
    private Key id; 
    @Persistent(serialized = "true") 
    private ContactProfiles contactProfiles; 
    // getters and setters 
} 


In this example the App Engine JDO/JPA implementation converts the
Person.contactProfiles field into a
com.google.appengine.api.datastore.Blobusing standard Java
serialization.  This Blob is then stored as a single
property on the Person Entity.  When you fetch a Person the corresponding
Entity is retrieved and the Blob is deserialized in just a single datastore
rpc, leaving you with a ContactProfiles instance and all its associated
sub-objects.

There are a few drawbacks to this approach that you should be aware of.
First, even though your application understands the structure of the bytes
that make up the ContactProfiles, the datastore does not.  As a result you
can't filter or sort on any of the properties of ContactProfile or
PhoneNumber.  Second, all the known gotchas associated with Java
serialization apply here.  If you evolve your Serializable classes make sure
you do it in a backwards compatible way!  Third, you might be looking at the
definition of the ContactProfiles class and thinking "Why are we bothering
with a ContactProfiles class when Person could just store
List<ContactProfile>?"  The reason is that updating a serialized field is
not as simple as updating other types of fields, and this extra layer of
indirection makes things a bit easier.  DataNucleus has no way of "seeing"
the changes you make to the internal values of a serialized field, and as a
result it doesn't know when it needs to flush changes to these fields to the
datastore.  However, DataNucleus *can* see when the top-level serialized
field reference changes.  Giving Person a reference to a ContactProfiles
object makes it easy for us to change ContactProfiles in a way that
DataNucleus is guaranteed to recognize:
public void addContactProfile(Person p, ContactProfile cp) { 
    // update our serialized field 
    p.getContactProfiles().get().add(cp); 
    // give the person a new ContactProfiles reference so the update is 
detected 
    p.setContactProfiles(new ContactProfiles(p.getContactProfiles().get())); 
} 


The last line where we set a new ContactProfiles instace back on the Person
is the key and it's easy to miss, so be careful!  If you forget this step
your updates will be ignored and you will be sad.
Despite the limitations I've listed, Serialized fields are a good way to
store structured data inside the record of a containing Entity.  As long as
you can get by without filtering or sorting on this data and you remember
that it has special update requirements, serialized fields will almost
certainly come in handy at some point.

Until next time,
Max

转载自:http://groups.google.com/group/google-appengine-java/browse_thread/thread/747ceed8396c0ed8#

说明:上面的中文翻译是我用自己能理解的方式翻译出来的,并不是逐字翻译,只作为自己参考用,并不十分精确。

其实个人觉得这个做法必须用到的地方可能不多哦。
分享到:
评论

相关推荐

    Laravel开发-eloquent-serialized-lob

    "Eloquent-Serialized-Lob" 是一个专门为Laravel5设计的Eloquent扩展,它允许我们序列化LOB(Large Object)类型的字段,比如BLOB或CLOB。LOB字段通常用来存储大块的数据,如图片、文档或长文本。 首先,我们需要...

    crud-user-with-serialized:用户注册,登录后即可访问

    在项目"crud-user-with-serialized-master"中,我们可以预期包含以下组件: 1. 用户模型(User Model):定义用户对象的属性(如用户名、密码、邮箱等)和方法。 2. 数据库接口(Database Interface):提供CRUD...

    vdom-serialized-patch:将虚拟dom补丁序列化为最小JSON对象(未维护)

    vdom序列化补丁 将修补程序序列化为非常有效的JSON格式,然后直接从该对象修补DOM。...安装 npm install vdom-serialized-patch用法 var h = require ( 'virtual-dom/h' ) ;var diff = require ( 'virtual-dom/di

    silverstripe-serialized-dataobject:SilverStripe 3和4数据库字段,允许使用序列化将任意数据保存在单个db字段中

    维修人员联系Zauberfisch 要求silverstripe /框架&gt; = 4.2安装composer require "zauberfisch/silverstripe-serialized-dataobject" 重建清单(冲洗)文献资料有关文档和示例,请参阅 。归因来自模块JavaScript和CSS

    Python库 | serialized-redis-interface-0.3.1.tar.gz

    资源分类:Python库 所属语言:Python 资源全名:serialized-redis-interface-0.3.1.tar.gz 资源来源:官方 安装方法:https://lanzao.blog.csdn.net/article/details/101784059

    chrome-unserialize-php-crx插件

    将php-serialized数据转换回用于人类可读的东西。 可以选择var_export或json 将php-serialized数据转换回用于人类可读的东西。 可以选择var_export或json 无法解决循环参考(如果真的需要,请在Github上提出问题) ...

    Serialized IRQ Support for PCI Systems

    ### 串行中断(Serialized IRQ)支持在PCI系统中的应用 #### 一、概述 《串行中断(Serialized IRQ)支持在PCI系统中的应用》这一文档由Compaq Computer Corporation、Cirrus Logic Incorporated、National ...

    nyla-spring-postit:PostIt是一个基于Spring Boot Web的邮件客户端

    PostIt是一个基于Spring Boot Web的邮件客户端。 它使用Apache Geode / GemFire中加载的...-name=UserProfile --type=PARTITION_PERSISTENT要读取的配置Geode PDX序列化configure pdx --read-serialized=true --disk

    NextJS Utilities Extension-crx插件

    语言:English 显示NextJS静态数据的大小,并允许通过右键...您可以在此博客文章上阅读有关使用此扩展程序的所有信息:http://peterkellner.net/2019/06/16/a-chrome-extension-for-viewing-serialized-data-in-nextjs/

    解决Django响应JsonResponse返回json格式数据报错问题

    TYPEERROR: In order to allow non-dict objects to be serialized set the safe parmeter to False 解决: return JsonResponse({“name”: “tom”}, safe=False) 增加safe=false,使其接受列表 补充知识:...

    Protocol Buffers v2.6.1

    Protocol Buffers v2.6.1 2014-10-20 version 2.6.1 C++ Added atomicops support for Solaris. Released memory allocated by InitializeDefaultRepeatedFields...Fixed WhichOneof() to work with de-serialized pro

    java-api part1

    3. **serialized-form.html**:这个文件详细描述了Java对象序列化的过程,序列化是将Java对象转换为字节流,以便存储或在网络上传输。了解这个文件可以帮助开发者理解和处理对象的序列化和反序列化。 4. **constant...

    mapx 反序列化读取数据

    Since datasets rely on external data, the contents of the datasets are not serialized to the file along with the rest of the map's information. DataSets.Restore can be used to restore a dataset (and ...

    gwt-comet:从 code.google.compgwt-comet 自动导出

    gwt-彗星 ...概述 这个 gwt-comet 库为 GWT 提供了一个高效的 Comet 实现。 此库已移至 GitHub ...Supports string and GWT-serialized messages. Supports deflate compression. Supports heartbeat messages to det

    acpi控制笔记本风扇转速

    SpaceId is now part of the REGION object. BZ 429 ---------------------------------------- 11 October 2006. Summary of changes for version 20061011: 1) ACPI CA Core Subsystem: Completed an AML ...

    1.5api-part1

    2. `serialized-form.html`:这个文件通常包含关于序列化对象的信息,描述了类如何被序列化以及其字段的顺序。在Java中,序列化是将对象的状态转化为字节流的过程,便于存储或在网络间传输。 3. `constant-values....

    serializededitor用于编辑已在PHP中序列化数据的Vuejs组件

    5. **插件支持**:Vue.js社区提供了丰富的插件和库,"serialized-editor"可能已经集成了一些,如JSON编辑器插件,以便更有效地呈现和编辑JSON格式的序列化数据。 6. **版本控制**:文件名"deliciousbrains-...

    serialized-redis:一种使用redis-py序列化列表和字典的解决方案

    pip install serialized-redis 更新方法 放 得到 普鲁什 普鲁什克斯 兰奇 设置 get 例子 from serialized_redis import SerializedRedis redis = SerializedRedis () redis . set ( 'datas' , { 'name' : '...

    serialized-request:发出HTTP请求,并序列化对JavascriptTypescript类对象的请求和响应

    npm i @simpli/serialized-request axios class-transformer 请求使用 序列化请求支持GET,POST,PUT,PATCH,DELETE和HEAD Http方法 进口 import { Request , RequestListener } from '@simpli/serialized-request'...

Global site tag (gtag.js) - Google Analytics