简体   繁体   中英

Google App Engine datastore Entity not being deleted

I am using Google App Engine datastore to store 4 String values. The String vlaues are added to the datastore in a servlet:

DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();

        Entity balances;
        Key primaryKey;
        String table = "MainTable";
        String name = "Values";

        primaryKey = KeyFactory.createKey(table, name);

        Transaction t = datastore.beginTransaction();
            // If the 'table' exists - delete it
        datastore.delete(primaryKey);
            // Really make sure it's deleted/
        t.commit();

        t = datastore.beginTransaction();

            balances = new Entity("Balances", primaryKey);
        updateBalances(balances);
        datastore.put(balances);

            // Save the new data
        t.commit();
        resp.sendRedirect("/balance.jsp");

I want to be able to update the four String values each time the servlet is run - which is why I look for the key first and delete it. I even use a separate transaction to ensure this really happens.

The key is found and is deleted and then the values are added. But when I load a.jsp file which retrieves the values the number of 'records' in the Entity grows by 1 each time. I do not understand why the record is not being deleted.

Here is the.jsp code:

  <%
        DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();

        Key guestbookKey = KeyFactory.createKey("MainTable", "Values");

        Query query = new Query("Balances", guestbookKey);

        List<Entity> greetings = datastore.prepare(query).asList(FetchOptions.Builder.withLimit(5));
    %>
<!-- This should always be 1, but it gorws each time the servlet is hit.-->
    <%= greetings.size() %>

SOLUTION

I don't know what the problem was with the code in the original question. However I achieved my objective of persisting String values across sessions on a Google App Engine (GAE) by using a library called Objectify (http://code.google.com/p/objectify-appengine/) - which aims to simplify the use of the DataStore on GAE.

The library itself is just a.jar file and can be added to a Java project in Eclipse easily. I did not find using the library that easy to use...the main problem is registering the class which models the data you wish to save. Registration can only be done once!

To register the class only once I added a listener to my web app which registered the class with the Objectify framework and also created 4 random numbers and saved them:

public class MyListener implements ServletContextListener {
    public void contextInitialized(ServletContextEvent event) {

            // Register the Account class, only once!
        ObjectifyService.register(Account.class);

        Objectify ofy = ObjectifyService.begin();
        Account balances = null;

            // Create the values we wish to persist.
        balances = new Account(randomNum(), randomNum(), randomNum(),
                randomNum());

            // Actually save the values.
        ofy.put(balances);
        assert balances.id != null;    // id was autogenerated
    }

    public void contextDestroyed(ServletContextEvent event) {
        // App Engine does not currently invoke this method.
    }

    private String randomNum() {
        // Returns random number as a String
    }
}

.. this code is run only once when the server starts - for this to happen I also needed to modify web.xml to add:

<listener>
        <listener-class>.MyListener</listener-class>
    </listener>

Then I just had a.jsp page which read the saved values:

<%
Objectify ofy = ObjectifyService.begin();
boolean data = false;
// The value "mykey" was hard coded into my Account class enter code here 
// since I only wanted access to the same data every time.
Account a = ofy.get(Account.class, "mykey");
data = (null!=a);
%>

Here is my Account class:

import javax.persistence.*;

public class Account
{
    @Id String id = "mykey";
    public String balance1, balance2, balance3, balance4;

    private Account() {}

    public Account(String balance1, String balance2, String balance3, String balance4)
    {
        this.balance1 = balance1;
        this.balance2 = balance2;
        this.balance3 = balance3;
        this.balance4 = balance4;
    }
}

One last thing...I found the OBjectify documentation very helpful in understanding GAE Datastore irrespective of the Objectify framework

For future reference, I think your original example failed because of this line:

balances = new Entity("Balances", primaryKey);

This doesn't actually create an entity with primaryKey, but it creates an entity with primaryKey as the ancestor key. It will get an automatically generated id every time you store it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM