Datanucleus 创建子查询而不是连接
Datanucleus creates subquery instead of join
我有这些注释:
public class Account {
@Persistent(defaultFetchGroup = "true", dependent = "false")
@Column(name = "user_owner_id")
private User user;
}
public class User {
@Persistent(defaultFetchGroup = "true", mappedBy = "user")
@Element(column = "user_owner_id", dependent = "true")
private Set<Account> accounts;
}
启动帐户 class 时,数据库查询使用 SELECT * FROM accounts where exists (SELECT id from users where id=23)
我正在尝试给 datanucleus 一个注释,告诉它 运行 在数据库 SELECT a.* FROM accounts a JOIN users u on a.id = u.user_id where u.id = 23
上,因为这是更优化的。
那么我应该使用哪个注释来使数据核改变其查询格式?
---加法----
这是我们如何检索数据的精简版本:
PersistenceManager persistenceManager = persistenceManagerFactory.getPersistenceManager();
persistenceManager.getFetchPlan().setMaxFetchDepth(FetchPlan.FETCH_SIZE_GREEDY);
Query query = persistenceManager.newQuery("javax.jdo.query.JDOQL", null);
query.setClass(User.class);
query.setFilter("this.uuid==p1");
query.declareParameters("java.lang.String p1");
final List<E> entities = (List<E>) query.execute(uuid);
E entity = entities.iterator().next();
return persistenceManager.detachCopy(entity);
您正在执行 Query
只是为了获得一个对象,这是非常低效的。相反,你可以轻松做到
User u = pm.getObjectById(User.class, 1);
这可能总共会发布 2 SQL; 1 获取基本用户对象,1 获取连接到该用户的帐户。不会有 EXISTS 子句。
关于你实际在做什么。发出查询。查询是通用的,在大多数用例中将 return 多个对象。查询的过滤子句可能很复杂。查询被转换为 SQL 以获取基本的用户字段。它无法在一次调用中获取相关对象,因此您的日志可能会说一些关于 BULK FETCH 的内容(或类似的内容,无论 DataNucleus 怎么称呼它)。这将有一个 EXISTS
子句,其中 EXISTS
子查询将第二个查询限制为查询适用的对象)。他们这样做是为了避免 N+1 问题。通常,使用 EXISTS
最适合一般的查询情况。在您的特定情况下,有一个 INNER JOIN
会很好,但我认为目前不支持 BULK FETCH 选项。他们的代码是开源的,我知道他们过去曾要求人们在他们想要替代处理的地方贡献一些东西……所以如果你想在这种精确的情况下使用查询,你可以贡献一些东西。
我有这些注释:
public class Account {
@Persistent(defaultFetchGroup = "true", dependent = "false")
@Column(name = "user_owner_id")
private User user;
}
public class User {
@Persistent(defaultFetchGroup = "true", mappedBy = "user")
@Element(column = "user_owner_id", dependent = "true")
private Set<Account> accounts;
}
启动帐户 class 时,数据库查询使用 SELECT * FROM accounts where exists (SELECT id from users where id=23)
我正在尝试给 datanucleus 一个注释,告诉它 运行 在数据库 SELECT a.* FROM accounts a JOIN users u on a.id = u.user_id where u.id = 23
上,因为这是更优化的。
那么我应该使用哪个注释来使数据核改变其查询格式?
---加法----
这是我们如何检索数据的精简版本:
PersistenceManager persistenceManager = persistenceManagerFactory.getPersistenceManager();
persistenceManager.getFetchPlan().setMaxFetchDepth(FetchPlan.FETCH_SIZE_GREEDY);
Query query = persistenceManager.newQuery("javax.jdo.query.JDOQL", null);
query.setClass(User.class);
query.setFilter("this.uuid==p1");
query.declareParameters("java.lang.String p1");
final List<E> entities = (List<E>) query.execute(uuid);
E entity = entities.iterator().next();
return persistenceManager.detachCopy(entity);
您正在执行 Query
只是为了获得一个对象,这是非常低效的。相反,你可以轻松做到
User u = pm.getObjectById(User.class, 1);
这可能总共会发布 2 SQL; 1 获取基本用户对象,1 获取连接到该用户的帐户。不会有 EXISTS 子句。
关于你实际在做什么。发出查询。查询是通用的,在大多数用例中将 return 多个对象。查询的过滤子句可能很复杂。查询被转换为 SQL 以获取基本的用户字段。它无法在一次调用中获取相关对象,因此您的日志可能会说一些关于 BULK FETCH 的内容(或类似的内容,无论 DataNucleus 怎么称呼它)。这将有一个 EXISTS
子句,其中 EXISTS
子查询将第二个查询限制为查询适用的对象)。他们这样做是为了避免 N+1 问题。通常,使用 EXISTS
最适合一般的查询情况。在您的特定情况下,有一个 INNER JOIN
会很好,但我认为目前不支持 BULK FETCH 选项。他们的代码是开源的,我知道他们过去曾要求人们在他们想要替代处理的地方贡献一些东西……所以如果你想在这种精确的情况下使用查询,你可以贡献一些东西。