Java Hibernate/JPA:如何处理join的行为

Java Hibernate/JPA:如何处理join的行为,java,hibernate,jpa,Java,Hibernate,Jpa,我有一个表a,它有一个表B的外键。我在java类中表示如下: @Entity @Table(name = "A") public class A { @ManyToOne @JoinColumn(name = "FK_A") private B b; //Id, getters,setters etc. } 然而,A与B的连接是昂贵的,并且存在一些只需要A信息的用例。我正在为此编写命名查询,并使用第二个类,对同一个表A,只使用B的外键(以防止连接)。比如: @

我有一个表
a
,它有一个表
B
的外键。我在java类中表示如下:

@Entity
@Table(name = "A")
public class A {

    @ManyToOne
    @JoinColumn(name = "FK_A")
    private B b;

   //Id, getters,setters etc.
}
然而,A与B的连接是昂贵的,并且存在一些只需要A信息的用例。我正在为此编写命名查询,并使用第二个类,对同一个表
A
,只使用B的外键(以防止连接)。比如:

@Entity(name = "AFlat")
@Table(name = "A")
public class AFlat {

    @Column(name = "FK_A")
    private String b;

   //Id, getters,setters etc.
}

对于某些查询,是否有方法阻止
a连接B
?懒惰初始化会有帮助吗?有没有更干净的解决方案,因为我对其他10个实体也有同样的问题?

延迟获取只是对persistence提供者的一个提示,因此您永远无法确定是否获取了关系

我对Hibernate了解不多,所以我不确定Hibernate是如何处理这个问题的(但是EclipseLink正在急切地加载关系,例如)

从理论上讲,可以通过实体图定义在不同的业务案例中获取什么和不获取什么(请参见:) 但是,正如上面提到的,最终它取决于persistence提供商

如果您必须确保使用普通JDBC或在其上创建一个视图 你的实体,就像你做的那样


延迟获取只是对persistence提供者的一个提示,因此您永远无法确定关系是否被获取

我对Hibernate了解不多,所以我不确定Hibernate是如何处理这个问题的(但是EclipseLink正在急切地加载关系,例如)

从理论上讲,可以通过实体图定义在不同的业务案例中获取什么和不获取什么(请参见:) 但是,正如上面提到的,最终它取决于persistence提供商

如果您必须确保使用普通JDBC或在其上创建一个视图 你的实体,就像你做的那样


更标准的方法是仅使用实体A和B,并将关系声明为惰性:

@Entity
@Table(name = "A")
public class A {

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "FK_A")
    private B b;

   //Id, getters,setters etc.
}
惰性的不动产关系一经使用就会由Hibernate初始化。如果您需要特定用例的关系,您可以调用getter来触发初始化,或者专门为该查询指定即时抓取(这通常会提供更好的性能)。有几种方法可以做到这一点,比如使用

JOIN FETCH
而不是

JOIN 
在查询中,使用或。
您可以在中找到有关不同方法的概述。

更标准的方法是仅使用实体A和B,并将关系声明为惰性:

@Entity
@Table(name = "A")
public class A {

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "FK_A")
    private B b;

   //Id, getters,setters etc.
}
惰性的不动产关系一经使用就会由Hibernate初始化。如果您需要特定用例的关系,您可以调用getter来触发初始化,或者专门为该查询指定即时抓取(这通常会提供更好的性能)。有几种方法可以做到这一点,比如使用

JOIN FETCH
而不是

JOIN 
在查询中,使用或。
您可以在中找到有关不同方法的概述。

了解您想要的最好方法是:

  • 将关系标记为Lazy,这样A只会在显式需要时加载B
  • 在服务层中创建两个加载方法,标记为@Transactional。一个用于加载平面,另一个用于加载带有依赖项的A(本例中为B):

  • 因此,当您需要平面对象时,只需调用service.loadA();但如果需要依赖项,则必须调用service.loadAWithDependencies()


    请记住,加载依赖项(即调用getB().getSomeBeFieldDifferentFromId())仅在事务中有效。如果不这样做,您将得到一个LazyInitialization错误。

    最好的方法是:

  • 将关系标记为Lazy,这样A只会在显式需要时加载B
  • 在服务层中创建两个加载方法,标记为@Transactional。一个用于加载平面,另一个用于加载带有依赖项的A(本例中为B):

  • 因此,当您需要平面对象时,只需调用service.loadA();但如果需要依赖项,则必须调用service.loadAWithDependencies()

    请记住,加载依赖项(即调用getB().getSomeBeFieldDifferentFromId())仅在事务中有效。如果不这样做,您将得到一个LazyInitializationError