【问题标题】:Joining two tables without JPQL在没有 JPQL 的情况下连接两个表
【发布时间】:2021-03-28 14:09:14
【问题描述】:

我必须对 MySQL 表 TICKET-是父表,USER-是子表,多对一关系。

=TICKET=
PK(ID)
summary
message
FK(user_id) references USER(user_id)

=USER=
PK(ID)
email
password

还有 JPA 实体

@Entity 
class TICKET {
    @Id
    private Integer ID;
    private String summary;
    private String message;
    @ManyToOne
    @JoinColumn(name="user")
    private USER user;
}

@Entity
class USER {
    @Id
    private Integer ID;
    private String email;
    private String password;
}

如果我通过 ID 进行查询以获取票证,它还会返回不好的用户信息(USER.ID、USER.email、USER.password)。

ticketsCrudRepository.findById(ticketId);

我想要的是得到一个如下所示的表格:

TICKET.ID | summary | message | USER.email

我知道如何在 MySQL 中做到这一点,但 JPA 对我来说太重要了。我不想使用 JPQL 或本地查询语言。 有什么建议吗?

【问题讨论】:

    标签: java mysql hibernate jpa


    【解决方案1】:

    当您获取票证时,您还会得到一个用户,因为@ManyToOne 默认情况下具有FetchType.EAGER。您可以通过将注释更改为 @ManyToOne(fetch = FetchType.LAZY)

    来更改此设置

    要进行搜索,您可以尝试类似的方法

    public List<Object[]> getTikcetsForUser(final User user) {
       String hql = "select t.id, t.summary, t.message, u.email "
                    + "from Tikcet t, User u "
                    + "where ticket.user = :user";
    
       Query<Object[]> query = getSession().createQuery(hql, Object[].class);
       query.setParameter("user", user);
       return query.getResultList();
    }
    

    返回的 List 将包含具有 4 个字段(t.id、t.summary、t.message、u.email)的数组。

    如果您觉得这很有用,请告诉我。

    :)

    【讨论】:

    • 我已经知道这种可能性,我希望得到一些不需要我输入 SQL 查询的东西。
    【解决方案2】:

    我一直在寻找的解决方案是 Spring Data JPA Projections。它们可以是具有与您要从数据库中获取的列相匹配的 getter 的接口或类。详细信息请查看Spring Framework documentation here.

    【讨论】:

      【解决方案3】:

      使用 Spring Data Projections 是一种选择,但您有时会遇到它的局限性。如果您达到了这一点,您可以查看Blaze-Persistence Entity Views

      我创建了该库以允许在 JPA 模型和自定义接口或抽象类定义模型之间轻松映射,例如 Spring Data Projections on steroids。这个想法是您按照自己喜欢的方式定义目标结构(域模型),并通过 JPQL 表达式将属性(getter)映射到实体模型。

      使用 Blaze-Persistence Entity-Views 的用例的 DTO 模型可能如下所示:

      @EntityView(TICKET.class)
      public interface TicketDto {
          @IdMapping
          Long getId();
          String getName();
          UserDto getUser();
      
          @EntityView(USER.class)
          interface UserDto {
              @IdMapping
              Long getId();
              String getEmail();
          }
      }
      

      在你的情况下甚至更简单

      @EntityView(TICKET.class)
      public interface TicketDto {
          @IdMapping
          Long getId();
          String getName();
          @Mapping("user.email")
          String getUserEmail();
      }
      

      查询是将实体视图应用于查询的问题,最简单的就是通过 id 进行查询。

      TicketDto a = entityViewManager.find(entityManager, TicketDto.class, id);

      Spring Data 集成让您可以像使用 Spring Data Projections 一样使用它:https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features

      【讨论】:

        猜你喜欢
        • 2012-03-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-11-15
        • 2021-11-12
        • 2021-12-04
        • 1970-01-01
        • 2018-09-19
        相关资源
        最近更新 更多