J'utilise Donner ces classes: P> A a = new A();
C c = new C();
PropertyUtils.setProperty(a, "b.c", c); //exception
7 Réponses :
Après avoir fait des recherches, la réponse courte à "Est-ce possible ..." La question est
Je l'ai résolu en faisant cela:
Cela aura un problème lorsque vous essayez de définir C sur un NULL B. Le meilleur moyen est de traverser l'objet à l'aide de la réflexion et de le créer en cours de route.
Un peu de correction:
Je n'ai utilisé que la réflexion W / O Library Apache pour y parvenir. L'hypothèse est que tous les objets à parcourir sont tous des pojos et la construction par défaut est accessible au public. De cette façon, il n'est pas nécessaire de construire le chemin de référence pour chaque boucle.
public Object getOrCreateEmbeddedObject(Object inputObj,String[] fieldNames) throws Exception { Object cursor = inputObj; //Loop until second last index for (int i = 0; i < fieldNames.length - 1; i++){ Field ff = getClassFieldFrom(cursor,fieldNames[i]); Object child = ff.get(cursor); if(null == child) { Class<?> cls=ff.getType(); child = cls.newInstance(); ff.set(cursor, child); } cursor = child; } return cursor; } private Field getClassFieldFrom(Object object, String fieldStr) throws NoSuchFieldException { java.lang.reflect.Field ff = object.getClass().getDeclaredField(fieldStr); ff.setAccessible(true); return ff; }
Je suis allé à l'approche très fondamentale consistant à instantifier chacun des objets par défaut:
public class A { B b = new B(); } public class B { C c = new C(); } public class C { }
Je connais la question concerne Apache Commons Procientitils.StProperty, mais il existe une fonctionnalité très similaire disponible dans language d'expression de printemps "spel "qui fait exactement ce que vous voulez. Mieux encore, il traite aussi des listes et des tableaux. Le lien Doc ci-dessus est pour le printemps 4.x mais le code ci-dessous fonctionne pour moi au printemps 3.2.9.
StockOrder stockOrder = new StockOrder(); // Your root class here SpelParserConfiguration config = new SpelParserConfiguration(true,true); // auto create objects if null ExpressionParser parser = new SpelExpressionParser(config); StandardEvaluationContext modelContext = new StandardEvaluationContext(stockOrder); parser.parseExpression("techId").setValue(modelContext, "XXXYYY1"); parser.parseExpression("orderLines[0].partNumber").setValue(modelContext, "65498"); parser.parseExpression("orderLines[0].inventories[0].serialNumber").setValue(modelContext, "54686513216"); System.out.println(ReflectionToStringBuilder.toString(stockOrder));
IMHO, la meilleure solution consiste à se débarrasser des Commons-Beantutils et à utiliser le cadre de printemps org.springframework.beans.PropertyAccessorFactory Je ne vais pas approfondir dans les détails de la façon dont cela fonctionne, mais Si vous voulez vérifier, allez jeter un coup d'œil dans le lien ci-dessus, cette API est assez intuitive, mais vous devez avoir un noyau de source de printemps configuré dans votre classe de classe. Je ne vous recommande donc pas d'ajouter le printemps juste Pour le bien de cette fonctionnalité. p> si vous n'avez que Dans cet exemple, j'ai utilisé avec JPA TUPLE Requête pour construire un objet personnalisé avec une propriété spécifique Y chemins avec ses valeurs correspondantes à définir. p> Ce code utilise Commons-Beanutils-1.9.3.jar P> P>