0

我的查询看起来像这样,但没有按预期工作。我已经尝试了很多不同的变体,但是我在查询中遗漏了一些东西。

存储库代码

@Query("SELECT c FROM /customer c, c.emailAddresses email WHERE email.emailAddress = $1")
List<CustomerEntity> findByEmailAddress(String emailAddress);       

型号

public class CustomerEntity {
   @Id
   protected String id;
   private List<CustomerEmailAddressEntity> emailAddresses;      
}

public class CustomerEmailAddressEntity {
   private Long id;
   private String emailAddress;
 }

我得到的堆栈如下所示:

Caused by: java.lang.ClassCastException: com.gemstone.gemfire.cache.query.internal.Undefined cannot be cast to com.gemstone.gemfire.cache.query.SelectResults
    at com.gemstone.gemfire.internal.cache.PRQueryProcessor.executeSequentially(PRQueryProcessor.java:330)
    at com.gemstone.gemfire.internal.cache.PRQueryProcessor.executeQuery(PRQueryProcessor.java:127)
    at com.gemstone.gemfire.internal.cache.PartitionedRegionQueryEvaluator.executeQueryOnLocalNode(PartitionedRegionQueryEvaluator.java:1370)
    at com.gemstone.gemfire.internal.cache.PartitionedRegionQueryEvaluator.executeQueryOnRemoteAndLocalNodes(PartitionedRegionQueryEvaluator.java:339)
    at com.gemstone.gemfire.internal.cache.PartitionedRegionQueryEvaluator.queryBuckets(PartitionedRegionQueryEvaluator.java:442)
    at com.gemstone.gemfire.internal.cache.PartitionedRegion.doExecuteQuery(PartitionedRegion.java:1909)
    at com.gemstone.gemfire.internal.cache.PartitionedRegion.executeQuery(PartitionedRegion.java:1829)
    at com.gemstone.gemfire.cache.query.internal.DefaultQuery.execute(DefaultQuery.java:234)
    at com.gemstone.gemfire.cache.query.internal.DefaultQuery.execute(DefaultQuery.java:195)
    at com.gemstone.gemfire.internal.cache.tier.sockets.BaseCommand.processQueryUsingParams(BaseCommand.java:1402)
    at com.gemstone.gemfire.internal.cache.tier.sockets.BaseCommand.processQuery(BaseCommand.java:1347)
    at com.gemstone.gemfire.internal.cache.tier.sockets.command.Query.cmdExecute(Query.java:88)
    at com.gemstone.gemfire.internal.cache.tier.sockets.BaseCommand.execute(BaseCommand.java:174)
    at com.gemstone.gemfire.internal.cache.tier.sockets.ServerConnection.doNormalMsg(ServerConnection.java:809)
    at com.gemstone.gemfire.internal.cache.tier.sockets.ServerConnection.doOneMessage(ServerConnection.java:940)
    at com.gemstone.gemfire.internal.cache.tier.sockets.ServerConnection.run(ServerConnection.java:1189)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at com.gemstone.gemfire.internal.cache.tier.sockets.AcceptorImpl$1$1.run(AcceptorImpl.java:532)
    at java.lang.Thread.run(Thread.java:724)

我不确定我做错了什么。任何帮助表示赞赏。

4

2 回答 2

1

接得好!

我要补充一点,一般来说,数组和基于集合的(应用程序域对象)属性永远不应该为空。空可以,但永远不会为空。这对于迭代可能是有问题的(特别是对于导致相当模糊的 NPE 的 foreach 循环,类似于自动装箱/拆箱中的 null 原始类型 Wrapper 对象)以及如您所见的 GemFire OQL。

不过,我同意如果 GemFire 确定查询问题的原因或能够处理空引用,它会提供更多信息和帮助。

有趣的是,这个问题可能是 GemFire 7.0.2 特有的。我刚刚使用 GemFire 7.0.2 和(最新的)GemFire 8.1.0 测试了这个场景。

在 7.0.2 中,发生以下异常...

org.springframework.dao.InvalidDataAccessApiUsageException: Result object returned from GemfireCallback isn't a SelectResult: [UNDEFINED]
...

但是,使用 GemFire 8.1.0 运行时,OQL 语句(查询)按预期工作,即使嵌套集合在我的应用程序域对象上未初始化......

class Customer ... {
  Set<Address> addresses;
  ...
}

interface CustomerRepository implements GemfireRepository<Customer, Long> {
  @Query("<trace> SELECT DISTINCT c FROM /Customers c, c.addresses a WHERE a.city = $1")
  List<User> findCustomersInCity(String city);

}

然后...

customerRepo.findCustomersInCity("Portland");

我(重新)对我的客户进行了编码,以便仅在添加地址时才初始化“地址”集合,并且我在测试用例中使用了带有和不带有地址的客户的组合。

因此,即使 GemFire 8.x 似乎可以处理这个问题,我仍然认为正确初始化对象是明智的。

于 2015-02-17T22:15:53.403 回答
0

我们小组中一位谦虚的建筑师找到了原因。这不是一个错误的查询,而是数据的问题。一些客户的电子邮件地址为空,而 Gemfire OQL 无法处理空集合元素。如果 GemfireOQL 给我一个更有用的错误信息会更好。

所以吸取了教训:

在将它们存储到 gemfire 7 之前预初始化您的集合。

于 2015-02-12T23:16:39.333 回答