【问题标题】:Set version property without using @Version annotation of MongoTemplate在不使用 MongoTemplate 的 @Version 注释的情况下设置版本属性
【发布时间】:2020-06-09 18:19:39
【问题描述】:

我们正在使用 Spring.data.mongodb 的 @Version 注释来使用乐观锁定并使用 mongoTemplate.save(T entity) 保存实体。

由于我们使用六边形架构,其中具体的MongoTemplate 实现位于基础架构模块中,域模型位于“核心”模块中,我们需要对 spring.data 放置一个 maven 依赖项.mongodb 也在那里,为了使用 @Version 注释:

@Document("basket")
public class Basket {


  @Id
  BasketId id;

  @Version
  long documentVersion;

}

现在我们想摆脱整个 core 模块中的 Spring 依赖项,因为我们想将 core 提取为 LIB-jar 并在另一个项目中使用它(不使用 spring)。对于这里的@Document@Id 部分,这很容易,因为MongoTemplate 似乎很容易检测到我们的BasketId(因为它被称为“id”)并且MongoTemplate 提供了在摆脱时提供集合名称@Document。但是,这对于 documentVersion 是错误的,并且简单地将其重命名为 version 也不起作用。

所以我想在不使用 MongoTemplate 的注释的情况下使用版本属性。

【问题讨论】:

    标签: java spring spring-data spring-data-mongodb mongotemplate


    【解决方案1】:

    我在深入研究后自己弄清楚了。我在core 项目中停用了org.springframework.data.annotation.@Version 的任何用法,并将其替换为我自己的名为@EnabledOptimisticLocking 的注释。为了让spring.data.mongodb 提防它而不是@Version,您需要执行以下操作:

    public class CustomVersionAnnotationMappingContext extends MongoMappingContext {
    
    private static final FieldNamingStrategy DEFAULT_NAMING_STRATEGY = PropertyNameFieldNamingStrategy.INSTANCE;
    
    private FieldNamingStrategy fieldNamingStrategy = DEFAULT_NAMING_STRATEGY;
    
    @Override
    public MongoPersistentProperty createPersistentProperty(Property property, BasicMongoPersistentEntity<?> owner,
            SimpleTypeHolder simpleTypeHolder) {
        return new CustomVersionAnnotationPersistentProperty(property, owner, simpleTypeHolder, fieldNamingStrategy);
    }
    
    @Override
    public void setFieldNamingStrategy(FieldNamingStrategy fieldNamingStrategy) {
        super.setFieldNamingStrategy(fieldNamingStrategy);
        this.fieldNamingStrategy = fieldNamingStrategy == null ? DEFAULT_NAMING_STRATEGY : fieldNamingStrategy;
    }
    
    class CustomVersionAnnotationPersistentProperty extends CachingMongoPersistentProperty {
    
        /**
         * Creates a new {@link CachingMongoPersistentProperty}.
         *
         * @param property
         * @param owner
         * @param simpleTypeHolder
         * @param fieldNamingStrategy
         */
        public CustomVersionAnnotationPersistentProperty(Property property,
                MongoPersistentEntity<?> owner,
                SimpleTypeHolder simpleTypeHolder,
                FieldNamingStrategy fieldNamingStrategy) {
            super(property, owner, simpleTypeHolder, fieldNamingStrategy);
        }
    
        @Override
        public boolean isVersionProperty() {
            return isAnnotationPresent(EnableOptimisticLocking.class);
        }
    }
    }
    

    然后简单地将其初始化为默认的 bean 之前,否则将创建:

    @Bean
    public MongoMappingContext mongoMappingContext(@Autowired CustomConversions customConversions) throws ClassNotFoundException {
    
        MongoMappingContext mappingContext = new CustomVersionAnnotationMappingContext();
        mappingContext.setSimpleTypeHolder(customConversions.getSimpleTypeHolder());
        mappingContext.setAutoIndexCreation(true);
        mappingContext.afterPropertiesSet();
    
        return mappingContext;
    }
    

    不幸的是,fieldNamingStrategy 类属性是私有的,并且没有 getter,因此需要将该字段拉起并复制它。

    理论上,如果需要,现在也可以用您自己的注释替换其他注释,例如@Id

    【讨论】:

      猜你喜欢
      • 2017-01-11
      • 2014-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-10
      • 2018-02-27
      • 1970-01-01
      相关资源
      最近更新 更多