如何为 SimpleReactiveCassandraRepository 提供 CassandraEntityInformation<T, ID>?

How to provide CassandraEntityInformation<T, ID> for a SimpleReactiveCassandraRepository?

我正在做一些关于 spring-data-cassandra-reactive 的研究,看起来我无法弄清楚或找不到关于此的正确文档。

根据文档,您可以创建一个用 @Repository 注释的 interface,然后使用注释创建自定义查询来检索您想要的数据。代码看起来像这样:


@Repository
public interface UserRepository
        extends ReactiveCassandraRepository<UserEntity, UUID>
{

    @Query("SELECT u FROM UserEntity u WHERE username = :user ALLOW FILTERING")
    Mono<UserEntity> findUserEntityByUsername(@Param("user") String user);

    /**
     * This is just to illustrate/simulate some custom/advanced logic that cannot be
     * done via @Query()
     */
    default Mono<UserEntity> saveWithBase64EncodedPassword(UserEntity entity)
    {
        String encodedPassword = Base64.getEncoder().encodeToString(entity.getPassword().getBytes());
        entity.updatePassword(encodedPassword);
        return this.save(entity);
    }

}


@Table(UserEntity.TABLE_NAME)
public class UserEntity
{

    public final static String TABLE_NAME = "users";

    @PrimaryKeyColumn(name = "uuid", ordinal = 0, type = PrimaryKeyType.PARTITIONED)
    @CassandraType(type = CassandraType.Name.UUID)
    @Column
    private UUID id;

    @Column
    @CassandraType(type = CassandraType.Name.VARCHAR)
    private String username;

    @Column
    @CassandraType(type = CassandraType.Name.VARCHAR)
    private String password;

    public UserEntity()
    {
        this.id = UUID.randomUUID();
    }

    public UserEntity(String username, String password)
    {
        this.id = UUID.randomUUID();
        this.username = username;
        this.password = password;
    }

    public UUID getId()
    {
        return id;
    }

    public void setId(UUID id)
    {
        this.id = id;
    }

    public String getUsername()
    {
        return username;
    }

    public void setUsername(String username)
    {
        this.username = username;
    }

    public String getPassword()
    {
        return password;
    }

    public void setPassword(String password)
    {
        this.password = password;
    }

    public void updatePassword(String newPassword)
    {
        this.password = newPassword;
    }

}

依赖关系:

plugins {
    id("org.springframework.boot") version "2.6.6"
    id("io.spring.dependency-management") version "1.0.11.RELEASE"
}

dependencies {

    // Embedded Cassandra Server - used for testing.
    implementation("com.github.nosan:embedded-cassandra-spring-boot-starter:4.1.0")

    // Spring Data Cassandra Dependencies
    annotationProcessor("org.springframework.boot:spring-boot-configuration-processor")
    implementation("org.springframework.boot:spring-boot-starter-actuator")
    implementation("org.springframework.boot:spring-boot-starter-data-cassandra-reactive")

    testImplementation("org.springframework.boot:spring-boot-starter-test") {
        exclude("org.junit.vintage:junit-vintage-engine")
        exclude("com.vaadin.external.google:android-json")
    }
    testImplementation("io.projectreactor:reactor-test")
    // /Spring Data Cassandra Dependencies
}

到目前为止,这一切正常。但是,我试图弄清楚如何切换到实现接口以便能够使用 @Autowire (即在此示例代码中为 autowire
org.springframework.security.crypto.password.PasswordEncoder)

浏览 spring-data-cassandra jar 中的代码,我注意到有一个名为 org.springframework.data.cassandra.repository.support.SimpleReactiveCassandraRepository 的 class,您可以从中扩展。它已经包含您需要为您实现的大部分常见功能,这就是为什么它看起来是 extend 的完美候选者。

问题来了 - 它需要 CassandraEntityInformation<T, ID> metadata。 我似乎无法找到它的来源或它应该如何自动连接,我觉得我可能遗漏了一些东西或者可能是依赖项。

有什么想法吗?

SimpleReactiveCassandraRepository 是一个很棒的 class,因为它让您可以访问 ReactiveCassandraOperations,因此可以访问 CqlSession。这是进行细粒度操作的好方法。 (LWT,巴克特)

您是正确的,不同的 classes 将被自动装配。这是一个示例代码:

@Repository
public class OwnerReactiveCassandraRepository extends SimpleReactiveCassandraRepository<OwnerEntitySpring, UUID> {

protected final CqlSession cqlSession;
protected final ReactiveCassandraOperations reactiveCassandraTemplate;

@SuppressWarnings("unchecked")
public OwnerReactiveCassandraRepository(CqlSession cqlSession, ReactiveCassandraOperations ops) {
    super(new MappingCassandraEntityInformation<OwnerEntitySpring, UUID>(
            (CassandraPersistentEntity<OwnerEntitySpring>) ops.getConverter().getMappingContext()
            .getRequiredPersistentEntity(OwnerEntitySpring.class), ops.getConverter()), ops);
    this.cqlSession = cqlSession;
    this.reactiveCassandraTemplate = ops;
}

public Flux<OwnerEntitySpring> searchByOwnerName(String ownerLastName) {
    return reactiveCassandraTemplate.getReactiveCqlOperations()
                                    .query(SimpleStatement
                                        .builder("SELECT * FROM " + TABLE_NAME + " WHERE " + COLUMN_LASTNAME  + "=?")
                                        .addPositionalValues(ownerLastName)
                                        .build(), (row, rownum) -> new OwnerEntitySpring(row));
}

TLDR;我用 Spring 数据 Reactive 实现了 Spring PetClinic,您可以访问完整代码 here It is a step by step workshop with the code. You may want to look specially at this folder

在该项目中,您会发现与 drivers only 反应,与 CassandraRepositories 反应和与 SimpleCassandraRepositories 反应。 (检查 TEST 文件夹)