Spring Data JPA sql查询返回对象

问题概述:

JPA主要适用于强对象关系映射的场景,但是再做查询时需要返回的结果千差万别。所以,当我们使用非数据库对象作为返回结果对象时,

@Data
public class testDTO  {
    Integer ageSum;
    Integer count;
}

 

@Repository
public interface TestDTORepository extends JpaRepository<testDTO, Long>, JpaSpecificationExecutor {
   
@Query(value = "select count(1) count,sum(age) ageSum from student",nativeQuery = true)
public testDTO get();

@Query(value = "select count(1) count,sum(age) ageSum from student",nativeQuery = true)
public List<testDTO> getList();
}

 

往往会启动报错。

Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not a managed type: class com.example.demo.dao.testDTO

再网上收了好久,只有一种Object[]去接受返回结果的方法(Map,Json同样报上面的错)。

当然会感觉到很蠢,应为不看Sql的话,我们完全没办法知道数组中的每一位代表的是对象中的哪一个值。

苦思无果。

最后在stackoverflow上找到了还算可以的解决方法。

地址参考:https://stackoverflow.com/questions/44436287/nativequery-spring-data-return-object?r=SearchResults

再repository中定义接口,接口中方法为sql返回参数的对应get方法(其他方法测试无效)。

返回此接口对象。

 

改造后代码:

package com.example.demo.repository;

import com.example.demo.dao.User;
import com.example.demo.dao.testDTO;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface TestDTORepository extends JpaRepository<User, Long>, JpaSpecificationExecutor {
    public interface CountAndAgeSum {
        Integer getCount();
        Integer getAgeSum();
    }

    @Query(value = "select count(1) count,sum(age) ageSum from student",nativeQuery = true)
    public CountAndAgeSum get();

    @Query(value = "select count(1) count,sum(age) ageSum from student",nativeQuery = true)
    public List<CountAndAgeSum> getList();

}

 

那么接来的问题就好解决了。

可以通过放射去映射对象,从而得到你想要的对象。

如:

package com.example.demo.Util;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.stream.Collectors;

public class GetClassUtil {


    public static Object getClass(Object obj, Class cla) throws IllegalAccessException, InstantiationException, InvocationTargetException {
        Object c = cla.newInstance();
        Method[] objMethodArray = obj.getClass().getDeclaredMethods();
        Method[] claMethodArray = cla.getDeclaredMethods();
        for (Method objMethod : objMethodArray) {
            for (Method claMethod : claMethodArray) {
                String claMethodName = claMethod.getName().toUpperCase();
                String objMethodName = objMethod.getName().toUpperCase().replaceAll("GET", "");
                if (claMethodName.startsWith("SET") && claMethodName.contains(objMethodName)) {
                    claMethod.invoke(c, objMethod.invoke(obj));
                    break;
                }
            }
        }
        return c;
    }

    public static List getClassList(List objList, Class cla) throws IllegalAccessException, InvocationTargetException, InstantiationException {
        return (List) objList.stream().map(o -> {
            try {
                return GetClassUtil.getClass(o, cla);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
            return null;
        }).collect(Collectors.toList());
    }

}

该方法类的使用的话,可参考下面代码:

TestDTORepository.CountAndAgeSum c = testDTORepository.get();
testDTO t = null;
try {
     t = (testDTO)GetClassUtil.getClass(c,testDTO.class);
} catch (IllegalAccessException e) {
    e.printStackTrace();
} catch (InstantiationException e) {
    e.printStackTrace();
} catch (InvocationTargetException e) {
    e.printStackTrace();
}

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值