即使fetchtype是懒惰的,JPA也会加载太多数据

时间:2018-06-08 13:54:55

标签: java hibernate jpa

我有一个应用程序可以加载与下水道网络相关的数据。以下是涉及的实体样本。首先,我定义了一个Network实体:

@Entity
@Table(name = "network")
public class Network extends Serializable {
  @Id
  @generatedValue(strategy=GenerationType.AUTO)
  private Long id;

  ...
  @OneToMany(mappedBy = "network")
  private List<Conduit> conduits;

  @OneToMany(mappedBy = "network")
  private List<ConduitVolumeter> conduitVolumeters;

  ...
}

涉及的第二个实体是Conduit,它代表网络中的管道。

@Entity
@Table(name = "conduit")
@NamedQuery(name = "Conduit.findAll", query = "SELECT c FROM Conduit c")
public class Conduit extends Serializable {
  @Id
  @generatedValue(strategy=GenerationType.AUTO)
  private Long id;

  ...
  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "id_network", nullable = false)
  private Network network;

  @OneToOne(mappedBy = "conduit", fetch = FetchType.LAZY)
  private ConduitVolumeter conduitVolumeter;

  ...
}

接下来,我定义ConduitVolumeter。这表示用于测量导管中的体积的测量装置。由于可以在其他网络项中测量卷,因此与数据库中的Volumeter表关联的抽象类volumeter

@Entity(name = "ConduitVolumeter")
@DiscriminatorValue("1")
public class ConduitVolumeter extends Volumeter {

  @OneToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "id_nme")
  private Conduit conduit;

  ...
}

@Entity
@Table(name = "volumeter")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "nme_type", discriminatorType = DiscriminatorType.INTEGER)
public abstract class Volumeter extends Serializable {
  @Id
  @generatedValue(strategy=GenerationType.AUTO)
  private Long id;

  ...
  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "id_network", nullable = false)
  private Network network;

  ...
}

问题在于,当我尝试加载与网络相关的所有管道时,Hibernate根据其日志系统地尝试一次一个地加载与每个加载管道相关联的每个卷管。

Hibernate: 
    select
        conduit0_.id as id_1_7_,
        conduit0_.name as name23_7_,
        conduit0_.id_network as id_netw39_7_,
    from
        conduit conduit0_ cross 
    join
        network network1_ 
    where
        conduit0_.id_network=?

...

Hibernate: 
    select
        conduitvol0_.id as id2_116_0_,
        conduitvol0_.name as name10_116_0_,
        conduitvol0_.id_network as id_netw15_116_0_,
        conduitvol0_.id_nme as id_nme17_116_0_ 
    from
        volumeter conduitvol0_ 
    where
        conduitvol0_.id_nme=? 
        and conduitvol0_.nme_type=1

我的问题:为什么Hibernate会尝试加载volumeter数据?每个@ManyToOne@OneToOne注释都设置为FetchType.LAZY。我错过了什么?

顺便说一下,我被要求将JPA与遗留数据库一起使用。数据库模型是问题吗?有没有办法在没有音量管的情况下加载导管?

问候。

弗朗索瓦

1 个答案:

答案 0 :(得分:1)

FetchType只是一个提示。这取决于你如何查询数据,如果你使用spring-data-jpa存储库方法,如findOne或findBy方法(派生查询),那么Lazy应该可以工作,但如果你在存储库方法上使用JPA存储库和@Query并写你的查询然后懒惰可能不起作用。