Reputation: 9295
Spring Data Reactive does not support Page as a return type. I'm trying to implement this using two different queries (one to get result list and another to get total count) from Service layer.
The first query gives the contents as Flux<Person>
and the second query gives the count as Mono<Integer>
.
Can I combine these two and return a Mono<Page<Person>>
? How?
Please help.
Upvotes: 4
Views: 4315
Reputation: 9295
So finally I coded this as below.
I'm new to this whole reactive paradigm. So the below code may not be the best way to do this. Eventually, I hope Spring Data R2DBC adds support for Page return type. The answer to the above question is in the search method implementation in the CustomMentorRepositoryImpl class.
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Version;
import org.springframework.data.relational.core.mapping.Column;
import org.springframework.data.relational.core.mapping.Table;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Table("mentors")
public class Mentor {
@Id
private Long id;
boolean hasId() {
return id != null;
}
@Version
@Column("version")
private Integer version;
@Column("name")
private String name;
@Column("age")
private Integer age;
}
Repository class
import com.sample.app.domain.Mentor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.r2dbc.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import org.springframework.stereotype.Repository;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@Repository
public interface MentorRepository extends
ReactiveCrudRepository<Mentor, String>, CustomMentorRepository {
}
// CustomRepository class
import com.sample.app.domain.Mentor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.query.Param;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
public interface CustomMentorRepository {
public Mono<Page<Mentor>> search(String name, Pageable page);
}
// CustomRepositoryImpl class
import lombok.AllArgsConstructor;
import com.sample.app.domain.Mentor;
import com.sample.app.repository.CustomMentorRepository;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.r2dbc.core.DatabaseClient;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@AllArgsConstructor
public class CustomMentorRepositoryImpl implements CustomMentorRepository {
DatabaseClient databaseClient;
@Override
public Mono<Page<Mentor>> search(String name, Pageable page) {
// Get the contents
Flux<Mentor> contents = databaseClient.execute("SELECT * FROM mentors where name like :name limit :limit offset :offset")
.bind("name", "%" + name + "%")
.bind("limit", page.getPageSize())
.bind("offset", page.getOffset())
.as(Mentor.class)
.fetch().all();
// Get the count
Mono<Long> count = databaseClient.execute("SELECT count(*) FROM mentors where name like :name")
.bind("name", "%" + name + "%")
.as(Long.class)
.fetch().first();
return contents.collectList().zipWith(count).flatMap(objects ->
Mono.just(new PageImpl<Mentor>(objects.getT1(), page, objects.getT2()))
);
}
}
Upvotes: 2