我一直收到这样的消息,Spring将使用CassandraRepositoryFactoryBean覆盖我的工厂bean定义。这会导致问题,因为我重写工厂的原因是覆盖存储库上的 save
方法,以便我可以自动填充createTimestamp
和updateTimestamp
方法。
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]
显然,这里有一些优先级顺序或缺少配置,但我找不到它。也许你可以?
我的弹簧配置:
@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
方法。
原来
@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);
}
不能存在于单独的配置 java 类中,即使该类用 @Configuration
注释。我不得不把它放在主应用程序类中。
必须删除我创建的工厂。TimestampCrudRepositoryFactoryBean
只有界面和实现(一旦注释被移动(,它就可以工作了,Spring 没有尝试用更通用的定义替换我的定义。
图 这是 Spring 配置的操作顺序。至少这是我有根据的猜测。