Kaw*_*awu 16 java hibernate jpa lazy-loading relationships
我有以下实体(仅显示相关映射):
@Entity
@Table(name = "PQs")
public class PQ implements Serializable
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column
private Integer id;
@Column
private String name;
@ManyToOne(fetch = FetchType.LAZY) // lazy XToOne
@JoinColumn(name = "user_id", referencedColumnName = "person_id")
private User user;
@OneToOne(mappedBy = "pq", fetch = FetchType.LAZY) // lazy XToOne
private Group group;
@OneToOne(mappedBy = "pq", fetch = FetchType.LAZY) // lazy XToOne
private Tendering tendering;
...
}
Run Code Online (Sandbox Code Playgroud)
请注意上面的注释:@XToOne与其他实体有三种关系:
用户(具有简单ID作为PK的SecurityIdentity子类,由PQ表示所有者):
@Entity
@Table(name = "Users")
@DiscriminatorValue(value = "user")
public class User extends SecurityIdentity
{
@Column
private String name;
@OneToMany(mappedBy = "user")
private Set<PQ> pqs = new HashSet<PQ>();
...
}
Run Code Online (Sandbox Code Playgroud)
组(也是具有简单ID作为PK的SecurityIdentity子类,引用PQ来表示可以与该PQ交互的一组用户):
@Entity
@Table(name = "Groups")
@DiscriminatorValue(value = "group")
public class Group extends SecurityIdentity
{
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "pq_id", referencedColumnName = "id")
private PQ pq;
...
}
Run Code Online (Sandbox Code Playgroud)
招标:
@Entity
@Table(name = "Tenderings")
public class Tendering implements Serializable
{
@Id
@Column(name = "pq_id", insertable = false, updatable = false)
private Integer pqId;
@Column(name = "external_code")
private String externalCode;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "pq_id", referencedColumnName = "id")
private PQ pq;
...
}
Run Code Online (Sandbox Code Playgroud)
不要对共享ID的组和用户感到困惑,只需将它们视为简单ID即可.招标只是一个单独的文档对象(一对一).
正如您所看到@XToOne的,PQ实体上有三种关系,如果没有设置提取类型,则会急切加载(JPA默认值).所以为了防止这种情况,我将所有@XToOne关系标记为FetchType.LAZY.
现在使用时
em.find(PQ.class, someExistingId);
我得到了Hibernate输出:
23:53:55,815 INFO [stdout] Hibernate: select pq0_.id as id291_0_, pq0_.description as descript2_291_0_, pq0_.name as name291_0_, pq0_.submission_date as submission4_291_0_, pq0_.user_id as user5_291_0_ from PQs pq0_ where pq0_.id=?
23:53:55,818 INFO [stdout] Hibernate: select user0_.id as id280_0_, user0_1_.identity_type_id as identity2_280_0_, user0_.is_enabled as is1_297_0_, user0_.name as name297_0_, user0_.password as password297_0_, user0_.person_id as person5_297_0_ from Users user0_ inner join SecurityIdentities user0_1_ on user0_.id=user0_1_.id where user0_.person_id=?
23:53:55,821 INFO [stdout] Hibernate: select group0_.id as id280_0_, group0_1_.identity_type_id as identity2_280_0_, group0_.pq_id as pq2_281_0_ from Groups group0_ inner join SecurityIdentities group0_1_ on group0_.id=group0_1_.id where group0_.pq_id=?
23:53:55,823 INFO [stdout] Hibernate: select tendering0_.pq_id as pq1_296_0_, tendering0_.binary_file as binary2_296_0_, tendering0_.customer_id as customer6_296_0_, tendering0_.description as descript3_296_0_, tendering0_.external_code as external4_296_0_, tendering0_.title as title296_0_ from Tenderings tendering0_ where tendering0_.pq_id=?
Run Code Online (Sandbox Code Playgroud)
另外三个SELECT来自@XToOne关系(如网上许多地方所述).我看到的来源主要是这样的:
如前所述,不应该提取这种@ManyToOne关系User user:
@ManyToOne(fetch=FetchType.LAZY)应该工作得很好.
...这里的关系从PQ到用户,但它是牵强,因为你可以在看到select user0_.id as id280_0_, ...声明...
对于其他两个Group group和Tendering tendering两个@OneToOne 反向映射,外键引用PQ表的PK(ID),从而在PQ实体中产生相同的映射.
请注意,所有三个关系都不是可选的:PQ始终具有所有者(用户),并且PQ始终由招标和组实体引用.我刚才没有在上面的JPA中建模......
因此,当添加optional = false到PQ实体的三个关系时:
@Entity
@Table(name = "PQs")
public class PQ implements Serializable
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column
private Integer id;
@Column
private String name;
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "user_id", referencedColumnName = "person_id")
private User user;
@OneToOne(mappedBy = "pq", fetch = FetchType.LAZY, optional = false)
private Group group;
@OneToOne(mappedBy = "pq", fetch = FetchType.LAZY, optional = false)
private Tendering tendering;
...
}
Run Code Online (Sandbox Code Playgroud)
...我得到以下Hibernate输出:
00:47:34,397 INFO [stdout] Hibernate: select pq0_.id as id361_0_, pq0_.description as descript2_361_0_, pq0_.name as name361_0_, pq0_.submission_date as submission4_361_0_, pq0_.user_id as user5_361_0_ from PQs pq0_ where pq0_.id=?
00:47:34,410 INFO [stdout] Hibernate: select user0_.id as id350_0_, user0_1_.identity_type_id as identity2_350_0_, user0_.is_enabled as is1_367_0_, user0_.name as name367_0_, user0_.password as password367_0_, user0_.person_id as person5_367_0_ from Users user0_ inner join SecurityIdentities user0_1_ on user0_.id=user0_1_.id where user0_.person_id=?
00:47:34,413 INFO [stdout] Hibernate: select group0_.id as id350_0_, group0_1_.identity_type_id as identity2_350_0_, group0_.pq_id as pq2_351_0_ from Groups group0_ inner join SecurityIdentities group0_1_ on group0_.id=group0_1_.id where group0_.pq_id=?
Run Code Online (Sandbox Code Playgroud)
请注意,我只是optional = false在PQ实体上玩,因为这是我使用的那个em.find(...).(如果这还不够,请赐教.)
我现在的问题是双重的:
@ManyToOne对该User实体的热切期望(鉴于据说这是懒惰的工作,请参阅使一个OneToOne关系变得懒惰)?OneToOne关系Tendering不被提取?是因为Tendering实体引用PQ的PK列作为PK本身(@Idin Tendering),Group实体没有(与PQ的PK有规律关系)?怎么了?如何使这些非可选关系变得懒惰?(没有代码检测或其他黑客,只是简单的注释......)
我知道LAZY的事情只是提示JPA提供者做一些关于延迟加载的事情,但是在这种情况下,好像其他东西是错误的(因为它的一部分是有效的).
PS:我正在使用Hibernate 4.0 BETA,JBoss 7.0.0.Final附带的版本以及JPA注释(以上都是JPA 1.0兼容).
| 归档时间: |
|
| 查看次数: |
21414 次 |
| 最近记录: |