【问题标题】:Implementing complex MAX function in Spring Boot/JPA query language在 Spring Boot/JPA 查询语言中实现复杂的 MAX 函数
【发布时间】:2020-07-21 20:21:48
【问题描述】:

Spring Boot 在此处使用 JPA/Hibernate 和 CrudRepository impls 来管理我的数据库表的持久性。

我有以下 MySQL 表:

CREATE TABLE IF NOT EXISTS price_scarcity_configs (
    price_scarcity_config_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
    price_scarcity_config_ref_id VARCHAR(36) NOT NULL,
    price_scarcity_config_version BIGINT NOT NULL,
    price_scarcity_config_updated_on DATETIME NOT NULL,
    price_scarcity_config_fizz INTEGER NOT NULL,

    CONSTRAINT pk_price_scarcity_configs PRIMARY KEY (price_scarcity_config_id),

    CONSTRAINT uc_price_scarcity_configs_ref_id_and_version UNIQUE (price_scarcity_config_ref_id, price_scarcity_config_version)
);

这些记录将被版本化,并且“相同”记录的不同版本都将共享相同的price_scarcity_config_ref_id。因此,2+ 条记录可以具有相同的price_scarcity_config_ref_id,但会有两个截然不同的不同版本。

我还使用以下 JPA/Hibernate 实体对其进行建模:

// Uses Lombok annotations to generate getters/setters, etc.

@MappedSuperclass
@Data
@EqualsAndHashCode(callSuper=false)
public abstract class BaseEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String refId;

}

@Entity
@Table(name = "price_scarcity_configs")
@AttributeOverrides({
        @AttributeOverride(name = "id", column = @Column(name = "price_scarcity_config_id")),
        @AttributeOverride(name = "refId", column = @Column(name = "price_scarcity_config_ref_id"))
})
@Data
@EqualsAndHashCode(callSuper=false)
public class PriceScarcityConfiguration extends BaseEntity {

    @Column(name = "price_scarcity_config_version")
    private Long version;

    @Column(name = "price_scarcity_config_updated_on")
    private Date updatedOn;

    @Column(name = "price_scarcity_config_fizz")
    private Integer fizz;

}

我现在正在尝试编写PriceScarcityConfigurationRepository 并且需要一个相当复杂的查询。给定refId,我需要找到匹配该 ref id 并且具有最高/最大版本号的记录。执行此操作的原始 SQL 查询是:

select
  *
from
  price_scarcity_configs pcs
inner join
  (
    SELECT
      price_scarcity_config_ref_id,
      MAX(price_scarcity_config_version) as max_ver
    FROM
      price_scarcity_configs
    group by
      price_scarcity_config_ref_id
  ) t
on
  t.price_scarcity_config_ref_id = pcs.price_scarcity_config_ref_id 
  and
  t.max_ver = pcs.price_scarcity_config_version;

鉴于我的存储库并使用 JPA/Hibernate 的内置查询语言/annos,我该如何实现此查询?

public interface PriceScarcityConfigurationRepository extends CrudRepository<PriceScarcityConfiguration,Long> {

    @Query("FROM PriceScarcityConfiguration WHERE ??? HOW TO IMPLEMENT THE ABOVE QUERY HERE ???")
    PriceSheetConfiguration fetchLatestVersionByRefId(@Param("refId") String refId);

}

【问题讨论】:

    标签: java mysql hibernate jpa spring-boot-jpa


    【解决方案1】:

    您可以改用以下查询并使用setMaxResults(1)

    FROM PriceScarcityConfiguration p WHERE p.refId = :refId ORDER BY p.version DESC
    

    或者简单地使用 Spring Data 表示法

    List<PriceSheetConfiguration> findFirstByRefIdOrderByVersionDesc(String refId);
    

    【讨论】:

    • 谢谢@Christian (+1) -- 我会在哪里setMaxResults(1)(对于第一个解决方案)?
    • 当你有一个实体管理器时,你使用entityManager.createQuery("FROM PriceScarcityConfiguration p WHERE p.refId = :refId ORDER BY p.version DESC").setParameter("refId", refId).setMaxResults(1).getResultList()
    • PriceScarcityConfigurationRepository接口中,我可以定义一个接口方法并将"FROM PriceScarcityConfiguration..."字符串放在@Query anno中吗?
    • 我不这么认为,您必须注入实体管理器并手动执行查询。弹簧数据概念不适合您吗? List&lt;PriceSheetConfiguration&gt; findFirstByRefIdOrderByVersionDesc(String refId);
    猜你喜欢
    • 1970-01-01
    • 2022-10-14
    • 1970-01-01
    • 2018-09-27
    • 2019-10-05
    • 2019-07-01
    • 2021-09-15
    • 1970-01-01
    • 2021-10-13
    相关资源
    最近更新 更多