1

假设我有 2 个 JPA 类,它们在数据存储区(Google 应用程序引擎)中为 2 个实体建模,如下所示:

@Entity
public class Clazz {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Key classKey;

@Basic
private String classId;

@Basic
private String className;

@ManyToOne
private Subject subject;
    }

@Entity
public class Subject {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Key subjectKey;

@Basic
private String subjectId;

@Basic
private String subjectName;

@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "subject")
private Set<Clazz> classes = new HashSet<Clazz>();
}

那么,如何使用 JPA 标准获取具有 classId 和 subjectId 等于给定值的 Clazz 对象。我使用了这段代码,但得到了这样的异常:

em = EMF.get().createEntityManager();
        CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
        CriteriaQuery<Clazz> criteriaQuery = criteriaBuilder.createQuery(Clazz.class);
        Root<Clazz> root = criteriaQuery.from(Clazz.class);
        List<Predicate> predicates = new ArrayList<Predicate>();

        if (searchObj.getClassId() != null && searchObj.getClassId().length() > 0) {
            Expression<String> classIdExpression = root.get("classId");
            predicates.add(criteriaBuilder.equal(classIdExpression, searchObj.getClassId()));
        }

        if (searchObj.getSubjectId() != null && searchObj.getSubjectId().length() > 0) {
            Join<Clazz, Subject> join = root.join("subject");
            predicates.add(criteriaBuilder.equal(join.get("subjectId"), searchObj.getSubjectId()));
        }

        if (predicates.isEmpty()) {
            criteriaQuery.select(root);
        } else {
            criteriaQuery.select(root).where(predicates.toArray(new Predicate[predicates.size()]));
        }

        TypedQuery<Clazz> query = em.createQuery(criteriaQuery);
        return query.getResultList();

例外:

javax.persistence.PersistenceException: SELECT DN_THIS FROM thesis.filesharing.model.Clazz DN_THIS JOIN DN_THIS.subject WHERE (DN_THIS.classId = '44444') AND (DN_THIS.subject.subjectId = 'IT5834'): Can only reference properties of a sub-object if the sub-object is embedded.
at org.datanucleus.api.jpa.NucleusJPAHelper.getJPAExceptionForNucleusException(NucleusJPAHelper.java:302)
at org.datanucleus.api.jpa.JPAQuery.getResultList(JPAQuery.java:202)
at thesis.filesharing.dao.impl.ClassDAOImpl.countFoundClasses(ClassDAOImpl.java:203)
at thesis.filesharing.bo.impl.ClassBOImpl.countFoundClasses(ClassBOImpl.java:84)
at thesis.filesharing.test.TestController.searchClasses(TestController.java:143)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.google.appengine.tools.development.agent.runtime.Runtime.invoke(Runtime.java:115)
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:219)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:746)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:687)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:915)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:811)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:796)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166)

提前致谢

4

3 回答 3

0

实际上,您应该阅读一些内容,GAE Datastore因为基于数据存储的数据存储No-SQL database主要基于数据结构,因此这里没有任何关系(无表)仅类

@OneToMany..etc 不再支持

来自维基百科在计算中,NoSQL(通常解释为“不仅仅是 SQL”[1])是一类广泛的数据库管理系统,它不遵守广泛使用的关系数据库管理系统模型。NoSQL 数据库主要不是基于表构建的,并且通常不使用 SQL 进行数据操作。

于 2013-02-24T01:14:18.053 回答
0

由于 GAE 不能很好地处理标准连接,但接受以下类型的语句:

SELECT f FROM Foo f JOIN f.bar b WHERE b.id = "42"

我设法使用别名实现了这个问题的 hacky 解决方案,并且效果很好。不过,我不能保证这种方法的安全性,因此使用风险自负。

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Foo> q = cb.createQuery(Foo.class);
Root<Foo> foo = q.from(Foo.class);

foo.join("bar").alias("b1");  // Comment 1
foo.alias("b1");  // Comment 2
q.select(foo).where(cb.equal(foo.get("id"), "42"));
foo.alias("f1");  // Comment 3

TypedQuery<Foo> query = em.createQuery(q);
List<Foo> foos = query.getResultList();

有几点需要注意:

  • 注释 1:此别名仅代表bJPQL 语句中的第一个。
  • 注释 2:此别名代表bin b.id
  • 注释 3:此别名表示fJPQL 语句中的

生成的语句em.createQuery(q)等同于上面的 JPQL 语句。

于 2014-01-21T00:30:34.373 回答
0

如果子对象是嵌入的,则只能引用子对象的属性。

足够明确。GAE/Datastore 无法轻松应对“加入”。是否使用 JPQL 的 JPA 标准无关紧要,因为它们等同于对数据存储的相同要求

于 2013-02-22T19:14:10.683 回答