Skip to content

Fix derived queries with boolean literals. #983

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<groupId>org.springframework.data</groupId>
<artifactId>spring-data-relational-parent</artifactId>
<version>2.3.0-SNAPSHOT</version>
<version>2.3.0-908-boolean-for-derived-queries-SNAPSHOT</version>
<packaging>pom</packaging>

<name>Spring Data Relational Parent</name>
Expand Down
2 changes: 1 addition & 1 deletion spring-data-jdbc-distribution/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-relational-parent</artifactId>
<version>2.3.0-SNAPSHOT</version>
<version>2.3.0-908-boolean-for-derived-queries-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
4 changes: 2 additions & 2 deletions spring-data-jdbc/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<modelVersion>4.0.0</modelVersion>

<artifactId>spring-data-jdbc</artifactId>
<version>2.3.0-SNAPSHOT</version>
<version>2.3.0-908-boolean-for-derived-queries-SNAPSHOT</version>

<name>Spring Data JDBC</name>
<description>Spring Data module for JDBC repositories.</description>
Expand All @@ -15,7 +15,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-relational-parent</artifactId>
<version>2.3.0-SNAPSHOT</version>
<version>2.3.0-908-boolean-for-derived-queries-SNAPSHOT</version>
</parent>

<properties>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ public JdbcCustomConversions jdbcCustomConversions() {
}
}

