从Spring Data Jpa查询返回自定义对象

时间:2018-07-16 10:44:18

标签: java spring spring-boot spring-data-jpa spring-data

我在jpa信息库类中有一个自定义查询:

// Filter the User documents
MatchOperation matchUser = Aggregation.match(Criteria.where("userId").is(userId));

// Join CollAddr 
LookupOperation lookupEvent = LookupOperation.newLookup()
                .from("CollAddr")
                .localField("addrId")
                .foreignField("_id")
                .as("address");

// Project only address
 ProjectionOperation projectAddr = Aggregation.project("address");


Aggregation aggregation = Aggregation.newAggregation(matchUser, lookupEvent,projectAddr);

Document addr = mongoTemplate.aggregate(aggregation, "CollUserAddr", Document.class).getUniqueMappedResult();

该查询返回请求最多的10位实习导师/教授;结果由教授的信息和一个整数值(计数)组成。

教授模型类别:

ArrayList

ProfessorInternshipCount模型(用于封装查询结果):

Address

现在,我很难将查询返回的内容与我创建的模型绑定在一起。 更准确地说,我得到以下异常:

package it.univaq.we.internshipTutor.repository;
import ...

public interface ProfessorRepository extends JpaRepository<Professor, Long> {

    List<Professor> findAll();

    ...

    @Query(value =  "SELECT professor.id, professor.department_id, " +
                    "professor.first_name, professor.last_name, " +
                    "professor.email, COUNT(professor_id) as count " +
                    "FROM professor LEFT JOIN student_internship ON professor.id = professor_id " +
                    "GROUP BY professor_id ORDER BY count DESC LIMIT ?1", nativeQuery = true)
    List<ProfessorInternshipCount> mostRequestedProfessors(int limit);
}

我做错什么了吗?有做我想做的更好的方法吗?

3 个答案:

答案 0 :(得分:4)

您可以使用投影轻松实现此目的。 这里有波纹管列:

private String firstName;
private String lastName;
private Long id;

使用查询中的getter创建接口。您的投影将如下所示:

public interface ITestProjection {
    Long getId();
    Integer getCount();
    String getFirstName();
    String getLastName();
}

您的查询会这样:

@Query(value = "SELECT professor.id, professor.department_id, " +
                    "professor.first_name, professor.last_name, " +
                    "professor.email, COUNT(professor_id) as count " +
                    "FROM professor LEFT JOIN student_internship ON professor.id = professor_id " +
                    "GROUP BY professor_id ORDER BY count DESC LIMIT =?1", nativeQuery = true)
    ArrayList<ITestProjection> findDataWithCount(Integer limit);

希望这可以解决您的问题。

有关更多详细信息,请访问this thread

谢谢:)

答案 1 :(得分:1)

您可以通过以下两种方式执行此操作。

  1. 使用ModelMapper将实体转换为目标bean类型
  2. 使用Spring Projection做到这一点

浏览文章以获取更多细节。

http://javasampleapproach.com/spring-framework/spring-data/query-alter-domain-model-spring-jpa-projection-springboot-mysql-database

答案 2 :(得分:1)

例如,让我们拥有:

  • 用户-具有多个字段的实体对象。

  • UserBean -只是要转换我们数据的对象。

不良做法:

 @Repository
    public class ReportingRepository {

        @PersistenceContext
        private EntityManager em;

        public List<UserBean> findQuery() {
            Query query = em.createNativeQuery("select  ...  from Table  INNER JOIN ...");
            List<UserBean> items = (List<UserBean>) query.getResultList();
            return items;
        }

    }

但是它将返回数组中的值,因此,如果我们编写以下代码,它会更漂亮,这是更好的做法:

query.unwrap(SQLQuery.class)
           .addScalar("instance name", StringType.INSTANCE)
           .addScalar("second instance name", IntegerType.INSTANCE)
           .setResultTransformer(Transformers.aliasToBean(UserBean.class));

   List<UserBean> items = query.getResultList();

因此,最终所有内容都被转换为UserBean类。 注意,在 addScalar 方法中,您应该传递实例变量名称(在您的问题中,您具有 count 变量)