将对象转换为数据存储区实体

时间:2014-04-23 17:50:06

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

我的目标是制作一个非常简单的Object< - > Entity映射,这是我到目前为止所做的,这是递归的:

/**
     *
     * 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());
}

问题是否有任何现有的Object-to-Entity映射代码?我并不是在寻找完整的承诺ORM框架,只需要一个简单的POJOEntity转换器代码。这段代码是否以任何方式膨胀?

2 个答案:

答案 0 :(得分:-1)

你正在编写另一个持久性库的痛苦方式。小心,一个纯粹的&#34;对象模型与数据存储区实体几乎不匹配。在某些时候,你会做出妥协来匹配底层的实体结构,那时你就会意识到一个更好的图书馆一直在这样做。

例如:您提供实体的父密钥,但如果您只想更新该密钥,那么该实体的密钥在哪里?如果在某些时候你不想为一个小查询加载所有对象图,你将如何处理延迟加载?你如何序列化密钥?那么Blobbyte[]怎么样?你如何处理超常属性?

在你花费数周时间研究已经存在的东西之前帮自己一个忙,在遇到一个对一个人来说太大的问题之前,使用一个经过验证的持久性工具。如果你需要保留纯对象模型(例如,如果你在前端使用GWT),那么将持久化类映射到你的POJO。

如果你真的不需要像Objectify这样的东西,那么这可能意味着你可以通过低级API的灵活性获得更好的效果。将实体映射到您的类不需要很长时间。

最重要的是,通过编写自己的&#34;框架&#34;,您错过了两者手动和低级API的灵活性刚性但坚固的工具,它比你做得更好。

答案 1 :(得分:-1)

This is the GaeMarshaller对我有用。