【问题标题】:Usage of Hibernate OGM with cloud MongoDB Atlas M0 (Free Tier)Hibernate OGM 与云 MongoDB Atlas M0 的使用(免费套餐)
【发布时间】:2019-02-01 21:32:37
【问题描述】:

我正在尝试将 MongoDB Atlas M0(免费层)用于我的 JAVA EE 应用程序,现在我正在使用:

  • 本地 MongoDB 数据库 (v4.0.4)

  • 休眠核心“hibernate-core 5.3.6.Final”

  • 休眠 OGM “hibernate-ogm-mongodb 5.3.1.Final”

  • Java 应用服务器 WildFly 15.0.0.Final.

使用本地数据库,一对 MongoDB 和 Hibernate OGM 就像一个魅力,但是当我尝试在免费层上将 Hibernate 与 Mongo Atlas 连接以测试云数据库时,我无法建立有效的连接,因为 mongodb 驱动程序抛出异常com.mongodb.MongoSocketReadException: Prematurely达到流结束

我将提供我的 persistence.xml 的两个版本,第一个可以在 localhost 上正常工作,第二个是我用来连接到云的版本。

本地主机版本:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd"
             version="2.2">

    <!--   @@@   MongoDB   HIBERNATE   OGM   PERSISTENCE   UNIT   @@@   -->
    <persistence-unit name="PersistenceUnitNoSQL" transaction-type="JTA">

        <provider>org.hibernate.ogm.jpa.HibernateOgmPersistence</provider>

        <class>org.companyname.model.UserEntity</class>
        <class>org.companyname.model.ItemEntity</class>

        <properties>

            <property name="hibernate.ogm.datastore.provider" value="mongodb"/>
            <property name="hibernate.ogm.datastore.host" value="localhost:27017"/>
            <property name="hibernate.ogm.datastore.database" value="databasename"/>
            <property name="hibernate.ogm.datastore.create_database" value="true"/>

        </properties>

    </persistence-unit>

</persistence>

无法使用 atlas 云版本:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd"
             version="2.2">

    <!--   @@@   MongoDB   HIBERNATE   OGM   PERSISTENCE   UNIT   @@@   -->
    <persistence-unit name="PersistenceUnitNoSQL" transaction-type="JTA">

        <provider>org.hibernate.ogm.jpa.HibernateOgmPersistence</provider>

        <class>org.companyname.model.UserEntity</class>
        <class>org.companyname.model.ItemEntity</class>

        <properties>

            <property name="hibernate.ogm.datastore.provider" value="mongodb"/>
            <property name="hibernate.ogm.datastore.host" value="cluster0-clustername-shard-00-00-raa4n.mongodb.net:27017,cluster0-clustername-shard-00-01-raa4n.mongodb.net:27017,cluster0-clustername-shard-00-02-raa4n.mongodb.net:27017"/>

            <property name="hibernate.ogm.datastore.database" value="databasename"/>
            <property name="hibernate.ogm.datastore.create_database" value="true"/>

        <property name="hibernate.ogm.datastore.username" value="atlas-user-name"/>
        <property name="hibernate.ogm.datastore.password" value="atlas-user-password"/>
        <property name="hibernate.ogm.mongodb.authentication_mechanism" value="SCRAM_SHA_1"/>

        </properties>

    </persistence-unit>

</persistence>

像主机一样,我使用来自 Atlas 帐户帮助窗口的“标准连接字符串”的副本集 URI,因为使用“短 SRV 连接字符串”Hibernate 会抛出 org.hibernate.service.spi.ServiceException: OGM000072:无法配置数据存储提供者,所以我认为尚不支持这种类型的连接。

因此,在最后一个 persistence.xml 配置中,我遇到了以下错误:

