本篇内容介绍了“Spring Data Jpa原生SQL返回自定义对象最简洁方式是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
创新互联公司是一家专注于成都做网站、成都网站建设、成都外贸网站建设与策划设计,运河网站建设哪家好?创新互联公司做网站,专注于网站建设十多年,网设计领域的专业建站公司;建站业务涵盖:运河等地区。运河做网站价格咨询:028-86922220
此文章只讨论两种方式查询, 使用jpa关键字查询和自定义sql
// 方式1 1. ListfindByName(String name); // 方式2 2. @Query(value = "select name from t_users where name = ?", nativeQuery = true) List findByName2(String name);
即通过定义一个接口接口 UserName,两种方式都支持通过定义接口接受返回,JPA原生支持
public interface UserName {
String getNname();
}方式一 JAP原生支持自定义对象,但条件是而且只有一个构造函数,有些工具类需要用到默认构造函数,不方便
方式二 JAP不支持自定义对象,会返回Object[] 对象数组
例子只是解决方式二, 如果需要解决方式一构造函数问题,可以借鉴,下面例子自己实现 我们定义一个接口ReabamDTO
public interface ReabamDTO {
}内容是map 转 ReabamDTO
public final class JpaConvert implements GenericConverter {
@Override
public Set getConvertibleTypes() {
return Collections.singleton(new ConvertiblePair(Map.class, ReabamDTO.class));
}
@Override
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
return map2Pojo(source, targetType.getObjectType());
}
public static T map2Pojo(Object entity, Class tClass) {
CopyOptions copyOptions = CopyOptions.create()
.setIgnoreCase(true)
.setIgnoreError(true)
.setIgnoreNullValue(true)
.setFieldNameEditor(StrUtil::toUnderlineCase);
return BeanUtil.toBean(entity, tClass, copyOptions);
}
} 将自定义convert加入到GenericConversionService
@Configuration
public class JpaConfig {
@PostConstruct
public void init() {
GenericConversionService genericConversionService = ((GenericConversionService) DefaultConversionService.getSharedInstance());
genericConversionService.addConverter(new JpaConvert());
}
}public interface UsersRepository extends JpaRepository{ List findByName(String name); @Query(value = "select name from t_users where name = ?", nativeQuery = true) List findByName2(String name); }
@Data
@ToString
@NoArgsConstructor
public class UserName implements ReabamDTO {
private String name;
}@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = DemoApplication.class, properties = {"spring.profiles.active=local"})
class DemoApplicationTests {
@Autowired
private UsersRepository usersRepository;
@Test
void contextLoads() {
Users users = new Users();
users.setName("A");
users.setAge(1);
users.setAddress("AA");
usersRepository.save(users);
}
/**
* 非自定义sql可以返回自定义对象
*/
@Test
void t2() {
List a = usersRepository.findByName("A");
System.out.println(a);
}
/**
* 自定义sql 自定义对象
*/
@Test
void t3() {
List a = usersRepository.findByName2("A");
System.out.println(a);
}
} 查看报错信息,找不到转换器异常, 那么只需要加入对应的装换器就可以了,
org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [org.springframework.data.jpa.repository.query.AbstractJpaQuery$TupleConverter$TupleBackedMap] to type [com.architeture.demo.UserName] at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:322) at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:195) at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:175) at org.springframework.data.repository.query.ResultProcessor$ProjectingConverter.convert(ResultProcessor.java:309) at org.springframework.data.repository.query.ResultProcessor$ChainingConverter.lambda$and$0(ResultProcessor.java:225) at org.springframework.data.repository.query.ResultProcessor$ChainingConverter.convert(ResultProcessor.java:236) at org.springframework.data.repository.query.ResultProcessor.processResult(ResultProcessor.java:156) at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:158) at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:143)
通过查看源码, 获取转换器的位置 org.springframework.core.convert.support.GenericConversionService#getConverter
@Nullable
protected GenericConverter getConverter(TypeDescriptor sourceType, TypeDescriptor targetType) {
ConverterCacheKey key = new ConverterCacheKey(sourceType, targetType);
GenericConverter converter = this.converterCache.get(key);
if (converter != null) {
return (converter != NO_MATCH ? converter : null);
}
converter = this.converters.find(sourceType, targetType);
if (converter == null) {
converter = getDefaultConverter(sourceType, targetType);
}
if (converter != null) {
this.converterCache.put(key, converter);
return converter;
}
this.converterCache.put(key, NO_MATCH);
return null;
}继续看源码, 查找能加入转换器位置 converter = this.converters.find(sourceType, targetType);
@Nullable
public GenericConverter find(TypeDescriptor sourceType, TypeDescriptor targetType) {
// Search the full type hierarchy
// 获取
List> sourceCandidates = getClassHierarchy(sourceType.getType());
List> targetCandidates = getClassHierarchy(targetType.getType());
for (Class> sourceCandidate : sourceCandidates) {
for (Class> targetCandidate : targetCandidates) {
ConvertiblePair convertiblePair = new ConvertiblePair(sourceCandidate, targetCandidate);
GenericConverter converter = getRegisteredConverter(sourceType, targetType, convertiblePair);
if (converter != null) {
return converter;
}
}
}
return null;
}

此方法 源对象TupBackedMap父类或接口和UserName父类或接口进行组合,获取到对应的转换器
TupBackedMap的父类或接口

org.springframework.core.convert.support.GenericConversionService#addConverter(org.springframework.core.convert.converter.GenericConverter)
@Nullable
private GenericConverter getRegisteredConverter(TypeDescriptor sourceType,
TypeDescriptor targetType, ConvertiblePair convertiblePair) {
// Check specifically registered converters
ConvertersForPair convertersForPair = this.converters.get(convertiblePair);
if (convertersForPair != null) {
GenericConverter converter = convertersForPair.getConverter(sourceType, targetType);
if (converter != null) {
return converter;
}
}
// Check ConditionalConverters for a dynamic match
for (GenericConverter globalConverter : this.globalConverters) {
if (((ConditionalConverter) globalConverter).matches(sourceType, targetType)) {
return globalConverter;
}
}
return null;
}可以看到在 ConvertersForPair convertersForPair = this.converters.get(convertiblePair); 在convertes中加入转换器
org.springframework.core.convert.support.GenericConversionService.Converters
private static class Converters {
private final Map converters = new LinkedHashMap<>(36);
public void add(GenericConverter converter) {
}
} 查看调用 add 方法位置, org.springframework.core.convert.support.GenericConversionService#addConverter(org.springframework.core.convert.converter.GenericConverter)最终定位到这里
“Spring Data Jpa原生SQL返回自定义对象最简洁方式是什么”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注创新互联网站,小编将为大家输出更多高质量的实用文章!