DATAJPA-506 - Add support for conversion of Blob values to byte[] in native queries.
JpaQueryExecution no applies type conversion for Blob instances to be able to return byte[] from repository calls. Original pull request: #72.
This commit is contained in:
committed by
Oliver Gierke
parent
af45da40c6
commit
68e2ee5ed9
@@ -24,6 +24,7 @@ import javax.persistence.Query;
|
||||
import javax.persistence.StoredProcedureQuery;
|
||||
import javax.persistence.TypedQuery;
|
||||
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Slice;
|
||||
@@ -43,6 +44,12 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public abstract class JpaQueryExecution {
|
||||
|
||||
private static final DefaultConversionService conversionService = new DefaultConversionService();
|
||||
|
||||
static {
|
||||
conversionService.addConverter(JpaResultConverters.BlobToByteArrayConverter.INSTANCE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the given {@link AbstractStringBasedJpaQuery} with the given {@link ParameterBinder}.
|
||||
*
|
||||
@@ -55,11 +62,26 @@ public abstract class JpaQueryExecution {
|
||||
Assert.notNull(query);
|
||||
Assert.notNull(values);
|
||||
|
||||
Object result;
|
||||
|
||||
try {
|
||||
return doExecute(query, values);
|
||||
result = doExecute(query, values);
|
||||
} catch (NoResultException e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (result == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
JpaQueryMethod queryMethod = query.getQueryMethod();
|
||||
Class<?> requiredType = queryMethod.getReturnType();
|
||||
|
||||
if (void.class.equals(requiredType) || requiredType.isAssignableFrom(result.getClass())) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return conversionService.convert(result, requiredType);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.repository.query;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.sql.Blob;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.dao.CleanupFailureDataAccessException;
|
||||
import org.springframework.dao.DataRetrievalFailureException;
|
||||
import org.springframework.util.StreamUtils;
|
||||
|
||||
/**
|
||||
* Container for additional JPA result {@link Converter}s.
|
||||
*
|
||||
* @author Thomas Darimont
|
||||
* @since 1.6
|
||||
*/
|
||||
class JpaResultConverters {
|
||||
|
||||
/**
|
||||
* {@code private} to prevent instantiation.
|
||||
*/
|
||||
private JpaResultConverters() {}
|
||||
|
||||
/**
|
||||
* Converts the given {@link Blob} into a {@code byte[]}.
|
||||
*
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
enum BlobToByteArrayConverter implements Converter<Blob, byte[]> {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public byte[] convert(Blob source) {
|
||||
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
InputStream blobStream = null;
|
||||
try {
|
||||
|
||||
blobStream = source.getBinaryStream();
|
||||
|
||||
if (blobStream != null) {
|
||||
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
StreamUtils.copy(blobStream, baos);
|
||||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
} catch (SQLException e) {
|
||||
throw new DataRetrievalFailureException("Couldn't retrieve data from blob.", e);
|
||||
} catch (IOException e) {
|
||||
throw new DataRetrievalFailureException("Couldn't retrieve data from blob.", e);
|
||||
} finally {
|
||||
if (blobStream != null) {
|
||||
try {
|
||||
blobStream.close();
|
||||
} catch (IOException e) {
|
||||
throw new CleanupFailureDataAccessException("Couldn't close binary stream for given blob.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1390,6 +1390,23 @@ public class UserRepositoryTests {
|
||||
flushTestUsers();
|
||||
|
||||
byte[] result = null; // repository.findBinaryDataByIdJpaQl(firstUser.getId());
|
||||
|
||||
assertThat(result.length, is(data.length));
|
||||
assertThat(result, is(data));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAJPA-506
|
||||
*/
|
||||
@Test
|
||||
public void findBinaryDataByIdNative() throws Exception {
|
||||
|
||||
byte[] data = "Woho!!".getBytes("UTF-8");
|
||||
firstUser.setBinaryData(data);
|
||||
|
||||
flushTestUsers();
|
||||
|
||||
byte[] result = repository.findBinaryDataByIdNative(firstUser.getId());
|
||||
assertThat(result.length, is(data.length));
|
||||
assertThat(result, is(data));
|
||||
}
|
||||
|
||||
@@ -445,4 +445,10 @@ public interface UserRepository extends JpaRepository<User, Integer>, JpaSpecifi
|
||||
* @see DATAJPA-551
|
||||
*/
|
||||
Slice<User> findTop2UsersBy(Pageable page);
|
||||
|
||||
/**
|
||||
* @see DATAJPA-506
|
||||
*/
|
||||
@Query(value = "select u.binaryData from User u where u.id = ?", nativeQuery = true)
|
||||
byte[] findBinaryDataByIdNative(Integer id);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user