2

我刚刚开始使用 AppEngine,但数据存储存在一些问题。

我想使用 JPA 将一些数据写入数据存储区。我一直在关注 Appengine 网站上的 Java 示例和留言簿示例,我想将此留言簿示例翻译为使用 JPA 2.0。

当我在我的输出中使用我的数据存储区中已经可用的一些数据(使用以前的运行创建)运行应用程序时,它显示我在写入之前有 7 个项目,然后写入是好的,之后它又给了我 7 个项目。但是,如果我打开我的管理控制台 (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 不支持这种数据库一致性。对于每次写入,它们不会在后台复制数据库,而是同时写入 > 50% 的副本并稍后完成复制。因此,如果您先写入,然后立即读取,您的读取可能会遇到尚未复制的副本。

您只需要更改代码以避免写入后读取。通常这应该不是问题,因为它已经在内存中。

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

要在 Eclipse 中更改该设置,请转到 Project > Right Click > Google > AppEngine Settings > Run Configurations > Web Application > YOUR PROJECT > App Engine > High Replication Settings (HRD) Unapplied Job Percentage > 50。此值模拟次数百分比在开发中写入后读取将失败。0% = 正常数据库(但在生产中会失败)。

JPA 位于 Datastore API 之上,因此也存在同样的问题。

于 2013-11-15T02:30:53.643 回答