20:02:01,094 INFO  [org.mongodb.driver.cluster] (ServerService Thread Pool -- 78) Cluster description not yet available. Waiting for 30000 ms before timing out
20:02:01,175 INFO  [org.mongodb.driver.cluster] (cluster-ClusterId{value='5c5497a97aea6111622c7540', description='null'}-cluster0-clustername-shard-00-02-raa4n.mongodb.net:27017)
Exception in monitor thread while connecting to server cluster0-clustername-shard-00-02-raa4n.mongodb.net:27017: com.mongodb.MongoSocketReadException: Prematurely reached end of stream
    at com.mongodb.internal.connection.SocketStream.read(SocketStream.java:112)
    at com.mongodb.internal.connection.InternalStreamConnection.receiveResponseBuffers(InternalStreamConnection.java:570)
    at com.mongodb.internal.connection.InternalStreamConnection.receiveMessage(InternalStreamConnection.java:441)
    at com.mongodb.internal.connection.InternalStreamConnection.receiveCommandMessageResponse(InternalStreamConnection.java:295)
    at com.mongodb.internal.connection.InternalStreamConnection.sendAndReceive(InternalStreamConnection.java:255)
    at com.mongodb.internal.connection.CommandHelper.sendAndReceive(CommandHelper.java:83)
    at com.mongodb.internal.connection.CommandHelper.executeCommand(CommandHelper.java:33)
    at com.mongodb.internal.connection.InternalStreamConnectionInitializer.initializeConnectionDescription(InternalStreamConnectionInitializer.java:106)
    at com.mongodb.internal.connection.InternalStreamConnectionInitializer.initialize(InternalStreamConnectionInitializer.java:63)
    at com.mongodb.internal.connection.InternalStreamConnection.open(InternalStreamConnection.java:127)
    at com.mongodb.internal.connection.DefaultServerMonitor$ServerMonitorRunnable.run(DefaultServerMonitor.java:117)
    at java.lang.Thread.run(Thread.java:748)

Hibernate 尝试连接到每个分片 (00-00, 00-01, 00-02),但都抛出此异常。

我试图解决这个问题的方法:

  • 使用 mongo-java-driver 版本 3.9.1 而不是内置的 Hibernate 3.6.3,但是两个驱动程序都存在相同的问题

  • 我的 IP 已添加(我的应用从我的笔记本电脑部署)到我的 atlas 帐户 IP 白名单

  • 我能够从 Mongo Shell 和 MongoDB Compass 很好地连接到集群

  • 我对“hibernate.ogm.mongodb.authentication_mechanism”有疑问,但“SCRAM_SHA_1”和“BEST”对我不起作用

  • 最后我尝试直接从 Java 连接到集群(不使用 Hibernate)

MongoClient mongoClient = MongoClients.create("mongodb+srv://atlas-user-name:atlas-user-password@cluster0-clustername-raa4n.mongodb.net/test?retryWrites=true");

MongoClient mongoClient = MongoClients.create("mongodb://atlas-user-name:atlas-user-password@cluster0-clustername-shard-00-00-raa4n.mongodb.net:27017,cluster0-clustername-shard-00-01-raa4n.mongodb.net:27017,cluster0-clustername-shard-00-02-raa4n.mongodb.net:27017/test?ssl=true&replicaSet=Cluster0-clustername-shard-0&authSource=admin&retryWrites=true");

两种情况都很好,我能够建立连接并毫无问题地使用数据库。

所以我的问题是为什么 Hibernate 会抛出这种异常?

【问题讨论】:

    标签: mongodb hibernate jakarta-ee hibernate-ogm mongodb-atlas


    【解决方案1】:

    Hibernate OGM 创建客户端的方式可能有问题。

    我认为现在为您检查这个更简单的方法是覆盖 MongoDBDatastoreProvider 并提供一个初始化的 MongoClient。

    您可以通过扩展 MongoDBDatastoreProvider 并覆盖方法 createMongoClient 来做到这一点。比如:

    package org.myprojects;
    
    import org.hibernate.ogm.datastore.mongodb.impl.MongoDBDatastoreProvider;
    
    public class MYCustomMongoDBDatastoreProvider extends MongoDBDatastoreProvider {
    
        @Override
        protected MongoClient createMongoClient(MongoDBConfiguration config) {    
           return MongoClients.create(...);
        }
    
    }
    
    

    然后使用属性OgmProperties.DATASTORE_PROVIDER 来使用您的数据存储提供程序:

    hibernate.ogm.datastore.provider = org.myprojects.MYCustomMongoDBDatastoreProvider
    

    在本例中,我将其设置在 hibernate.properties 文件中,但您可以将其设置在对您的项目更有意义的位置。

    编辑:关于错误的附加说明。

    I think the problems is that we are not using the factory to create the mongo client

    编辑 2:该问题可能是由于缺乏对 SSL 的支持造成的。 An issue has been created 并包含更多信息

    【讨论】:

    【解决方案2】:

    遇到同样的问题。另外,我启用了 SSL 并且连接成功:

    &lt;property name="hibernate.ogm.mongodb.driver.sslEnabled" value="true"/&gt;

    【讨论】:

    • 这是一个很好的解决方案,会检查它,谢谢@MaximSharai
    猜你喜欢
    • 2017-10-08
    • 2023-02-22
    • 2020-10-02
    • 2022-11-10
    • 1970-01-01
    • 1970-01-01
    • 2020-06-28
    • 2018-08-23
    • 1970-01-01
    相关资源
    最近更新 更多