private List<?> userConverters() {
protected List<?> userConverters() {
return Collections.emptyList();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -402,11 +402,15 @@ private Condition createCondition(Column column, @Nullable Object mappedValue, i
}

if (comparator == Comparator.IS_TRUE) {
return column.isEqualTo(SQL.literalOf(true));

Expression bind = bindBoolean(column, parameterSource, true);
return column.isEqualTo(bind);
}

if (comparator == Comparator.IS_FALSE) {
return column.isEqualTo(SQL.literalOf(false));

Expression bind = bindBoolean(column, parameterSource, false);
return column.isEqualTo(bind);
}

Expression columnExpression = column;
Expand Down Expand Up @@ -495,6 +499,12 @@ private Condition createCondition(Column column, @Nullable Object mappedValue, i
}
}

private Expression bindBoolean(Column column, MapSqlParameterSource parameterSource, boolean value) {

Object converted = converter.writeValue(value, ClassTypeInformation.OBJECT);
return bind(converted, Types.BIT, parameterSource, column.getName().getReference());
}

Field createPropertyField(@Nullable RelationalPersistentEntity<?> entity, SqlIdentifier key) {
return entity == null ? new Field(key) : new MetadataBackedField(key, entity, mappingContext, converter);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,19 @@ public void pageQueryProjectionShouldReturnProjectedEntities() {
assertThat(result.getContent().get(0).getName()).isEqualTo("Entity Name");
}

@Test // #908
void derivedQueryWithBooleanLiteralFindsCorrectValues() {

repository.save(createDummyEntity());
DummyEntity entity = createDummyEntity();
entity.flag = true;
entity = repository.save(entity);

List<DummyEntity> result = repository.findByFlagTrue();

assertThat(result).extracting(e -> e.idProp).containsExactly(entity.idProp);
}

private Instant createDummyBeforeAndAfterNow() {

Instant now = Instant.now();
Expand Down Expand Up @@ -557,6 +570,8 @@ interface DummyEntityRepository extends CrudRepository<DummyEntity, Long> {

@Query("SELECT * FROM DUMMY_ENTITY WHERE OFFSET_DATE_TIME > :threshhold")
List<DummyEntity> findByOffsetDateTime(@Param("threshhold") OffsetDateTime threshhold);

List<DummyEntity> findByFlagTrue();
}

@Configuration
Expand Down Expand Up @@ -603,10 +618,12 @@ public void onApplicationEvent(AbstractRelationalEvent<?> event) {
@Data
@NoArgsConstructor
static class DummyEntity {

String name;
Instant pointInTime;
OffsetDateTime offsetDateTime;
@Id private Long idProp;
boolean flag;

public DummyEntity(String name) {
this.name = name;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@
*/
package org.springframework.data.jdbc.repository.config;

import static java.util.Arrays.*;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;

import java.util.Arrays;
import java.util.Collections;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;

import org.junit.jupiter.api.Test;
Expand All @@ -29,14 +30,17 @@
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.ReadingConverter;
import org.springframework.data.convert.WritingConverter;
import org.springframework.data.jdbc.core.JdbcAggregateTemplate;
import org.springframework.data.jdbc.core.convert.DataAccessStrategy;
import org.springframework.data.jdbc.core.convert.JdbcConverter;
import org.springframework.data.jdbc.core.convert.JdbcCustomConversions;
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
import org.springframework.data.relational.core.dialect.Dialect;
import org.springframework.data.relational.core.dialect.HsqlDbDialect;
import org.springframework.data.relational.core.dialect.LimitClause;
import org.springframework.data.relational.core.dialect.LockClause;
import org.springframework.data.relational.core.sql.render.SelectRenderContext;
import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
Expand All @@ -53,7 +57,7 @@ void configuresInfrastructureComponents() {

assertApplicationContext(context -> {

List<Class<?>> expectedBeanTypes = Arrays.asList(DataAccessStrategy.class, //
List<Class<?>> expectedBeanTypes = asList(DataAccessStrategy.class, //
JdbcMappingContext.class, //
JdbcConverter.class, //
JdbcCustomConversions.class, //
Expand All @@ -70,11 +74,26 @@ void configuresInfrastructureComponents() {
void registersSimpleTypesFromCustomConversions() {

assertApplicationContext(context -> {

JdbcMappingContext mappingContext = context.getBean(JdbcMappingContext.class);
assertThat( //
mappingContext.getPersistentEntity(AbstractJdbcConfigurationUnderTest.Blah.class) //
).describedAs("Blah should not be an entity, since there is a WritingConversion configured for it") //
.isNull();

}, AbstractJdbcConfigurationUnderTest.class, Infrastructure.class);
}

@Test // #908
void userProvidedConversionsOverwriteDialectSpecificConversions() {

assertApplicationContext(applicationContext -> {

Optional<Class<?>> customWriteTarget = applicationContext.getBean(JdbcCustomConversions.class)
.getCustomWriteTarget(Boolean.class);

assertThat(customWriteTarget).contains(String.class);

}, AbstractJdbcConfigurationUnderTest.class, Infrastructure.class);
}

Expand Down Expand Up @@ -106,12 +125,12 @@ static class AbstractJdbcConfigurationUnderTest extends AbstractJdbcConfiguratio
@Override
@Bean
public Dialect jdbcDialect(NamedParameterJdbcOperations operations) {
return HsqlDbDialect.INSTANCE;
return new DummyDialect();
}

@Override
public JdbcCustomConversions jdbcCustomConversions() {
return new JdbcCustomConversions(Collections.singletonList(Blah2BlubbConverter.INSTANCE));
protected List<?> userConverters() {
return asList(Blah2BlubbConverter.INSTANCE, BooleanToYnConverter.INSTANCE);
}

@WritingConverter
Expand All @@ -127,6 +146,59 @@ public Blubb convert(Blah blah) {
private static class Blah {}

private static class Blubb {}

private static class DummyDialect implements Dialect {
@Override
public LimitClause limit() {
return null;
}

@Override
public LockClause lock() {
return null;
}

@Override
public SelectRenderContext getSelectContext() {
return null;
}

@Override
public Collection<Object> getConverters() {
return asList(BooleanToNumberConverter.INSTANCE, NumberToBooleanConverter.INSTANCE);
}
}

@WritingConverter
enum BooleanToNumberConverter implements Converter<Boolean, Number> {
INSTANCE;

@Override
public Number convert(Boolean source) {
return source ? 1 : 0;
}
}

@ReadingConverter
enum NumberToBooleanConverter implements Converter<Number, Boolean> {
INSTANCE;

@Override
public Boolean convert(Number source) {
return source.intValue() == 0;
}
}

@WritingConverter
enum BooleanToYnConverter implements Converter<Boolean, String> {
INSTANCE;

@Override
public String convert(Boolean source) {
return source ? "Y" : "N";
}
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import java.util.List;
import java.util.Properties;

import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
Expand Down Expand Up @@ -457,7 +458,7 @@ public void createsQueryToFindAllEntitiesByBooleanAttributeTrue() throws Excepti
RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[0]);
ParametrizedQuery query = jdbcQuery.createQuery(accessor, returnedType);

assertThat(query.getQuery()).isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"ACTIVE\" = TRUE");
assertThat(query.getQuery()).isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"ACTIVE\" = :active");
}

@Test // DATAJDBC-318
Expand All @@ -468,7 +469,7 @@ public void createsQueryToFindAllEntitiesByBooleanAttributeFalse() throws Except
RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[0]);
ParametrizedQuery query = jdbcQuery.createQuery(accessor, returnedType);

assertThat(query.getQuery()).isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"ACTIVE\" = FALSE");
assertThat(query.getQuery()).isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"ACTIVE\" = :active");
}

@Test // DATAJDBC-318
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ CREATE TABLE dummy_entity
id_Prop BIGINT GENERATED BY DEFAULT AS IDENTITY ( START WITH 1 ) PRIMARY KEY,
NAME VARCHAR(100),
POINT_IN_TIME TIMESTAMP,
OFFSET_DATE_TIME TIMESTAMP -- with time zone is only supported with z/OS
OFFSET_DATE_TIME TIMESTAMP, -- with time zone is only supported with z/OS
FLAG BOOLEAN
);
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ CREATE TABLE dummy_entity
id_Prop BIGINT GENERATED BY DEFAULT AS IDENTITY ( START WITH 1 ) PRIMARY KEY,
NAME VARCHAR(100),
POINT_IN_TIME TIMESTAMP,
OFFSET_DATE_TIME TIMESTAMP WITH TIME ZONE
OFFSET_DATE_TIME TIMESTAMP WITH TIME ZONE,
FLAG BOOLEAN
);
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ CREATE TABLE dummy_entity
id_Prop BIGINT GENERATED BY DEFAULT AS IDENTITY ( START WITH 1 ) PRIMARY KEY,
NAME VARCHAR(100),
POINT_IN_TIME TIMESTAMP,
OFFSET_DATE_TIME TIMESTAMP WITH TIME ZONE
OFFSET_DATE_TIME TIMESTAMP WITH TIME ZONE,
FLAG BOOLEAN
);
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ CREATE TABLE dummy_entity
id_Prop BIGINT AUTO_INCREMENT PRIMARY KEY,
NAME VARCHAR(100),
POINT_IN_TIME TIMESTAMP(3),
OFFSET_DATE_TIME TIMESTAMP(3)
OFFSET_DATE_TIME TIMESTAMP(3),
FLAG BOOLEAN
);
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ CREATE TABLE dummy_entity
id_Prop BIGINT IDENTITY PRIMARY KEY,
NAME VARCHAR(100),
POINT_IN_TIME DATETIME,
OFFSET_DATE_TIME DATETIMEOFFSET
OFFSET_DATE_TIME DATETIMEOFFSET,
FLAG BIT
);
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
SET SQL_MODE='ALLOW_INVALID_DATES';

CREATE TABLE dummy_entity
CREATE TABLE DUMMY_ENTITY
(
id_Prop BIGINT AUTO_INCREMENT PRIMARY KEY,
ID_PROP BIGINT AUTO_INCREMENT PRIMARY KEY,
NAME VARCHAR(100),
POINT_IN_TIME TIMESTAMP(3) default null,
OFFSET_DATE_TIME TIMESTAMP(3) default null
POINT_IN_TIME TIMESTAMP(3) DEFAULT NULL,
OFFSET_DATE_TIME TIMESTAMP(3) DEFAULT NULL,
FLAG BIT(1)
);
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ CREATE TABLE DUMMY_ENTITY
ID_PROP NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY PRIMARY KEY,
NAME VARCHAR2(100),
POINT_IN_TIME TIMESTAMP,
OFFSET_DATE_TIME TIMESTAMP WITH TIME ZONE
OFFSET_DATE_TIME TIMESTAMP WITH TIME ZONE,
FLAG NUMBER(1,0)
);
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ CREATE TABLE dummy_entity
id_Prop SERIAL PRIMARY KEY,
NAME VARCHAR(100),
POINT_IN_TIME TIMESTAMP,
OFFSET_DATE_TIME TIMESTAMP WITH TIME ZONE
OFFSET_DATE_TIME TIMESTAMP WITH TIME ZONE,
FLAG BOOLEAN
);
4 changes: 2 additions & 2 deletions spring-data-relational/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@
<modelVersion>4.0.0</modelVersion>

<artifactId>spring-data-relational</artifactId>
<version>2.3.0-SNAPSHOT</version>
<version>2.3.0-908-boolean-for-derived-queries-SNAPSHOT</version>

<name>Spring Data Relational</name>
<description>Spring Data Relational support</description>

<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-relational-parent</artifactId>
<version>2.3.0-SNAPSHOT</version>
<version>2.3.0-908-boolean-for-derived-queries-SNAPSHOT</version>
</parent>

<properties>
Expand Down
Loading