升级到 datanucleus-appengine 的 2.0.0 最终版本后,当通过 Query API 使用 JDOQL 查询时,提取组现在似乎被忽略了。我不确定这是库中的错误还是我做错了。
我定义了一个“用户”实体,其中包含对其他实体的多个 1:M 列表引用。我们通过 fetch 组控制这些引用的获取,例如:
@PersistenceCapable(identityType = IdentityType.APPLICATION, detachable="true")
@FetchGroups({@FetchGroup(name="bits",
members=@Persistent(name="userHistory"),
@Persistent(name="userBranding")}),
@FetchGroup(name="content", members={@Persistent(name="userContent")})})
public class User implements Serializable {
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private String username;
@Persistent
private String email;
@Persistent(mappedBy = "contentUser", defaultFetchGroup = "false")
@Element(dependent = "true")
@Order(extensions = @Extension(vendorName = "datanucleus", key = "list-ordering",value="contentKey asc"))
private List<Content> userContent;
@Persistent(mappedBy = "historyUser", defaultFetchGroup = "false")
@Element(dependent = "true")
@Order(extensions = @Extension(vendorName = "datanucleus", key = "list-ordering", value = "createdDate asc"))
private List<History> userHistory;
@Persistent(mappedBy = "brandingUser", defaultFetchGroup = "false")
@Element(dependent = "true")
private List<MediaBranding> userBranding;
...
}
有了上面的定义,我的理解是:
- 仅使用默认提取组时,不会提取任何关系。
- 如果指定了 'bits' 提取组,则应提取 userHistory 和 userBranding。
- 如果指定了“内容”获取组,则应获取用户内容。
使用 JDOQL 通过电子邮件字段获取用户时,无论指定哪些获取组,都不会获取任何关系。如果我使用 getById() 来获取用户,则会按预期应用获取组。
我已关闭 L2 缓存(在 jdoquery.xml 中设置为 NONE)。
我用来获取的测试用例如下所示(使用 2.0.0-final 版本失败,使用 1.0.10 版本通过)。
@SuppressWarnings("unchecked")
@Test
public void testAddRetrieveUserByJDOQLQueryFetchGroups() {
PersistenceManager pm;
User u = persistUserAndFriends();
pm = getPMF().getPersistenceManager();
User result = null;
try {
pm.getFetchPlan().addGroup("bits");
pm.getFetchPlan().addGroup("content");
log.info("Groups in fetch plan: " + pm.getFetchPlan().getGroups());
Query query = pm.newQuery(User.class);
query.setFilter("email == emailParam");
query.declareParameters("java.lang.String emailParam");
List<User> results = (List<User>) query.execute("hello@site.net");
assertEquals(1, results.size());
result = results.get(0);
pm.makeTransient(result, true);
} finally {
pm.close();
}
assertNotNull("User history should be fetched", result.getUserHistory());
assertNotNull("User branding should be fetched", result.getUserBranding());
assertEquals("Should be two history children", 2, result.getUserHistory().size());
assertEquals("Should be two branding children", 2, result.getUserBranding().size());
assertEquals("Should be a content child", 1, result.getUserContent().size());
}
我会以错误的方式解决这个问题吗?