JPQL/JPA 查询松散关系上可为空的连接字段

问题描述 投票:0回答:0

Spring Boot 和 Hibernate 在这里。我有以下 JPA 实体:

@Entity(name = "decision_analytics")
@Table(schema = "mydb")
@Data
public class DecisionAnalytics {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    
    @Column(name = "client_name")
    private String clientName;

    @Column(name = "amount")
    private BigDecimal amount;

    // lots of other fields here, omitted for brevity
    
}

对应这张表:

CREATE TABLE mydb.analytics.decision_analytics (
    id int IDENTITY(1,1) NOT NULL,
    client_name varchar(MAX) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    amount float NULL,
  
    -- again, lots of other columns here, omitted for brevity
);

要从该表中获取该实体的记录,我有以下控制器:

@RestController
@RequestMapping("api/v1/decision-analytics")
public class DecisionController {

    @Autowired
    private DecisionAnalyticsService daService;

    @GetMapping("/{clientName}")
    public ResponseEntity<?> getDecisionAnalytics(@PathVariable("clientName") String clientName, @RequestParam Integer pageNo, @RequestParam Integer pageSize) {

        List<DecisionAnalytics> da = daService.getDecisionAnalytics(clientName, pageNo, pageSize);
        return ResponseEntity.ok(da);

    }


}

使用这些服务和存储库类/方法:

@Service
public class DecisionAnalyticsService {

    @Autowired
    private DecisionAnalyticsRepository daRepository;

    public List<DecisionAnalytics> getDecisionAnalytics(String clientName, Integer pageNo, Integer pageSize) {

        Pageable pageable = PageRequest.of(pageNo, pageSize);
        List<DecisionAnalytics> daList = daRepository.findByClientNameOrderByAmount(clientName, pageable);

        // do other stuff down here

        return daList;
    
    }

}

@Repository
public interface DecisionAnalyticsRepository extends JpaRepository<DecisionAnalytics, Long> {

    List<DecisionAnalytics> findByClientNameOrderByAmount(String clientName, Pageable pageable);
    
}

以上所有工作都非常好。now一个新实体,

DecisionMeta

@Entity
@Table(name = "decision_meta", schema = "mydb")
@Data
public class DecisionMeta {

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

  // see below -- cannot be a DecisionAnalytics instance w/ @OneToOne, etc.
    @Column(name = "decision_analytic_id")
    private Long decisionAnalyticId;
   
    @Column(name = "status")
    private String status;
  
}

对应一个新表:

CREATE TABLE mydb.decision_meta (
    id int IDENTITY(1,1) NOT NULL,
    decision_analytic_id int NULL,
    status varchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
);

问题来了:

[decision_meta].[decision_analytic_id]
是一个整数,但 not
[decision_analytics]
表的外键。哦,它应该,但它不是,也不可能是出于这个问题范围之外的(不是很好的)原因。因此,虽然
[decision_meta].[decision_analytic_id]
看起来,行为并将用作 if 它将成为
[decision_analytics]
表的外键,但没有实际的 FK 约束,我无法添加一个。非常重要的是要呼唤
[decision_meta].[decision_analytic_id]
可以,有时是
null

所以目前

DecisionAnalyticsController#fetchDecisionAnalytics(...)
端点方法:

  • 过滤掉任何
    client_name
    与通过路径参数在HTTP请求中发送的内容不匹配的记录;和
  • 它使用页码和页面大小(查询字符串参数)进一步过滤/限制返回的结果

我现在需要进一步过滤那个端点,这样它:

  • 过滤掉所有
    client_name
    与通过路径参数在HTTP请求中发送的内容不匹配的记录(同上);和
  • 它使用页码和页面大小(查询字符串参数)进一步过滤/限制返回的结果(也同上);和
  • 只拉回
    DecisionAnalytics
    id
    存在于
    [decision_meta].[decision_analytic_id]
    [decision_meta].[status]
    值为
    "ACTIVE"
  • 的记录

所以在 SQL 形式中,查询将是 something like:

SELECT *
FROM decision_analytics da
INNER JOIN decision_meta dm
ON da.id = dm.decision_analytic_id
WHERE
  da.client_name = ?
  AND
  dm.decision_analytic_id IS NOT NULL
  AND
  dm.status = 'ACTIVE'

...当然,在 Spring 层上也应用了页码/大小。

所以如果我的表中有以下记录:

[decision_analytics]
===
id | client_name | ...other columns ... | amount
1 | ACME | ...other... | 43.12
2 | Fizzbuzz | ...other... | 144.38
3 | ACME | ...other... | 9.16

[decision_meta]
===
id | decision_analytic_id | ...other columns... | status
1 | null | ...other... | NOT_ACTIVE
2 | 3 | ...other... | null
3 | 2 | ...other... | ACTIVE
4 | null | ...other... | null

然后只返回

decision_analytics
的第二行(id=2):

2 | Fizzbuzz | ...other... | 144.38

...因为该记录与

decision_meta
记录相关联并且具有
ACTIVE
状态。

我正在努力弄清楚

DecisionAnalyticsRepository#findByClientNameOrderByAmount(...)
方法需要如何更改(可能添加特定的
@Query
注释)以适应这些更改后的标准并且仍然是
Pageable
。谁能指出我正确的方向?提前致谢!

spring-boot hibernate jpa jpql
© www.soinside.com 2019 - 2024. All rights reserved.