我的目标是制作一个非常简单的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框架,只需要一个简单的POJO
到Entity
转换器代码。这段代码是否以任何方式膨胀?
答案 0 :(得分:-1)
你正在编写另一个持久性库的痛苦方式。小心,一个纯粹的&#34;对象模型与数据存储区实体几乎不匹配。在某些时候,你会做出妥协来匹配底层的实体结构,那时你就会意识到一个更好的图书馆一直在这样做。
例如:您提供实体的父密钥,但如果您只想更新该密钥,那么该实体的密钥在哪里?如果在某些时候你不想为一个小查询加载所有对象图,你将如何处理延迟加载?你如何序列化密钥?那么Blob
和byte[]
怎么样?你如何处理超常属性?
在你花费数周时间研究已经存在的东西之前帮自己一个忙,在遇到一个对一个人来说太大的问题之前,使用一个经过验证的持久性工具。如果你需要保留纯对象模型(例如,如果你在前端使用GWT),那么将持久化类映射到你的POJO。
如果你真的不需要像Objectify这样的东西,那么这可能意味着你可以通过低级API的灵活性获得更好的效果。将实体映射到您的类不需要很长时间。
最重要的是,通过编写自己的&#34;框架&#34;,您错过了两者手动和低级API的灵活性和刚性但坚固的工具,它比你做得更好。
答案 1 :(得分:-1)