当前位置: 首页 > 知识库问答 >
问题:

没有连接子句的一对多JPA查询

常睿范
2023-03-14

给定两个具有一对多关系的表(SQLServer的脚本):

CREATE TABLE address (
  id BIGINT IDENTITY (1, 1) NOT NULL,
  street VARCHAR(255),
  zip VARCHAR(32),
  city VARCHAR(255),  
  country VARCHAR(32),

  CONSTRAINT PK_address PRIMARY KEY NONCLUSTERED(id)
);
CREATE TABLE person (
  id BIGINT IDENTITY (1, 1) NOT NULL,
  address_id BIGINT NOT NULL,
  first_name VARCHAR(32),
  last_name VARCHAR(32),

  CONSTRAINT PK_person PRIMARY KEY NONCLUSTERED(id),
  CONSTRAINT FK_person_address FOREIGN KEY (address_id) REFERENCES address
); 

一个人只有一个地址,但同一地址可以链接到多个不同的人。

还有一个Spring JPA存储库,其中包含一个显式查询:

@Repository
public interface PersonJpaRepository extends JpaRepository<Person, Long> {

    List<Person> findByAddressId(Long addressId);
}

使用Hibernate作为JPA提供程序,会为该查找方法生成类似的SQL:

select person0_.id, person0_.first_name, person0_.last_name
from person person0_ 
left outer join address address1_ on person0_.address_id=address1_.id 
where person0_.address_id=?

因为我对地址表中的任何数据都不感兴趣,而且我已经知道address_id了,所以似乎没有真正需要连接:

select person0_.id, person0_.first_name, person0_.last_name
from person person0_ 
where person0_.address_id=?

这个查询给出了相同的结果。

我是否可以让JPA/Hibernate在没有连接的情况下生成SQL,而无需通过@Query显式定义查询?

共有2个答案

庞意智
2023-03-14

是的,你可以!我可以非常有帮助地消除连接,因为它不会引入第二个表名。例如,这可以使ORDER变得更加容易,因为不需要为表命名。

让它更具体。可以执行HQL-SELCT并限制多通关系,而无需在生成的SQL中加入任何连接:

而不是使用加入

session.createQuery("FROM Person person WHERE person.adress.id = 42")

我们使用可以使用adress_id

session.createQuery("FROM Person person WHERE person.adressId = 42")

如果您指定一个额外的adressId字段,该字段仅用作Hibernate的映射信息,则此选项有效:

@Entity
@Access(AccessType.FIELD)
public class Person{
    @Id
    String id;

    @JoinColumn(name = "adress_id") 
    @ManyToOne(fetch = FetchType.LAZY)
    @Nullable
    public Adress adress;


    @Column(name = "adress_id", insertable = false, updatable = false)
    private String adressId;

 // [... street, zip, city, country]
}


@Entity
@Access(FIELD)
public class Adress{
    @Id
    String id;

   // [... firstName, lastName]
}

AccessType。不需要字段(但我们可以在示例中留下getter/setter)。FetchType。LAZY@Nullable也是可选的,但在使用它有意义时要明确。我们能够加载具有特定地址(我们知道地址id)的个人实体。但是我们不需要连接,因为WHERE子句和初始获取都不需要连接(地址可以通过延迟获取)。

钮鸿煊
2023-03-14

您无法更改Hibernate的行为,但不必关心加入。

数据库无论如何都会优化查询,因为没有针对表地址的保护。

因此,从数据库的角度来看,两个查询都是相同的。

 类似资料:
  • 问题内容: 假设您具有以下一对多关系:。现在,您要选择所有学生名为“ John”且其科学工作称为“Black Holes”的学校。 我这样做如下,但是由于某种原因,它使我无法接受所有可能的学校。 更新资料 找到此答案后,我尝试了以下操作,但结果相同(它使我返回所有学校而不是所有学校): 问题答案: public static Specification spec() { return (root,

  • 我想管理与映射到联接表的实体的关系。因此我有3个实体类:、、。具有注释的和成员。 及其嵌入的密钥: 当我需要带有给定标记的帖子时,我希望使用以下查询: 整件事都在这里: https://github.com/riskop/jpa_hibernate_spring_boot_many_to_many_managed_on_join_table_problem

  • 问题内容: 我想在以下(简化的)数据库中应用JPA: 因此,一个节点可以具有多个权限,并且一个权限可以被多个节点引用。 我希望我的班级看起来像这样: 但是注释“ @ManyToMany”似乎仅可用于“ @JoinTable”,在这种情况下,它不可用(据我所知)。有人知道修改数据库之外是否还有其他方法吗? 问题答案: JPA不允许这样做,因为它需要外键来引用完整的主键以用于标识目的,并且它可能不适用

  • 问题内容: 我们正在开发一个使用EJB连接到数据库的Web应用程序。 在我们的数据库模型中,我们有一个移动设备表,另一个有功能表,最后一个有手机模型映射功能值的表。模型(id_model,…)功能(id_feature,…)model_features(id_model,id_feature,值) 我们想要执行一个查询,以按匹配特征的数量对模型进行排序。就是说,我们传递了一个要匹配的功能列表(即从

  • 我有一个类Api,它包含一个数据列表:

  • 我有2个具有多对多关系的实体User和AcCountBase。我需要从连接表中选择所有具有选定用户ID的AcCountBase对象。我尝试了一些连接查询,但不起作用。