首页 > 解决方案 > 使用 JPA @Query Annotation 获取自定义实体并混合列和其他实体

问题描述

编辑:由于某种原因,Stackoverflow 未在发布时显示格式化的表格,但在预览中显示良好

我在持久性中使用 JPA 为我的所有 CRUD 操作分层。我试图找到一种方法来获得一些自定义查询来获取一个表的选定列和另一个表的实体并拥有一个新的自定义实体。

让我举个例子说明我的意思。(很抱歉这个超长的问题,因为它提到的一些地方提供了关于你在做什么以及到目前为止你已经尝试过的完整信息)。我有以下四张桌子。我不会展示所有其他表格,以免成为一篇长篇文章。

冰淇淋 | 编号 | 品牌标识 | 类型 | | -- | -------- | ---- | |1|1|锥形| |2|2|锥形| |3|1|酒吧| |4|1|酒吧| |5|1|锥形| |6|1|锥形| 特征 |id|类型 |名称 | |---|--------|------------| |1 |风味|香草 | |2 |价格 |高 | |3 |风味|巧克力|

icecream_characteristics |characteristics_id|icecream_id | |-------|-----------| |1 |1 | |3 |1 | |1 |2 | |3 |3 | |3 |4 | |1 |5 |

可用性|id|icecream_id|date_id|start_time_id|数量| |--|---------|--------|-------------|--------| |1 |1 | 1 |1 |10 | |2 |1 | 1 |2 |20 | |3 |2 | 1 |1 |10 | |4 |3 | 1 |1 |10 | |5 |4 | 1 |1 |10 | |6 |5 | 1 |1 |10 | |7 |6 | 1 |1 |10 |

start_times |id|key |value| |--|----|-----| |1 |0200|02:00| |2 |1200|12:00|

以及由此产生的预期输出一个统计信息,它具有从给定 icream 类型和brandId 风味一次开始的所有可用性

如果我必须通过查询进行解释,那么它将类似于具有以下键及其对品牌 ID 的可用性选择不同的 i.type、c.type、start_times.value、可用性从可用性加入冰淇淋 i on availability.icream_id = i.id加入 start_times on availability.start_time_id = start_times.id left join icecream_characteristics ic on i.id = ic.icream_id left join features c on c.id = ic.characteristics_id and features.type='FLAVOR' where i.brand_id = 1;

分组将是

CONE,02:00,VANILLA 可用性 |id|icream_id|date_id|start_time_id|quantity| |--|---------|--------|-------------|--------| |1 |1 | 1 |1 |10 | |6 |5 | 1 |1 |10 |

CONE,12:00,VANILLA 可用性 |id|icream_id|date_id|start_time_id|quantity| |--|---------|--------|-------------|--------| |2 |1 | 1 |2 |20 |

CONE,02:00,巧克力供应 |id|icream_id|date_id|start_time_id|quantity| |--|---------|--------|-------------|--------| |1 |1 | 1 |1 |10 |

CONE,12:00,巧克力供应 |id|icream_id|date_id|start_time_id|quantity| |--|---------|--------|-------------|--------| |1 |1 | 1 |1 |10 |

BAR,02:00,巧克力供应 |id|icream_id|date_id|start_time_id|quantity| |--|---------|--------|-------------|--------| |4 |3 | 1 |1 |10 | |5 |4 | 1 |1 |10 |

CONE,02:00 可用性|id|icream_id|date_id|start_time_id|quantity| |--|---------|--------|-------------|--------| |7 |6 | 1 |1 |10 |

正如你所看到的,这给了我一个关于品牌在什么时候可以买到哪种冰淇淋组合的统计数据。根据开始时间、风味和类型重复可用性,有些没有指定风味是查询的可能性

    @Getter
@Setter
public class IcecreamStats {
  private Type type;
  private Characteristics characteristics;
  private String startTime;
  private Set<Availability> availabilities;
}

到目前为止我所做的。我已经创建了 JPA 实体,并在需要时获取必要的实体。

@Entity
@Table(
    name = "icecream")
public class Icecream {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  protected Long id;

  @Column(name = "brand_id", nullable = false)
  private long brandId;

  //Type CONE, CUP, BAR
  @Column(nullable = false, length = 6)
  @Enumerated(EnumType.STRING)
  private Type type;

  @ManyToMany
  @JoinTable(
      name = "icecream_characteristics",
      joinColumns =
      @JoinColumn(
          name = "icecream_id",
          referencedColumnName = "id",
          foreignKey = @ForeignKey(name = "FK_ICECREAM_CHARACTERISTICS"),
          nullable = false),
      inverseJoinColumns =
      @JoinColumn(
          name = "characteristics_id",
          referencedColumnName = "id",
          foreignKey = @ForeignKey(name = "FK_CHARACTERISTICS_ICECREAM"),
          nullable = false),
      indexes = @Index(columnList = "icecream_id", name = "I_ICECREAM_CHARACTERISTICS"))
  private Set<Characteristics> characteristics = new HashSet<>();

  @Transient
  public Set<Characteristics> getFlavor() {
    return characteristics.stream()
        .filter(l -> l.getType() == CharacteristicsType.FLAVOR)
        .collect(Collectors.toSet());
  }

}

特征

@Getter
@Setter
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "type")
@Table(
    name = "characteristics",
    uniqueConstraints = {
        @UniqueConstraint(
            columnNames = {"type", "value"},
            name = "UK_CHARACTERISTICS_NAME")
    })
public class Characteristics {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  protected Long id;

  @Column(nullable = false, insertable = false, updatable = false, length = 31)
  @Enumerated(EnumType.STRING)
  private CharacteristicsType type;

  private String name;
}

可用性

@Entity
@Table(
    name = "availability")
public class Availability {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  protected Long id;

  @Column(name = "icecream_id", nullable = false)
  private long icecreamId;

  @Column(name = "start_time_id", nullable = false)
  private long startTimeId;

  @Column(name = "date_id", nullable = false)
  private long dateId;

  private int quantity;
}

开始时间

@Entity
@Table(
    name = "start_time",
    uniqueConstraints = {
        @UniqueConstraint(columnNames = "key", name = "UK_KEY"),
        @UniqueConstraint(columnNames = "value", name = "UK_VALUE")
    })
public class StartTime {

    @EqualsAndHashCode.Include
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    @Pattern(regexp = "^" + HOURS_PATTERN + MINUTES_PATTERN + "$")
    @Column(name = "time_key", nullable = false, length = 4)
    private String key;

    @Pattern(regexp = "^" + HOURS_PATTERN + ":" + MINUTES_PATTERN + "$")
    @Column(nullable = false, length = 5)
    private String value;

}

那么是否有可能通过@Query 注释和 JPA 获得如上所示的 IcecreamStats 列表。或者我应该求助于 Spring JDBC(我可以自己做,但这是我的第二个偏好)

标签: javaspring-data-jpa

解决方案


推荐阅读