在 QueryDSL 中使用相同的 q 对象时已使用对象
Object is already used when use same q-object in QueryDSL
您好,我有一个带有 QUeryDSL 3.6.0 的 Hibernate 项目,当我在我的服务中 class 只有 findAll() 方法时,一切正常。但是当我添加 findByID 时出现错误。
public class ArticleServiceImpl extends ArticleService {
QArticle article = QArticle.article;
@Override
public List<Article> findAll() {
return query.from(article).fetchAll().list(article);
}
public Article findById(@Nonnull final long id) {
return query.from(article).where(article.id.eq(id)).uniqueResult(article);
}
}
错误是:
Exception in thread "main" java.lang.IllegalStateException: article is already used
at com.mysema.query.DefaultQueryMetadata.addJoin(DefaultQueryMetadata.java:160)
at com.mysema.query.support.QueryMixin.from(QueryMixin.java:189)
at com.mysema.query.jpa.JPAQueryBase.from(JPAQueryBase.java:88)
at com.mysema.query.jpa.JPAQueryBase.from(JPAQueryBase.java:32)
at com.example.hibernate.services.ArticleServiceImpl.findById(ArticleServiceImpl.java:30)
at com.example.hibernate.core.Main.main(Main.java:42)
会发生什么?我看到查询不是安全的。但是如何在两种不同的方法中使用Q-class呢?
编辑:
protected JPQLQuery query = new JPAQuery(entityManager);
它是来自 ArticleService 的受保护变量。
每当对 JPAQuery()
.
的同一实例的 from()
子句中生成的同一 QEntity
进行可重复调用时,就会抛出此异常
这是一个例子(免责声明:这将是一个非常非常愚蠢的例子,只是为了说明问题)。
假设我们有一个名为 MyEntity
的实体,我们尝试以某种方式从数据库中获取两个 MyEntity
,第一个结果将针对给定的 [=21] =],第二个结果将是 id+1
public List<MyEntity> findMyDumbEntities(long id) {
QMyEntity qMyEntity = QMyEntity.myEntity;
JPAQuery jpaQuery = new JPAQuery(entityManager);
MyEntity myFirstEntity = jpaQuery.from(qMyEntity).where(qMyEntity.id.eq(id)).uniqueResult(qMyEntity);
MyEntity mySecondEntity = jpaQuery.from(qMyEntity).where(qMyEntity.id.eq(id+1)).uniqueResult(qMyEntity);
return Arrays.asList(myFirstEntity, mySecondEntity);
}
并且在尝试调用此方法时我们将看到以下异常:
java.lang.IllegalStateException: qMyEntity is already used
为什么?因为我们有一个 JPAQuery
的实例并且我们正在重复调用同一个实体(我们有两个 jpqQuery.from(qMyEntity)
)。为了解决这个问题,我们只需要在每次查询时获取 JPAQuery 实例,所以我们需要将代码更改为
public List<MyEntity> findMyDumbEntities(long id) {
QMyEntity qMyEntity = QMyEntity.myEntity;
MyEntity myFirstEntity = new JPAQuery(entityManager).from(qMyEntity).where(qMyEntity.id.eq(id)).uniqueResult(qMyEntity);
MyEntity mySecondEntity = new JPAQuery(entityManager).from(qMyEntity).where(qMyEntity.id.eq(id+1)).uniqueResult(qMyEntity);
return Arrays.asList(myFirstEntity, mySecondEntity);
}
所以要解决你的问题,而不是让 JPQQuery 初始化一次
protected JPQLQuery query = new JPAQuery(entityManager);
例如每次新的 JPAQuery 时你得到的变化
protected JPQLQuery jpaQuery() {
return new JPAQuery(entityManager);
}
然后在您的服务实现中
@Override
public List<Article> findAll() {
return jpaQuery().from(article).fetchAll().list(article);
}
public Article findById(@Nonnull final long id) {
return jpaQuery().from(article).where(article.id.eq(id)).uniqueResult(article);
}
您好,我有一个带有 QUeryDSL 3.6.0 的 Hibernate 项目,当我在我的服务中 class 只有 findAll() 方法时,一切正常。但是当我添加 findByID 时出现错误。
public class ArticleServiceImpl extends ArticleService {
QArticle article = QArticle.article;
@Override
public List<Article> findAll() {
return query.from(article).fetchAll().list(article);
}
public Article findById(@Nonnull final long id) {
return query.from(article).where(article.id.eq(id)).uniqueResult(article);
}
}
错误是:
Exception in thread "main" java.lang.IllegalStateException: article is already used
at com.mysema.query.DefaultQueryMetadata.addJoin(DefaultQueryMetadata.java:160)
at com.mysema.query.support.QueryMixin.from(QueryMixin.java:189)
at com.mysema.query.jpa.JPAQueryBase.from(JPAQueryBase.java:88)
at com.mysema.query.jpa.JPAQueryBase.from(JPAQueryBase.java:32)
at com.example.hibernate.services.ArticleServiceImpl.findById(ArticleServiceImpl.java:30)
at com.example.hibernate.core.Main.main(Main.java:42)
会发生什么?我看到查询不是安全的。但是如何在两种不同的方法中使用Q-class呢?
编辑:
protected JPQLQuery query = new JPAQuery(entityManager);
它是来自 ArticleService 的受保护变量。
每当对 JPAQuery()
.
from()
子句中生成的同一 QEntity
进行可重复调用时,就会抛出此异常
这是一个例子(免责声明:这将是一个非常非常愚蠢的例子,只是为了说明问题)。
假设我们有一个名为 MyEntity
的实体,我们尝试以某种方式从数据库中获取两个 MyEntity
,第一个结果将针对给定的 [=21] =],第二个结果将是 id+1
public List<MyEntity> findMyDumbEntities(long id) {
QMyEntity qMyEntity = QMyEntity.myEntity;
JPAQuery jpaQuery = new JPAQuery(entityManager);
MyEntity myFirstEntity = jpaQuery.from(qMyEntity).where(qMyEntity.id.eq(id)).uniqueResult(qMyEntity);
MyEntity mySecondEntity = jpaQuery.from(qMyEntity).where(qMyEntity.id.eq(id+1)).uniqueResult(qMyEntity);
return Arrays.asList(myFirstEntity, mySecondEntity);
}
并且在尝试调用此方法时我们将看到以下异常:
java.lang.IllegalStateException: qMyEntity is already used
为什么?因为我们有一个 JPAQuery
的实例并且我们正在重复调用同一个实体(我们有两个 jpqQuery.from(qMyEntity)
)。为了解决这个问题,我们只需要在每次查询时获取 JPAQuery 实例,所以我们需要将代码更改为
public List<MyEntity> findMyDumbEntities(long id) {
QMyEntity qMyEntity = QMyEntity.myEntity;
MyEntity myFirstEntity = new JPAQuery(entityManager).from(qMyEntity).where(qMyEntity.id.eq(id)).uniqueResult(qMyEntity);
MyEntity mySecondEntity = new JPAQuery(entityManager).from(qMyEntity).where(qMyEntity.id.eq(id+1)).uniqueResult(qMyEntity);
return Arrays.asList(myFirstEntity, mySecondEntity);
}
所以要解决你的问题,而不是让 JPQQuery 初始化一次
protected JPQLQuery query = new JPAQuery(entityManager);
例如每次新的 JPAQuery 时你得到的变化
protected JPQLQuery jpaQuery() {
return new JPAQuery(entityManager);
}
然后在您的服务实现中
@Override
public List<Article> findAll() {
return jpaQuery().from(article).fetchAll().list(article);
}
public Article findById(@Nonnull final long id) {
return jpaQuery().from(article).where(article.id.eq(id)).uniqueResult(article);
}