2

AppEngineを使い始めたばかりですが、データストアに問題があります。

JPAを使用してデータストアにデータを書き込みたい。Appengine WebサイトのJavaの例をゲストブックの例でフォローしてきましたが、このゲストブックの例をJPA2.0を使用するように翻訳したいと思いました。

データストアですでに利用可能なデータ(以前の実行を使用して作成された)を出力に使用してアプリケーションを実行すると、書き込み前に7つのアイテムがあることが示され、書き込みは正常です。その後、再び7つのアイテムが表示されます。しかし、admin-console(http:// localhost:8888 / _ah / admin / datastore?kind = Greeting)を開くと、データストアにすでに8つのアイテムがあることがわかります。だから、どういうわけか私は幻の読み取りに苦しんでいます...

私のすべてのコードを以下に示します。

誰かが私が間違っていることを知っていますか?

これが私のpersistence.xmlの外観です:http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd "version =" 1.0 ">

<persistence-unit name="transactions-optional">
    <provider>org.datanucleus.api.jpa.PersistenceProviderImpl</provider>
    <properties>
        <property name="datanucleus.NontransactionalRead" value="true"/>
        <property name="datanucleus.NontransactionalWrite" value="true"/>
        <property name="datanucleus.ConnectionURL" value="appengine"/>
    </properties>
</persistence-unit>

そしてこれはコードです:

        EntityManagerFactory emf = EMF.get();
        EntityManager em = emf.createEntityManager();
        try {
            em.getTransaction().begin();

            // Reading the data
            javax.persistence.Query query = em.createQuery("SELECT FROM Greeting g");
            List<Greeting> greetings = query.getResultList();
            for (Greeting g : greetings) {
                log.info("Greeting found: " + g.getContent());
            }
            log.info("Number of greetings found before writing: " + greetings.size());

            // Storing the data
            Greeting greeting = new Greeting();
            greeting.setUser(user);
            greeting.setDate(new Date());
            greeting.setContent(content);

            em.persist(greeting);
            em.flush();

            // Reading the data
            query = em.createQuery("SELECT FROM Greeting g");
            greetings = query.getResultList();
            for (Greeting g : greetings) {
                log.info("Greeting found: " + g.getContent());
            }
            log.info("Number of greetings found after writing: " + greetings.size());
            em.getTransaction().commit();
        } catch (Exception e) {
            log.warning("Cannot write to database because of error: " + e.getMessage());
            e.printStackTrace();
        } finally {
            em.close();
            emf.close();
        }
4

1 に答える 1

0

Google AppEngineは、そのようなデータベースの整合性をサポートしていません。DBをバックグラウンドで複製する代わりに、書き込みごとに、コピーの50%以上に同時に書き込み、後で複製を終了します。したがって、書き込みを行ってすぐに読み取ると、読み取りがまだ複製されていないコピーにヒットする可能性があります。

書き込み後の読み取りを回避するには、コードを変更する必要があります。通常、これはすでにメモリにあるため、問題にはなりません。

https://developers.google.com/appengine/docs/java/datastore/structuring_for_strong_consistency

Eclipseでこの設定を変更するには、[プロジェクト]>[右クリック]>[Google]>[AppEngine設定]>[実行構成]>[Webアプリケーション]>[プロジェクト]>[AppEngine]> [高レプリケーション設定(HRD)未適用ジョブの割合]> 50に移動します。この値は、回数の割合をエミュレートします開発中の書き込み後、読み取りは失敗します。0%=通常のデータベース(ただし、本番環境では失敗します)。

JPAはDatastoreAPIの上にあるため、同じ問題が発生します。

于 2013-11-15T02:30:53.643 に答える