使用反射遍历对象的集合属性

Iterate through collection attribute of object with reflection

我正在尝试在我的代码中实施 this 解决方案,以在 spring 数据 mongodb 中进行级联保存。它适用于像这样的正常 class。

public class Test{

    @Id
    private String id;

    @DBRef
    @CascadeSave
    private Contact contact;
}

但是我有这样的东西。

public class Test{

    @Id
    private String id;

    @DBRef
    @CascadeSave
    private Set<Contact> contacts = new HashSet<>();
}

我想更改 listener 中的代码,该代码位于 link 中,用于处理集合。我尝试了几件事但没有成功。除此之外,如果有另一种方法来完成这项任务,我们将不胜感激,即使这是一个单独的问题。

下面给出了我的监听器代码,与示例没有太大区别link。

public class CascadingMongoEventListener extends AbstractMongoEventListener {

private static final Logger logger = LoggerFactory.getLogger(CascadingMongoEventListener.class);

@Autowired
private MongoOperations mongoOperations;

@Override
public void onBeforeConvert(final Object source) {
     ReflectionUtils.doWithFields(source.getClass(), new ReflectionUtils.FieldCallback() {

        public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
            ReflectionUtils.makeAccessible(field);
            try {
                if (field.isAnnotationPresent(DBRef.class) && field.isAnnotationPresent(CascadeSave.class)) {
                    final Object fieldValue = field.get(source);
                    if (fieldValue != null) {

                        if (Collection.class.isAssignableFrom(field.getType())) {
                            @SuppressWarnings("unchecked")
                            Collection models = (Collection) fieldValue;
                            for (Object model : models) {
                               mongoOperations.save(model);
                            }
                        } else {
                            mongoOperations.save(fieldValue);
                        }
                    }
                }
            } catch (Exception e) {
                logger.error(e.getMessage());
                e.printStackTrace();
            }
        }
    });
}

private static class DbRefFieldCallback implements ReflectionUtils.FieldCallback {
    private boolean idFound;

    public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
        ReflectionUtils.makeAccessible(field);
        if (field.isAnnotationPresent(Id.class)) {
            idFound = true;
        }
    }

    public boolean isIdFound() {
        return idFound;
    }
}
}

这是对我有用的解决方案,如果有任何改进建议,我将不胜感激。

public class CascadingMongoEventListener extends AbstractMongoEventListener {

private static final Logger logger = LoggerFactory.getLogger(CascadingMongoEventListener.class);
@Autowired
private MongoOperations mongoOperations;

@Override
public void onBeforeConvert(final Object source) {
    ReflectionUtils.doWithFields(source.getClass(), new ReflectionUtils.FieldCallback() {

        public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
            ReflectionUtils.makeAccessible(field);

            if (field != null) {
                Object fieldValue = field.get(source);
                if (field.isAnnotationPresent(DBRef.class) && field.isAnnotationPresent(CascadeSave.class)) {
                    if (Collection.class.isAssignableFrom(fieldValue.getClass())) {
                        Collection<Object> collection = (Collection<Object>) fieldValue;
                        for (Object item : collection) {
                            if (mongoOperations.collectionExists(item.getClass())) {
                                mongoOperations.save(item);
                                logger.debug("Set of {}s saved.", item.getClass().getSimpleName());
                            }
                        }
                    } else {
                        if (mongoOperations.collectionExists(fieldValue.getClass())) {
                            mongoOperations.save(fieldValue);
                            logger.debug("{} saved.", fieldValue.getClass().getSimpleName());
                        }
                    }
                }
            }
        }
    });
  }
}