你能阻止spring-data持久化在超类中声明的字段吗?

时间:2017-08-01 16:15:20

标签: spring spring-data spring-data-mongodb

我有一个域对象,它扩展了一个包含几个私有字段(用transient关键字标记)的基类。我想阻止超类字段被持久化。遗憾的是,我无法控制基类(它存在于第三方库中)。由于第三方库的机制,我也没有选择,只能使用继承。

有没有办法告诉spring-data:

  1. 仅保留子类中声明的字段。

  2. 仅保留已使用@Field显式注释的字段仅用于该域对象?

  3. 忽略使用transient关键字标记的字段?

  4. 我尝试在子类中使用带有@Override方法的@AccessType(Type.PROPERTY)来获取超类中的方法,我不希望持久化并使用@Transient注释那些方法。但是,对于超类中的某些字段,它似乎仍然使用字段访问。

    编辑:我想知道是否可以编写一个通用的Converter,它反射性地在子类中找到字段。但是,我不确定你如何配置Spring将该转换器用于固定的类集合。

2 个答案:

答案 0 :(得分:2)

@barbakini感谢您使用转换器的建议。我尝试过这种方法,但它似乎比预期的要复杂一点。

我的工作解决方案是使用AbstractMongoEventListener,它会过滤掉onBeforeSave()中不需要的字段:

public class ConfigurableFieldFilteringMongoSaveEventListener extends AbstractMongoEventListener<Object> {

  private final Map<Class<?>, Collection<String>> allowedFieldsByClass;

  public ConfigurableFieldFilteringMongoSaveEventListener(Map<Class<?>, Collection<String>> allowedFieldsByClass) {
    this.allowedFieldsByClass = allowedFieldsByClass;
  }

  @Override
  public void onBeforeSave(BeforeSaveEvent<Object> event) {
    super.onBeforeSave(event);
    final Object domainObject = event.getSource();
    final Collection<String> allowedFields = allowedFieldsByClass.get(domainObject.getClass());
    if (allowedFields == null) {
      return;
    }

    final DBObject dbObject = event.getDBObject();
    dbObject.keySet().retainAll(allowedFields);
  }
}

答案 1 :(得分:0)

是的,您可以为您的班级编写和使用自定义转换器,甚至可以将不同的字段名称从对象映射到mongodb集合:

@Configuration
public class MongoConfig extends AbstractMongoConfiguration {
    private final List<Converter<?, ?>> converters = new ArrayList<Converter<?, ?>>();

    public CustomConversions customConversions() {
        converters.add(new YourCustomConverter());
        return new CustomConversions(converters);
    }
}

和YourCustomConverter类:

@WritingConverter 
public class CandidateConverter implements Converter<DBObject, YourClass> {

    @Override
    public DBObject convert(YourClass object) {
        DBObject dbo = new BasicDBObject();
        dbo.put("_id", object.get_id);
        dbo.put("iAmNotSomeField", object.getSomeField);
        return dbo;
    }
}

对于子对象字段,您需要创建DBObject并将其放在上部DBObject中。同样,如果你愿意,你也可以写一个readingConverter。您可以在第6.3.6节

中找到更多信息here

<强>更新

对于我在评论中提出的建议。 Spring使用MappingMongoConverter在课堂上您可以搜索转换 conversionService