こんにちは私は、Hibernate/JPAとSpring Dataを使用するアプリケーションを持っています。 1対多関係の親子関係を持つ2つのエンティティがあります。 彼らは以下の通りです:子供をフェッチするための休止状態の親ループ
これは親である:
@Entity
@Table(name = "dataset")
public class Dataset {
@Id
@GenericGenerator(name = "generator", strategy = "increment")
@GeneratedValue(generator = "generator")
private Long id;
@Column(name = "name", nullable = false)
private String name;
@Column(name = "guid", nullable = false)
private String guid;
@Column(name = "size", nullable = false)
private Long size;
@Column(name = "create_time", nullable = false)
private Date createTime;
@OneToOne(optional = false)
@JoinColumn(name = "created_by")
private User createdBy;
@Column(name = "active", nullable = false)
private boolean active;
@Column(name = "orig_source", nullable = false)
private String origSource;
@Column(name = "orig_source_type", nullable = false)
private String origSourceType;
@Column(name = "orig_source_org", nullable = false)
private String origSourceOrg;
@Column(name = "uri", nullable = false)
private String uri;
@Column(name = "mimetype", nullable = false)
private String mimetype;
@Column(name = "registration_state", nullable = false)
private int registrationState;
@OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.ALL})
@JoinColumn(name = "dataset_id")
@JsonManagedReference
private List<DatasetFile> datasetFiles;
...
}
、これが子供である:
@Entity
@Table(name = "dataset_file")
public class DatasetFile implements Serializable {
@Id
@GenericGenerator(name = "generator", strategy = "increment")
@GeneratedValue(generator = "generator")
private Long id;
@Column(name = "filename", nullable = false)
private String filename;
@Column(name = "filesize", nullable = false)
private Long filesize;
@Column(name = "location", nullable = false)
private String uri;
@Column(name = "alias", nullable = false)
private String alias;
@Column(name = "guid", nullable = false)
private String guid;
@Column(name = "mimetype", nullable = false)
private String mimetype;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "dataset_id")
@JsonBackReference
private Dataset dataset;
次は私が作成した春のデータリポジトリです:
public interface DatasetRepo extends JpaRepository<Dataset, Long> {
@Query("SELECT CASE WHEN COUNT(p) > 0 THEN 'true' ELSE 'false' END FROM Dataset p WHERE p.uri = ?1")
public Boolean existsByURI(String location);
}
私がリポジトリのfindAll()
メソッドを呼び出すと、そのHibern最初にすべての親をフェッチし、次に各親をループし、子をフェッチするために親ごとにクエリを実行します.Hibernateがただ1つのクエリを実行して1つの中にすべての子をフェッチすることを知らないとは想像できませんそれに応じてレコードセットを展開し、アンマーシャリングします。以下
(私自身のコメントで注釈が付け)ログからの抜粋
//this is where it fetches the data set
Hibernate: select dataset0_.id as id1_1_, dataset0_.active as active2_1_, dataset0_.create_time as create_t3_1_, dataset0_.created_by as created13_1_, dataset0_.guid as guid4_1_, dataset0_.mimetype as mimetype5_1_, dataset0_.name as name6_1_, dataset0_.orig_source as orig_sou7_1_, dataset0_.orig_source_org as orig_sou8_1_, dataset0_.orig_source_type as orig_sou9_1_, dataset0_.registration_state as registr10_1_, dataset0_.size as size11_1_, dataset0_.uri as uri12_1_ from dataset dataset0_
//this is where it fetches the create user
Hibernate: select user0_.id as id1_5_1_, user0_.active as active2_5_1_, user0_.fn as fn3_5_1_, user0_.home_div as home_div4_5_1_, user0_.ln as ln5_5_1_, user0_.mi as mi6_5_1_, user0_.password as password7_5_1_, user0_.username as username8_5_1_, authoritie1_.id_user as id_user1_5_3_, authority2_.id as id_autho2_6_3_, authority2_.id as id1_0_0_, authority2_.name as name2_0_0_ from user user0_ left outer join users_authority authoritie1_ on user0_.id=authoritie1_.id_user left outer join authority authority2_ on authoritie1_.id_authority=authority2_.id where user0_.id=?
//this is where it fetch dataset files
Hibernate: select datasetfil0_.dataset_id as dataset_8_1_1_, datasetfil0_.id as id1_2_1_, datasetfil0_.id as id1_2_0_, datasetfil0_.alias as alias2_2_0_, datasetfil0_.dataset_id as dataset_8_2_0_, datasetfil0_.filename as filename3_2_0_, datasetfil0_.filesize as filesize4_2_0_, datasetfil0_.guid as guid5_2_0_, datasetfil0_.mimetype as mimetype6_2_0_, datasetfil0_.location as location7_2_0_ from dataset_file datasetfil0_ where datasetfil0_.dataset_id=?
Hibernate: select datasetfil0_.dataset_id as dataset_8_1_1_, datasetfil0_.id as id1_2_1_, datasetfil0_.id as id1_2_0_, datasetfil0_.alias as alias2_2_0_, datasetfil0_.dataset_id as dataset_8_2_0_, datasetfil0_.filename as filename3_2_0_, datasetfil0_.filesize as filesize4_2_0_, datasetfil0_.guid as guid5_2_0_, datasetfil0_.mimetype as mimetype6_2_0_, datasetfil0_.location as location7_2_0_ from dataset_file datasetfil0_ where datasetfil0_.dataset_id=?
Hibernate: select datasetfil0_.dataset_id as dataset_8_1_1_, datasetfil0_.id as id1_2_1_, datasetfil0_.id as id1_2_0_, datasetfil0_.alias as alias2_2_0_, datasetfil0_.dataset_id as dataset_8_2_0_, datasetfil0_.filename as filename3_2_0_, datasetfil0_.filesize as filesize4_2_0_, datasetfil0_.guid as guid5_2_0_, datasetfil0_.mimetype as mimetype6_2_0_, datasetfil0_.location as location7_2_0_ from dataset_file datasetfil0_ where datasetfil0_.dataset_id=?
Hibernate: select datasetfil0_.dataset_id as dataset_8_1_1_, datasetfil0_.id as id1_2_1_, datasetfil0_.id as id1_2_0_, datasetfil0_.alias as alias2_2_0_, datasetfil0_.dataset_id as dataset_8_2_0_, datasetfil0_.filename as filename3_2_0_, datasetfil0_.filesize as filesize4_2_0_, datasetfil0_.guid as guid5_2_0_, datasetfil0_.mimetype as mimetype6_2_0_, datasetfil0_.location as location7_2_0_ from dataset_file datasetfil0_ where datasetfil0_.dataset_id=?
Hibernate: select datasetfil0_.dataset_id as dataset_8_1_1_, datasetfil0_.id as id1_2_1_, datasetfil0_.id as id1_2_0_, datasetfil0_.alias as alias2_2_0_, datasetfil0_.dataset_id as dataset_8_2_0_, datasetfil0_.filename as filename3_2_0_, datasetfil0_.filesize as filesize4_2_0_, datasetfil0_.guid as guid5_2_0_, datasetfil0_.mimetype as mimetype6_2_0_, datasetfil0_.location as location7_2_0_ from dataset_file datasetfil0_ where datasetfil0_.dataset_id=?
...
は、これらのクエリについて、よりスマートに休止助けるためにどのように任意のアイデアですか? (私はデータセット、ユーザー、およびdataset_fileすべて1つのクエリでに参加したい生SQLでこれを書くとしたら、それはより速く何倍だ。
は、あなたがそうあなたの積極的なロードをあなたのdatasetFiles
を使用しているあなたに
しかし、データセットを読み込むと、すべてのdataset_filesがロードされますが、loadin gデータセットを通るループとしてのdataset_filesは、私にとって非常に素朴なようです。この作業を行うための単一の結合は、より高速です。例:a。*、b。*をデータセットから選択するa.id = b.dataset_idの内部結合dataset_file b; –
なぜあなたはdataset_filesを一度に読み込みたいのですか? LAZY戦略を実行することで、コレクションに先にデータをロードしてから収集したエンティティをクライアントに戻す必要がある場合に、永続性プロバイダにヒントを与えていることを忘れないでください。 –