Do not convert binary data in List<byte[]> to array SQL type.
byte[] is mapped to BINARY data and is not considered tuple data. The explicit check for byte[] is not very nice but matches the special handling in MappingJdbcConverter.writeJdbcValue Closes #1900 Original pull request: #1903
This commit is contained in:
committed by
Mark Paluch
parent
37c3095cb9
commit
5204336acc
@@ -93,7 +93,8 @@ public class StringBasedJdbcQuery extends AbstractJdbcQuery {
|
||||
public StringBasedJdbcQuery(JdbcQueryMethod queryMethod, NamedParameterJdbcOperations operations,
|
||||
@Nullable RowMapper<?> defaultRowMapper, JdbcConverter converter,
|
||||
QueryMethodEvaluationContextProvider evaluationContextProvider) {
|
||||
this(queryMethod, operations, result -> (RowMapper<Object>) defaultRowMapper, converter, evaluationContextProvider);
|
||||
this(queryMethod, operations, result -> (RowMapper<Object>) defaultRowMapper,
|
||||
converter, evaluationContextProvider);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -221,7 +222,7 @@ public class StringBasedJdbcQuery extends AbstractJdbcQuery {
|
||||
TypeInformation<?> actualType = typeInformation.getActualType();
|
||||
|
||||
// tuple-binding
|
||||
if (actualType != null && actualType.getType().isArray()) {
|
||||
if (actualType != null && actualType.getType().isArray() && !actualType.getType().equals(byte[].class)) {
|
||||
|
||||
TypeInformation<?> nestedElementType = actualType.getRequiredActualType();
|
||||
return writeCollection(collection, parameter.getActualSqlType(),
|
||||
|
||||
@@ -41,7 +41,6 @@ import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.PropertiesFactoryBean;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
@@ -51,23 +50,13 @@ import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.dao.IncorrectResultSizeDataAccessException;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.domain.Example;
|
||||
import org.springframework.data.domain.ExampleMatcher;
|
||||
import org.springframework.data.domain.Limit;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.ScrollPosition;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.domain.Window;
|
||||
import org.springframework.data.domain.*;
|
||||
import org.springframework.data.jdbc.core.mapping.AggregateReference;
|
||||
import org.springframework.data.jdbc.repository.query.Modifying;
|
||||
import org.springframework.data.jdbc.repository.query.Query;
|
||||
import org.springframework.data.jdbc.repository.support.JdbcRepositoryFactory;
|
||||
import org.springframework.data.jdbc.testing.ConditionalOnDatabase;
|
||||
import org.springframework.data.jdbc.testing.DatabaseType;
|
||||
import org.springframework.data.jdbc.testing.EnabledOnDatabase;
|
||||
import org.springframework.data.jdbc.testing.EnabledOnFeature;
|
||||
import org.springframework.data.jdbc.testing.IntegrationTest;
|
||||
import org.springframework.data.jdbc.testing.TestConfiguration;
|
||||
@@ -1357,6 +1346,52 @@ public class JdbcRepositoryIntegrationTests {
|
||||
assertThat(result).containsOnly(two);
|
||||
}
|
||||
|
||||
@Test // GH-1900
|
||||
void queryByListOfByteArray() {
|
||||
|
||||
byte[] oneBytes = { 1, 2, 3, 4, 5, 6, 7, 8 };
|
||||
DummyEntity one = createDummyEntity("one");
|
||||
one.setBytes(oneBytes);
|
||||
one = repository.save(one);
|
||||
|
||||
byte[] twoBytes = { 8, 7, 6, 5, 4, 3, 2, 1 };
|
||||
DummyEntity two = createDummyEntity("two");
|
||||
two.setBytes(twoBytes);
|
||||
two = repository.save(two);
|
||||
|
||||
byte[] threeBytes = { 3, 3, 3, 3, 3, 3, 3, 3 };
|
||||
DummyEntity three = createDummyEntity("three");
|
||||
three.setBytes(threeBytes);
|
||||
three = repository.save(three);
|
||||
|
||||
List<DummyEntity> result = repository.findByBytesIn(List.of(threeBytes, oneBytes));
|
||||
|
||||
assertThat(result).extracting("idProp").containsExactlyInAnyOrder(one.idProp, three.idProp);
|
||||
}
|
||||
|
||||
@Test // GH-1900
|
||||
void queryByByteArray() {
|
||||
|
||||
byte[] oneBytes = { 1, 2, 3, 4, 5, 6, 7, 8 };
|
||||
DummyEntity one = createDummyEntity("one");
|
||||
one.setBytes(oneBytes);
|
||||
one = repository.save(one);
|
||||
|
||||
byte[] twoBytes = { 8, 7, 6, 5, 4, 3, 2, 1 };
|
||||
DummyEntity two = createDummyEntity("two");
|
||||
two.setBytes(twoBytes);
|
||||
two = repository.save(two);
|
||||
|
||||
byte[] threeBytes = { 3, 3, 3, 3, 3, 3, 3, 3 };
|
||||
DummyEntity three = createDummyEntity("three");
|
||||
three.setBytes(threeBytes);
|
||||
three = repository.save(three);
|
||||
|
||||
List<DummyEntity> result = repository.findByBytes(twoBytes);
|
||||
|
||||
assertThat(result).extracting("idProp").containsExactly(two.idProp);
|
||||
}
|
||||
|
||||
private Root createRoot(String namePrefix) {
|
||||
|
||||
return new Root(null, namePrefix,
|
||||
@@ -1487,6 +1522,12 @@ public class JdbcRepositoryIntegrationTests {
|
||||
|
||||
@Query("SELECT * FROM DUMMY_ENTITY WHERE (ID_PROP, NAME) IN (:tuples)")
|
||||
List<DummyEntity> findByListInTuple(List<Object[]> tuples);
|
||||
|
||||
@Query("SELECT * FROM DUMMY_ENTITY WHERE BYTES IN (:bytes)")
|
||||
List<DummyEntity> findByBytesIn(List<byte[]> bytes);
|
||||
|
||||
@Query("SELECT * FROM DUMMY_ENTITY WHERE BYTES = :bytes")
|
||||
List<DummyEntity> findByBytes(byte[] bytes);
|
||||
}
|
||||
|
||||
interface RootRepository extends ListCrudRepository<Root, Long> {
|
||||
@@ -1810,6 +1851,7 @@ public class JdbcRepositoryIntegrationTests {
|
||||
boolean flag;
|
||||
AggregateReference<DummyEntity, Long> ref;
|
||||
Direction direction;
|
||||
byte[] bytes = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
public DummyEntity(String name) {
|
||||
this.name = name;
|
||||
@@ -1890,6 +1932,10 @@ public class JdbcRepositoryIntegrationTests {
|
||||
return Objects.hash(name, pointInTime, offsetDateTime, idProp, flag, ref, direction);
|
||||
}
|
||||
|
||||
public void setBytes(byte[] bytes) {
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DummyEntity{" + "name='" + name + '\'' + ", idProp=" + idProp + '}';
|
||||
|
||||
@@ -12,7 +12,8 @@ CREATE TABLE dummy_entity
|
||||
OFFSET_DATE_TIME TIMESTAMP, -- with time zone is only supported with z/OS
|
||||
FLAG BOOLEAN,
|
||||
REF BIGINT,
|
||||
DIRECTION VARCHAR(100)
|
||||
DIRECTION VARCHAR(100),
|
||||
BYTES BINARY(8)
|
||||
);
|
||||
|
||||
CREATE TABLE ROOT
|
||||
|
||||
@@ -6,7 +6,8 @@ CREATE TABLE dummy_entity
|
||||
OFFSET_DATE_TIME TIMESTAMP WITH TIME ZONE,
|
||||
FLAG BOOLEAN,
|
||||
REF BIGINT,
|
||||
DIRECTION VARCHAR(100)
|
||||
DIRECTION VARCHAR(100),
|
||||
BYTES BINARY(8)
|
||||
);
|
||||
|
||||
CREATE TABLE ROOT
|
||||
|
||||
@@ -6,7 +6,8 @@ CREATE TABLE dummy_entity
|
||||
OFFSET_DATE_TIME TIMESTAMP WITH TIME ZONE,
|
||||
FLAG BOOLEAN,
|
||||
REF BIGINT,
|
||||
DIRECTION VARCHAR(100)
|
||||
DIRECTION VARCHAR(100),
|
||||
BYTES BINARY(8)
|
||||
);
|
||||
|
||||
CREATE TABLE ROOT
|
||||
|
||||
@@ -6,7 +6,8 @@ CREATE TABLE dummy_entity
|
||||
OFFSET_DATE_TIME TIMESTAMP(3),
|
||||
FLAG BOOLEAN,
|
||||
REF BIGINT,
|
||||
DIRECTION VARCHAR(100)
|
||||
DIRECTION VARCHAR(100),
|
||||
BYTES BINARY(8)
|
||||
);
|
||||
|
||||
CREATE TABLE ROOT
|
||||
|
||||
@@ -12,7 +12,8 @@ CREATE TABLE dummy_entity
|
||||
OFFSET_DATE_TIME DATETIMEOFFSET,
|
||||
FLAG BIT,
|
||||
REF BIGINT,
|
||||
DIRECTION VARCHAR(100)
|
||||
DIRECTION VARCHAR(100),
|
||||
BYTES VARBINARY(8)
|
||||
);
|
||||
|
||||
CREATE TABLE ROOT
|
||||
|
||||
@@ -9,7 +9,8 @@ CREATE TABLE DUMMY_ENTITY
|
||||
OFFSET_DATE_TIME TIMESTAMP(3) DEFAULT NULL,
|
||||
FLAG BIT(1),
|
||||
REF BIGINT,
|
||||
DIRECTION VARCHAR(100)
|
||||
DIRECTION VARCHAR(100),
|
||||
BYTES BINARY(8)
|
||||
);
|
||||
|
||||
CREATE TABLE ROOT
|
||||
|
||||
@@ -12,7 +12,8 @@ CREATE TABLE DUMMY_ENTITY
|
||||
OFFSET_DATE_TIME TIMESTAMP WITH TIME ZONE,
|
||||
FLAG NUMBER(1,0),
|
||||
REF NUMBER,
|
||||
DIRECTION VARCHAR2(100)
|
||||
DIRECTION VARCHAR2(100),
|
||||
BYTES RAW(8)
|
||||
);
|
||||
|
||||
CREATE TABLE ROOT
|
||||
|
||||
@@ -12,7 +12,8 @@ CREATE TABLE dummy_entity
|
||||
OFFSET_DATE_TIME TIMESTAMP WITH TIME ZONE,
|
||||
FLAG BOOLEAN,
|
||||
REF BIGINT,
|
||||
DIRECTION VARCHAR(100)
|
||||
DIRECTION VARCHAR(100),
|
||||
BYTES BYTEA
|
||||
);
|
||||
|
||||
CREATE TABLE ROOT
|
||||
|
||||
Reference in New Issue
Block a user