为什么Spring Data Jpa在简单选择上加入?

时间:2016-01-22 18:15:40

标签: hibernate spring-data-jpa

我有@ManyToOne链接的实体。当我请求findByCity时,spring数据会“左外连接”。但是,如果我使用标准eq在hibernate上执行它 - 它会获得正常的请求,例如“select .... where city_id = ...”。 如何在没有@Query的情况下避免加入?

1 个答案:

答案 0 :(得分:0)

默认情况下,使用@ManyToOne关系的选择始终使用每个定义的联接。在Hibernate 5 Criteria中,您需要对其进行显式定义并为每个联接创建别名:
因此,不用写作(人->地址):

session.createCriteria(Person.class).
  .add(Restrictions.eq("adress.serial", "42"));

我们需要写

session.createCriteria(Person.class).
  .createAlias("adress", "adr");
  .add(Restrictions.eq("adr.serial", "42"));

createAlias似乎不是完美的方法名称,因为这样做是:

加入关联,为加入的关联分配别名。

但是还有一种解决方法,如果您想简单地选择一个受 ID 限制且不受约束的 ManyToOne 关系的实体, (在 HQL 中也不在结果 SQL 中)。

我们可以使用adress_id列代替上一个示例中的联接:

session.createCriteria(Person.class).
  .add(Restrictions.eq("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;
}


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

不需要AccessType.FIELD(但是我们可以在示例中保留getter / setter)。 FetchType.LAZY@Nullable也是可选的,但请在合理使用时明确说明。我们能够加载具有特定Person的{​​{1}}个实体(我们知道地址ID)。但是我们不需要连接,因为在WHERE子句和初始获取(地址可以被延迟获取)中都不需要。