【问题标题】:How to search using jpa specifications on a join of 2 tables?如何在 2 个表的连接上使用 jpa 规范进行搜索?
【发布时间】:2022-01-07 20:49:49
【问题描述】:

我有 2 个表,即 table1 和 table2。 我想要一个 JPA 规范来搜索两个表的连接,即 table1 上的一些字段和 table2 的一些字段。 这 2 个表如下所示:

@Entity
@Table(name = "table1")
public class Table1 {
    @Id
    @Column(name = "SID1", nullable = false)
    private Long sid1;

    @Column(name = "field1")
    private Long field1;

    @Column(name = "field2")
    private String field2;

    @Column(name = "SID2", nullable = false)
    private Long sid2;

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "SID2")
    private Table2 t2;
}

@Entity
@Table(name = "table2")
public class Table2 {
    @Id
    @Column(name = "SID2", nullable = false)
    private Long sid2;

    @Column(name = "field01")
    private Long field01;

    @Column(name = "field02")
    private String field02;
}

我想构建一个规范及其 SpecificationBuilde,但不知道如何从 root.get() 引用表 2 的字段。例如

public static Specification<Table1> hasField01(final String field) {
        return (root, query, cb) -> cb.equal(root.get("t2.field01"), field); //is this correct??
    }

我探索了分别对每个表进行 2 次查询的想法,但这变得很麻烦。 我们将不胜感激。

【问题讨论】:

  • 您要进行全外连接吗?否则,表应由外键链接,您需要加入该键。例如,如果 Table1 是 Bookshelf 而 Table2 是 Book,那么 Bookshelf 应该有一个 List 或者 Book 应该有一个 BookshelfId 作为外键。你想实现哪一个?
  • 你能把你想生成的SQL贴出来,然后我们可以把它翻译成JPQL。
  • 嗨@roccobaroccoSC 我已将问题编辑为更直接。如果需要任何解释,请告诉我。
  • Criteria api 就像 JPQL,但每个 '.'是一个单独的 get 调用。因此,假设 root 在 table1 上,而不是 root.get("t2.field01"),它将是 root.get("t2").get("field01") 为您提供在其他表达式中使用的路径,例如相等。
  • 谢谢,这可能行得通。将在今天实施并通知您。

标签: mysql spring-boot jpa join specifications


【解决方案1】:

如果您的目标是在加入 Table1 时搜索 Table2.field01,您可以使用以下 JPQL 查询:

SELECT 
    t1
FROM 
    Table1 t1 
    LEFT JOIN t1.t2 t2
WHERE 
    t2.field01 = :field

这将选择 Table1 但只有与 Table2 连接的记录的 field01 等于指定的参数。 ":field" 必须作为参数从外部提供给查询,如下所示:

public class Table1DAO {
    // ...
    public List<Table1> findByField01(Long field01)
    {
        try {
            List<Table1> result = entityManager
                .createQuery("SELECT t1 FROM  Table1 t1  LEFT JOIN t1.t2 t2 WHERE t2.field01 = :field", Table1.class)
                .setParameter("field", field01)
                .getResultList();

            return result;
        }
        catch (NoResultException e)
        {
            return null;
        }
        catch (Exception e)
        {
            throw e;
        }
    }
}

您可以选择两个表中的所有字段或字段的任意组合,但您的查询无法将此类结果转换为 Table1,您需要从返回的数组中读取它们:

List<Map<String, Object>> results = (List<Map<String, Object>>) query.getResultList();

【讨论】:

  • 由于某些原因我不能使用 JPQL,我必须使用规范。这是因为那里有很多字段,其中任何数量的字段都可以有值或没有值。虽然其中一些值在表 1 中,而其他值在表 2 中,因此是问题所在。
  • 规范是指JPA的标准api吗?
猜你喜欢
  • 2018-04-08
  • 1970-01-01
  • 2019-08-26
  • 2023-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-22
  • 1970-01-01
相关资源
最近更新 更多