【问题标题】:Translate Object into Datastore Entity [closed]将对象转换为数据存储实体 [关闭]
【发布时间】:2014-04-23 17:50:06
【问题描述】:

我的目标是做一个非常简单的对象这里的实体映射是我到目前为止所做的,这是递归的:

/**
     *
     * Create Entity objects that can be persisted into the GAE datastore,
     * including its Parent-Child relationships (if necessary).
     *
     * @param parent parent of the generated Entity or Entities
     * @param instance
     * @return
     */
    public Entity createEntityFrom(Key parent, Object instance){
        Preconditions.checkNotNull(instance, "Object should not be null");
        if (stack == null){ // List<Entity> stack;
            stack = new LinkedList<Entity>();
        }
        stack.clear();
        Key key = createKeyFrom(parent, instance); // inspect kind and create key
        Map<String,Object> props = new LinkedHashMap<String, Object>();
        List<Entity> target = null;
        Entity e = new Entity(key);
        Field[] fields = instance.getClass().getDeclaredFields();
        for (Field field : fields) {
            if (target == null){
                target = new LinkedList<Entity>();
            }
            String fieldName = field.getName();
            if(field.isAnnotationPresent(Id.class)){
                // skip
                continue;
            }
            try {
                boolean isAccessible = field.isAccessible();
                field.setAccessible(true);
                Class<?> clazz = field.getType();
                Object fieldValue = field.get(instance);

                if (fieldValue == null){
                    e.setProperty(fieldName, null);
                } else if (fieldValue instanceof String) {
                    setProperty(e, fieldName, fieldValue);
                } else if(fieldValue instanceof Number
                        || fieldValue instanceof Long
                        || fieldValue instanceof Integer
                        || fieldValue instanceof Short) {
                    setProperty(e, fieldName, fieldValue);
                } else if(fieldValue instanceof Boolean) {
                    setProperty(e, fieldName, fieldValue);
                } else if(fieldValue instanceof Date) {
                    setProperty(e, fieldName, fieldValue);
                } else if(fieldValue instanceof User) { // GAE support this type
                    setProperty(e, fieldName, fieldValue);
                } else if(fieldValue instanceof List) {
                    LOG.debug( "Processing List valueType");
                    if (field.isAnnotationPresent(Embedded.class)){
                        setProperty(e, fieldName, createEmbeddedEntityFromList(parent, (List) fieldValue));
                    } else {
                        // TODO
                        List<Object> list = (List<Object>) fieldValue;
                        List<Entity> result = new LinkedList<Entity>();
                        for (Object o : list){
                            //result = createEntityFrom(e.getKey(), o);
                        }
                    }
                } else if(fieldValue instanceof Map){
                    LOG.debug( "Processing Map valueType");
                    if (field.isAnnotationPresent(Embedded.class)){
                        setProperty(e, fieldName, createEmbeddedEntityFromMap(parent, (Map) fieldValue));
                    } else {
                        Entity mapEntity = new Entity(KeyStructure.createKey(e.getKey(), "kind", "key"));
                        Map map = (Map) fieldValue;
                        Iterator it = map.entrySet().iterator();
                        while(it.hasNext()){
                            Map.Entry entry = (Map.Entry) it.next();
                            Object entryKey = entry.getKey();
                            Object entryVal = entry.getValue();
                            validateKey(entryKey);
                            if(entryKey instanceof String){
                                //createEntityFrom()
                            } else if (entryKey instanceof Long){

                            } else {

                            }
                        }
                    }
                } else {
                    // For primitives
                    if (clazz.equals(int.class)){
                        int i = (Integer) fieldValue;
                        setProperty(e, fieldName, i);
                    } else if (clazz.equals(boolean.class)){
                        boolean i = (Boolean) fieldValue;
                        setProperty(e, fieldName, i);
                    } else if (clazz.equals(byte.class)){
                        byte i = (Byte) fieldValue;
                        setProperty(e, fieldName, i);
                    } else if (clazz.equals(short.class)){
                        short i = (Short) fieldValue;
                        setProperty(e, fieldName, i);
                    } else if (clazz.equals(long.class)){
                        long i = (Long) fieldValue;
                        setProperty(e, fieldName, i);
                    } else if (clazz.equals(float.class)){
                        float i = (Float) fieldValue;
                        setProperty(e, fieldName, i);
                    } else if (clazz.equals(double.class)){
                        double i = (Double) fieldValue;
                        setProperty(e, fieldName, i);
                    } else { // POJO
                        if (field.isAnnotationPresent(Parent.class)){
                            // update key
                            Key oldKey = e.getKey();
                            Entity parentEntity = createEntityFrom(null, field); // then add to the stack
                            // TODO
                        } else if (field.isAnnotationPresent(Child.class)){
                            Entity childEntity = createEntityFrom(e.getKey(), field);
                            setProperty(e, fieldName, childEntity.getKey());
                        }
                        Key parentKey = e.getKey();
                        Entity child = createEntityFrom(parentKey, fieldValue);
                        setProperty(e, fieldName, child.getKey());
                        stack.add(e);
                    }
                }
                field.setAccessible(isAccessible);
            } catch(IllegalAccessException ex){
                ex.printStackTrace();
            }
        }
        return e;
    }

测试

它的使用方法如下:

@Test
public void test(){
    Friend f = new Friend(); // one Entity
    f.setName("TestUser");
    f.setAge(25);
    f.setNewAddress(new Address("Test City")); // one Entity, @Child
    f.setOldAddress(new Address("Old Test City")); // not included, @Embedded
    List<Entity> stack = new LinkedList<Entity>();
    ObjectMapper mapper =  new ObjectMapper();
    mapper.createEntityFrom(null, f);
    assertEquals(2, stack.size());
}

问题是否有任何现有的对象到实体映射代码?我并不是真的在寻找完整的承诺 ORM 框架,只是一个简单的 POJOEntity 转换器代码。这段代码是否臃肿?

【问题讨论】:

标签: java google-app-engine google-cloud-datastore


【解决方案1】:

您正在痛苦地编写另一个持久性库。请注意,“纯”对象模型很难与数据存储实体匹配。在某些时候你会做出妥协以匹配底层实体结构,那时你会意识到一个更好的库一直在做这件事。

例如:您提供实体的父键,但如果您只想更新它,该实体的键在哪里?如果在某个时候您不想为一个小查询加载所有对象图,您将如何处理延迟加载?你如何序列化密钥? Blobs 和 byte[] 呢?你如何处理transcient属性?

在你花费数周的时间来处理已经存在的事情之前,请帮自己一个忙,在你偶然发现一个对一个人来说太大的问题之前,请使用一种经过验证的持久性工具。如果您需要保留纯对象模型(例如,如果您在前端使用 GWT),则将持久类映射到您的 POJO。

如果你真的不需要像 Objectify 这样的东西,这可能意味着你会更好地使用低级 API 的灵活性。将实体映射到您的类不需要那么长时间。

最重要的是,通过编写自己的“框架”,您将错过手动乏味的低级 API 的灵活性比您做得更好的刚性但坚固的工具。

【讨论】:

    【解决方案2】:

    This is the GaeMarshaller 对我有用。

    【讨论】:

      猜你喜欢
      • 2021-09-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-11
      • 1970-01-01
      • 2011-09-04
      • 1970-01-01
      • 2013-10-14
      相关资源
      最近更新 更多