条件 API 和实体图
Criteria API and Entity Graph
我有两个具有单向惰性关系的实体。其中之一有一个命名实体图。以下是实体(getter 和 setter 由于可读性而未列出):
@Entity
@NamedEntityGraph (
name = "Sms.fetchSims",
attributeNodes = {
@NamedAttributeNode("sim")
}
)
public class Sms {
@Id
@GeneratedValue (strategy = GenerationType.AUTO)
private Long id;
@NotNull
private Timestamp date;
@NotNull
private String sender;
@NotNull
private String content;
@NotNull
private Direction direction;
@NotNull
@ManyToOne (fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
private Sim sim;
}
@Entity
public class Sim {
@Id
@GeneratedValue (strategy = GenerationType.AUTO)
private long id;
@NotNull
private long IMSI;
private String MSISDN;
private String provider;
private Timestamp lockedDate;
}
当我使用带有此实体图的实体管理器 find() 方法获取任何短信时,我会收到一条带有 sim 卡的短信。
但我希望能够通过 sim id 找到短信。这就是为什么我为此目的创建了一个标准 api 查询。
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
EntityGraph eg = entityManager.getEntityGraph("Sms.fetchSims");
CriteriaQuery<Sms> cq = cb.createQuery(Sms.class);
Root<Sms> smses = cq.from(Sms.class);
Join<Sms, Sim> sims = smses.join(Sms_.sim);
cq.where(cb.equal(sims.get(Sim_.id), simId));
cq.orderBy(cb.desc(smses.get(Sms_.date)));
return entityManager
.createQuery(cq)
.setHint("javax.persistence.fetchgraph", eg)
.setMaxResults(1000)
.getResultList();
如您所见,我在这里使用类型化查询的 setHint 方法设置了实体图,但从未获取 sim,它的字段甚至没有在结果中列出 sql。我该怎么做才能使实体图符合标准 api?
我知道我可以对 smses.fetch(Sms_.sim) 进行类型转换以加入,但我收到丑陋的警告,而且这种方法对我来说像是一个肮脏的 hack。
我正在使用 hibernate 和 wildfly-8.2。0.Final 应用程序服务器。
是的,伙计,对不起。 hibernate中有一个bug在4.3之后修复了9.Final。
这是 4.3.9 生成的查询:
DEBUG - org.hibernate.SQL -
select
sms0_.id as id1_1_0_,
sim1_.id as id1_0_1_,
sms0_.content as content2_1_0_,
sms0_.date as date3_1_0_,
sms0_.direction as directio4_1_0_,
sms0_.sender as sender5_1_0_,
sms0_.sim_id as sim_id6_1_0_,
sim1_.IMSI as IMSI2_0_1_,
sim1_.MSISDN as MSISDN3_0_1_,
sim1_.lockedDate as lockedDa4_0_1_,
sim1_.provider as provider5_0_1_
from
Sms sms0_
inner join
Sim sim1_
on sms0_.sim_id=sim1_.id
where
sim1_.id=1
order by
sms0_.date desc limit ?
这里是 4.3.8 查询:
DEBUG - org.hibernate.SQL -
select
sms0_.id as id1_1_,
sms0_.content as content2_1_,
sms0_.date as date3_1_,
sms0_.direction as directio4_1_,
sms0_.sender as sender5_1_,
sms0_.sim_id as sim_id6_1_
from
Sms sms0_
inner join
Sim sim1_
on sms0_.sim_id=sim1_.id
where
sim1_.id=1
order by
sms0_.date desc limit ?
我有两个具有单向惰性关系的实体。其中之一有一个命名实体图。以下是实体(getter 和 setter 由于可读性而未列出):
@Entity
@NamedEntityGraph (
name = "Sms.fetchSims",
attributeNodes = {
@NamedAttributeNode("sim")
}
)
public class Sms {
@Id
@GeneratedValue (strategy = GenerationType.AUTO)
private Long id;
@NotNull
private Timestamp date;
@NotNull
private String sender;
@NotNull
private String content;
@NotNull
private Direction direction;
@NotNull
@ManyToOne (fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
private Sim sim;
}
@Entity
public class Sim {
@Id
@GeneratedValue (strategy = GenerationType.AUTO)
private long id;
@NotNull
private long IMSI;
private String MSISDN;
private String provider;
private Timestamp lockedDate;
}
当我使用带有此实体图的实体管理器 find() 方法获取任何短信时,我会收到一条带有 sim 卡的短信。 但我希望能够通过 sim id 找到短信。这就是为什么我为此目的创建了一个标准 api 查询。
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
EntityGraph eg = entityManager.getEntityGraph("Sms.fetchSims");
CriteriaQuery<Sms> cq = cb.createQuery(Sms.class);
Root<Sms> smses = cq.from(Sms.class);
Join<Sms, Sim> sims = smses.join(Sms_.sim);
cq.where(cb.equal(sims.get(Sim_.id), simId));
cq.orderBy(cb.desc(smses.get(Sms_.date)));
return entityManager
.createQuery(cq)
.setHint("javax.persistence.fetchgraph", eg)
.setMaxResults(1000)
.getResultList();
如您所见,我在这里使用类型化查询的 setHint 方法设置了实体图,但从未获取 sim,它的字段甚至没有在结果中列出 sql。我该怎么做才能使实体图符合标准 api?
我知道我可以对 smses.fetch(Sms_.sim) 进行类型转换以加入,但我收到丑陋的警告,而且这种方法对我来说像是一个肮脏的 hack。
我正在使用 hibernate 和 wildfly-8.2。0.Final 应用程序服务器。
是的,伙计,对不起。 hibernate中有一个bug在4.3之后修复了9.Final。 这是 4.3.9 生成的查询:
DEBUG - org.hibernate.SQL -
select
sms0_.id as id1_1_0_,
sim1_.id as id1_0_1_,
sms0_.content as content2_1_0_,
sms0_.date as date3_1_0_,
sms0_.direction as directio4_1_0_,
sms0_.sender as sender5_1_0_,
sms0_.sim_id as sim_id6_1_0_,
sim1_.IMSI as IMSI2_0_1_,
sim1_.MSISDN as MSISDN3_0_1_,
sim1_.lockedDate as lockedDa4_0_1_,
sim1_.provider as provider5_0_1_
from
Sms sms0_
inner join
Sim sim1_
on sms0_.sim_id=sim1_.id
where
sim1_.id=1
order by
sms0_.date desc limit ?
这里是 4.3.8 查询:
DEBUG - org.hibernate.SQL -
select
sms0_.id as id1_1_,
sms0_.content as content2_1_,
sms0_.date as date3_1_,
sms0_.direction as directio4_1_,
sms0_.sender as sender5_1_,
sms0_.sim_id as sim_id6_1_
from
Sms sms0_
inner join
Sim sim1_
on sms0_.sim_id=sim1_.id
where
sim1_.id=1
order by
sms0_.date desc limit ?