您好我有一个使用Hibernate / JPA和Spring Data的应用程序。 我有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;
以下是我创建的Spring Data存储库:
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()
方法时,我注意到Hibernate首先获取所有父节点,然后遍历每个父节点并为每个父节点运行查询以获取子节点,我可以& #39;想象一下Hibernate不知道只运行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=?
...
知道如何帮助Hibernate更智能地解决这些问题吗? (如果我在原始SQL中写这个,我在一个查询中加入数据集,用户和dataset_file,它的速度要快很多倍。
谢谢
答案 0 :(得分:0)
您正在使用急切加载datasetFiles
,因此您的持久性提供商会急切地抓取您的datasetFiles
,因为您将其设置为EAGER
获取策略。默认情况下,JPA中@OneToMany
的抓取策略为LAZY
。只是不设置fetch
策略,持久性提供程序将为您加载它。