【问题标题】:Spring Data JPA Cassandra override save methodSpring Data JPA Cassandra 覆盖保存方法
【发布时间】:2018-06-25 13:54:15
【问题描述】:

我不断收到这条消息,Spring 将使用 CassandraRepositoryFactoryBean 覆盖我的工厂 bean 定义。这会导致问题,因为我覆盖工厂的原因是要覆盖 repo 上的 save 方法,以便我可以自动填充 createTimestampupdateTimestamp 方法。

2018-01-16 18:24:32,355  INFO main o.s.b.f.s.DefaultListableBeanFactory:828 - Overriding bean definition for bean 'containerIdRepo' with a different definition: replacing [Root bean: class [com.database.repo.audit.TimestampCrudRepositoryFactoryBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null] with [Root bean: class [org.springframework.data.cassandra.repository.support.CassandraRepositoryFactoryBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null]

显然这里有一些优先顺序或缺少配置,但我找不到它。也许你可以?

我的 Spring 配置:

@Configuration
@EnableCassandraRepositories(repositoryFactoryBeanClass = TimestampCrudRepositoryFactoryBean.class, repositoryBaseClass = TimestampCrudRepositoryImpl.class, basePackages = {
    "com.database.repo", "com.database.entity" })
public class DataCassandraConfiguration extends CassandraConfiguration {

@Bean
@Primary
@Order(Ordered.HIGHEST_PRECEDENCE)
public CassandraTemplate cassandraTemplate(Session session, CassandraConverter converter) {
    return new CassandraTemplate(session, converter);
}

}

我在哪里覆盖TypedIdCassandraRepository

@NoRepositoryBean
public interface TimestampCrudRepository<T extends BaseTimestampEntity, I extends Serializable>
    extends TypedIdCassandraRepository<T, I> {


}

如果你对BaseTimestampEntity感兴趣

public abstract class BaseTimestampEntity {

@CreatedDate
@Column("create_timestamp") // timestamp,
private Instant createTimestamp;
@LastModifiedDate
@Column("update_timestamp") // timestamp,
private Instant updateTimestamp;

}

我在哪里实现save 方法:

@NoRepositoryBean
@Slf4j
public class TimestampCrudRepositoryImpl<T extends BaseAuditEntity, I extends Serializable>
    extends SimpleCassandraRepository<T, I> implements TimestampCrudRepository<T, I> {

private final boolean isPrimaryKeyEntity;

public TimeStampCrudRepositoryImpl(CassandraEntityInformation<T, I> metadata, CassandraOperations operations) {
    super(metadata, operations);
    this.isPrimaryKeyEntity = metadata.isPrimaryKeyEntity();
}

@Override
public <S extends T> S save(S entity) {
    log.info("Using overriden save method to add create and update timestamp");
    Assert.notNull(entity, "Entity must not be null");

    Instant now = Instant.now();

    entity.setUpdateTimestamp(now);

    if (entity.getCreateTimestamp() == null) {
        entity.setCreateTimestamp(now);
    }

    if (entityInformation.isNew(entity) || isPrimaryKeyEntity) {
        return operations.insert(entity);
    }

    return operations.update(entity);
}
}

最后是我的工厂:

public class TimestampCrudRepositoryFactoryBean<T extends TimestampCrudRepository<S, I>, S extends BaseTimestampEntity, I extends Serializable>
    extends RepositoryFactoryBeanSupport<T, S, I> {

@Autowired
private CassandraTemplate cassandraTemplate;

protected TimestampCrudRepositoryFactoryBean(Class<? extends T> repositoryInterface) {
    super(repositoryInterface);
}

public void setCassandraTemplate(CassandraTemplate cassandraTemplate) {
    this.cassandraTemplate = cassandraTemplate;
}

@Override
protected RepositoryFactorySupport createRepositoryFactory() {
    return new TimestampCrudRepositoryFactory(cassandraTemplate);
}

@Override
public void afterPropertiesSet() {
    super.afterPropertiesSet();
    Preconditions.checkNotNull(cassandraTemplate, "cassandraTemplate must not be null!");
    setMappingContext(cassandraTemplate.getConverter().getMappingContext());
}


private static class TimestampCrudRepositoryFactory<S extends BaseAuditEntity, I extends Serializable>
        extends CassandraRepositoryFactory {

    private final CassandraTemplate cassandraTemplate;

    public TimestampCrudRepositoryFactory(CassandraTemplate cassandraTemplate) {
        super(cassandraTemplate);
        this.cassandraTemplate = cassandraTemplate;
    }

    @Override
    @SuppressWarnings("unchecked")
    protected Object getTargetRepository(RepositoryInformation information) {
        CassandraEntityInformation<?, Serializable> entityInformation = getEntityInformation(information.getDomainType());

        return new TimestampCrudRepositoryImpl(entityInformation, cassandraTemplate);
    }

    @Override
    protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
        return TimestampCrudRepositoryImpl.class;
    }

}
}

差点忘了回购:

public interface ContainerIdRepo extends TimestampCrudRepository<ContainerEntity, MapId> {}

什么都没有发生,但插入 Cassandra DB 的 updateTimestamp 和 createTimestamp 是 null,我可以看出在调试时没有命中覆盖 save 方法。

【问题讨论】:

    标签: spring-data-jpa spring-data-cassandra spring-config


    【解决方案1】:

    结果

    @EnableCassandraRepositories(repositoryFactoryBeanClass = TimestampCrudRepositoryFactoryBean.class, repositoryBaseClass = TimestampCrudRepositoryImpl.class, basePackages = {
    "com.database.repo", "com.database.entity" })
    

    @Bean
    @Primary
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public CassandraTemplate cassandraTemplate(Session session, CassandraConverter converter) {
    return new CassandraTemplate(session, converter);
    }
    

    即使该类使用 @Configuration 注释,也不能存在于单独的配置 java 类中。我必须把它放在主应用程序类中。

    此外,我不得不删除我创建的工厂。 TimestampCrudRepositoryFactoryBean

    只有接口和实现(并且一旦注释被移动)它就可以工作,Spring 没有尝试用更通用的定义替换我的定义。

    图这是 Spring 配置的操作顺序。至少这是我有根据的猜测。

    【讨论】:

      猜你喜欢
      • 2012-10-13
      • 2015-01-31
      • 1970-01-01
      • 2014-06-05
      • 1970-01-01
      • 1970-01-01
      • 2018-09-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多