【问题标题】:How to get selective column in spring boot JPA?如何在 Spring Boot JPA 中获取选择性列?
【发布时间】:2020-08-16 05:46:11
【问题描述】:

我是 Spring Boot 新手。

我有两个实体 Invite 和 User。

@Entity
public class Invite {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    
    @Column(name="email")
    private String email_id;
    private String mobile;
    private String pincode;
    private String name;
    private String status;
    private Date created_on;
    private Date updated_on;
 
    //gettes and setters
}


@Entity
public class User {
    @Id
    @GeneratedValue(strategy= GenerationType.IDENTITY)
    private int id;
    
    @OneToOne
    private Invite invite;
    private String firstName;
    private String LastName;
    @JsonIgnore
    private String password;
    private Date created_on;
    private Date updated_on;

    // getters and setters

}

我想要以下数据

+---------+---------------------------------------------+
|  id     |   firstName    email_id         mobile      |
+-------------------+------------+----------------------+
|         |         |            |                      |
| 1       |Ram      | s@mail.com |      1111111111      |
|         |         |            |                      |
+---------+---------+------------+----------------------+

所以我在 UserRepository 中创建了以下查询:

@Repository
public interface UserRepository extends JpaRepository<User, Integer> {

    
    @Query("select u.id,u.firstName,i.email_id, i.mobile from User u inner join u.invite i")
    public List<User> getUserDetails();
}

所以我收到以下错误 -

Failed to convert from type [java.lang.Object[]] to type [@org.springframework.data.jpa.repository.Query com.example.jpa.JPA.entity.User] for value

我知道这是因为返回值是 Object 类型,我正试图将它输入到用户中。

您能否给我一种无需创建额外 DTO 类或接口即可获取任何数据的方法?

【问题讨论】:

  • 并补充说,您需要了解问题与Spring Boot无关。这是一个与 JPA 相关的问题,可以使用 Jpa Query 或 @Query 和 Query Projection 接口和类的 Data Jpa 抽象来解决。更正标签

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


【解决方案1】:

你已经知道问题所在了。

@Query("select u.id,u.firstName,i.email_id, i.mobile from User u inner join u.invite i")
List<User> getUserDetails();

您选择了几列,但要求 Data-Jpa 将 User 对象列表返回给您。

所以您首先需要了解 JPA 规范对使用 JPQL 的规定。

  • select u from User u where u.id = :id -> 这将返回User 类型对象的列表 本机查询是:SELECT * FROM USER WHERE ID = "{whatever value you passed}";

  • select u.username from User u where u.id = :id" -> 这仅返回用户名,可以说是字符串类型。因此,如果您使用 TypedQuery,则返回对象类型为 String 类型;如果您使用 Query,则返回 Object。生成的对应SQL为SELECT u.USERNAME FROM USER u WHERE u.id = {id}

  • select u.id, u.username from User u where u.id = :id -> 这将返回 Object[]。这是您需要 DTO 投影将其映射到您想要的正确类型的时候。

使用本机 JPA 实现,您可以使用 DTO ProjectionQuery Projection

我主要使用 JPA 规范中的 DTO 投影而不使用查询投影,因此我给出了 DTO 投影的示例,但如果通过上述文档,可以很好地参考如何使用每个抽象/功能。

  1. 定义一个类来表示我正在考虑的 DTO 和包:com.example。 包名很重要,因为您需要完整的类名以在 JPQL 中参考
package com.example;


class UserDTO {
 int id;
 String firstName,
 String email_id;
 String mobile;

 //All args constructor is needed and madatory
public User(int id, String firstName, String email_id, String mobile) {
 // assignments
}
  // getters and setters
}

在存储库中:

@Query("select new com.example.UserDTO(u.id,u.firstName,i.email_id, i.mobile) from User u inner join u.invite i")
List<UserDTO> getUserDetails();

最重要的是:新的完全限定类名(您正在获取的所有列)

这就是您如何将 DTO 投影与 JPQL 和 Data Jpa Repository 一起使用。

【讨论】:

  • 谢谢。我们能否以同样的方式使用 Tuple。
  • 是的,检查我分享的链接。 Vlad Mihalcea 是 Hibernate 的主要贡献者之一,浏览他的博客是您能做的最好的事情之一。您还应该通过JPA specHibernate User Guide
  • 你能告诉我使用元组的相同示例吗
  • 您能否检查一下我在上面分享的link。有一个 DTO 和 Tuple 的例子
【解决方案2】:

User 类中为您的选择性列编写一个构造函数并在查询中使用。确保您还在 Invite 类中为 email_idmobile 使用构造函数,并在 User 的构造函数中使用它。

@Query("select new com.example.jpa.JPA.entity.User(u.id,u.firstName,i.email_id, i.mobile) from User u inner join u.invite i")
public List<User> getUserDetails();

在 User 和 Invite 类中使用这个构造函数

public User(int id, String firstName, String email_id, String mobile) {
 // assign id and firstName
 // call invite class constuctor 
}

public Invite(String email_id, String mobile) {
 // assign email_id and mobile
}

【讨论】:

  • 你错过了关键字new
  • select new com.example.jpa.JPA.entity.User(u.id, new com.example.userDefinedObject(u.firstName) from ... 这是有效的声明吗?
  • @JavaLearner 不,而是在 User 构造函数中调用内部构造函数
【解决方案3】:

如果您想在查询结果中选择字段或自定义查询结果,您可以简单地使用jpa Projection。创建具有相关属性方法的接口

【讨论】:

  • OP 说无需创建额外的 DTO 类或接口即可获取任何数据
【解决方案4】:

试试这个..这对我有用: spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.DefaultNamingStrategy

这要添加到 application.properties 中

【讨论】:

    猜你喜欢
    • 2021-11-30
    • 2021-08-17
    • 2019-11-10
    • 2019-08-19
    • 1970-01-01
    • 2022-07-01
    • 2019-07-20
    • 2014-10-21
    • 2023-02-03
    相关资源
    最近更新 更多