间歇性的Mongo / JPA IllegalArgumentException解析本地查询

时间:2018-07-09 14:45:35

标签: java mongodb jpa

我正在按照

运行mongo-java-driver
    <dependency>
        <groupId>org.mongodb</groupId>
        <artifactId>mongo-java-driver</artifactId>
        <version>3.7.0</version>
        <scope>compile</scope>
    </dependency>

hibernate-ogm-mongodb

    <groupId>org.hibernate.ogm</groupId>
    <artifactId>hibernate-ogm-bom</artifactId>
    <type>pom</type>
    <version>5.3.1.Final</version>
    <scope>import</scope>

使用以下命令执行本机查询时,

    String query = "db.%s.find({ 'location': { '$nearSphere': { '$geometry': { 'type': 'Point', 'coordinates': [%s,%s] }, '$maxDistance': %s } } })";
    String format = String.format(query, getType().getSimpleName(), p.getX(), p.getY(), distance * 1000.0);
    try {
        Query nativeQuery = getEm().createNativeQuery(format, getType());
        return nativeQuery.getResultList();
    } catch (Exception ex) {
        System.out.println("**** Location exception on query: "+ format);
        throw ex;
    }

我间歇性地收到以下异常。我可以立即运行相同的代码,并收到有效的输出。

javax.ejb.EJBTransactionRolledbackException: Error while parsing action 'Query/Optional/CliQueryOrJsonFindQuery/FirstOf/ParsedQuery/Db/Db_Action1' at input position (line 1, pos 3):
db.User.find({ 'location': { '$nearSphere': { '$geometry': { 'type': 'Point', 'coordinates': [28.051258087158203,-26.135223388671875] }, '$maxDistance': 2.0 } } })
  ^

java.lang.IllegalArgumentException: Cannot peek beyond the bottom of the stack
  at org.parboiled.common.Preconditions.checkArgument(Preconditions.java:79)
  at org.parboiled.support.DefaultValueStack.peek(DefaultValueStack.java:149)
  at org.parboiled.support.DefaultValueStack.peek(DefaultValueStack.java:144)
  at org.parboiled.support.DefaultValueStack.peek(DefaultValueStack.java:139)
at org.parboiled.BaseActions.peek(BaseActions.java:260)

这种情况发生在多个不同的文档集合上,但始终是间歇性的。从字面上重复该操作将导致返回有效结果。

我以前使用的是3.6.4版,但收到类似的错误。

是否有任何迹象表明我做错了什么,或某种版本冲突?

我尝试循环运行以查看是否可以重新创建它,但它似乎只发生一次-它可能与闲置时间过后的某种连接超时有关吗?

更新

我尝试通过并行运行两个线程来创建竞争条件,但确实看到了异常,尽管略有不同。

javax.ejb.EJBException: 
org.hibernate.ogm.datastore.mongodb.query.parsing.nativequery.impl
.NativeQueryParseException: 
Cli query should match the format db.collection.operation(<arguments>)
at 
org.jboss.as.ejb3.tx.CMTTxInterceptor.handleExceptionInOurTx
(CMTTxInterceptor.java:187) 

我认为这足够令人信服。

1 个答案:

答案 0 :(得分:1)

GitHub's page on Parboiled parser可以清楚地看出:

  

由parboiled为Java创建的解析器类不是线程安全的。

...,这可能在多个线程尝试执行此查询时给您带来问题。

尝试改用命名查询。带有注释,将类似于:

@NamedNativeQueries({
  @NamedNativeQuery(
    name = "findNearSphere",
    query = "db.:dbName.find({'location': { '$nearSphere': { '$geometry': { 'type': 'Point', 'coordinates': [:xCoord,:yCoord] }, '$maxDistance': :distance } } }", resultClass = SomeResultClass.class
  )
})

getEm()
  .createNamedQuery("findNearSphere")
    .setParameter("dbName", "User")
    .setParameter("xCoord", 28.051258087158203)
    .setParameter("yCoord", -26.135223388671875)
    .setParameter("distance", 2.0)
  .getResultList(); 

...希望可以避免每次您要发出查询时都使用解析器。

如果您不使用注释,则应在XML映射文件中定义一些示例。

但是请记住,我没有测试过此代码,我脑海中的一个问题是您是否必须在本机查询中转义冒号)。

HTH