Мы рады сообщить, что наше сообщество начинает обрастать экспертами, и мы будем знакомить вас с их мнением. Встречайте, Михаил Поливаха, коммитер Spring Data JDBC (Relational), не удержался от комментария по вопросу поддержки проекций в разных модулях Spring Data. Ниже прямая речь Михаила.
Надо сказать, что projection-ы, как функциональность, должна быть доступна во всех модулях spring-data. Вопрос в том, что еще не все модули ее поддержку реализовали до конца.
Наивный читатель мог бы предположить, что поскольку в spring-data-jdbc есть поддержка как interface based projection-ов, так и dynamic projection-ов, то вот это заработает:
Но данный код сгенерит ошибку глубоко в недрах JdbcQueryCreator-a:
Связано это с тем, что на данный момент spring-data-jdbc просто не умеет переваривать динамические проджекшены для инфтерфейсов 🙂
Про это мы знаем, бага на это дело пока нет, если он кому-либо важен - можем завести. Хочу также напомнить, что если есть какие-либо инициативы для нововведений в spring-data-jdbc - можно оставлять в комментариях или писать мне в ЛС.
Надо сказать, что projection-ы, как функциональность, должна быть доступна во всех модулях spring-data. Вопрос в том, что еще не все модули ее поддержку реализовали до конца.
Наивный читатель мог бы предположить, что поскольку в spring-data-jdbc есть поддержка как interface based projection-ов, так и dynamic projection-ов, то вот это заработает:
public interface MyEntityRepository extends CrudRepository<MyEntity, Long> {
<T> Optional<T> findProjectionByStatus(String status, Class<T> clazz);
}
@Data
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@Accessors(chain = true)
@Table
public class MyEntity {
@Id
@EqualsAndHashCode.Include
private Long id;
private String status;
@CreatedDate
private Instant createdAt;
}
interface MyEntityInterfaceProjection {
String status();
Long id();
}
@Test
void whenDynamicProjectsAreInUseViaInterfaces_thenBlast() {
saveInitialEntity();
Optional<MyEntityInterfaceProjection> active = myEntityRepository.findProjectionByStatus("active", MyEntityInterfaceProjection.class);
Assertions.assertThat(active)
.isPresent()
.hasValueSatisfying(myEntityProjection -> {
Assertions.assertThat(myEntityProjection.id() != null && myEntityProjection.status().equalsIgnoreCase("active")).isTrue();
});
}
@NotNull
private MyEntity saveInitialEntity() {
MyEntity myEntity = new MyEntity();
myEntity.setStatus("active");
return myEntityRepository.save(myEntity);
}
Но данный код сгенерит ошибку глубоко в недрах JdbcQueryCreator-a:
java.lang.IllegalStateException: SELECT does not declare a select list
at org.springframework.data.relational.core.sql.SelectValidator.doValidate(SelectValidator.java:57)
at org.springframework.data.relational.core.sql.SelectValidator.validate(SelectValidator.java:49)
at org.springframework.data.relational.core.sql.DefaultSelectBuilder.build(DefaultSelectBuilder.java:207)
at org.springframework.data.jdbc.repository.query.JdbcQueryCreator.complete(JdbcQueryCreator.java:173)
at org.springframework.data.jdbc.repository.query.JdbcQueryCreator.complete(JdbcQueryCreator.java:66)
Связано это с тем, что на данный момент spring-data-jdbc просто не умеет переваривать динамические проджекшены для инфтерфейсов 🙂
Про это мы знаем, бага на это дело пока нет, если он кому-либо важен - можем завести. Хочу также напомнить, что если есть какие-либо инициативы для нововведений в spring-data-jdbc - можно оставлять в комментариях или писать мне в ЛС.