2011-12-17 9 views
5

Dzisiaj po raz pierwszy używam GWT i JDO. Używam go z Eclipse w lokalnym trybie debugowania.JDO aplikacji App-Engine nie działa, może buforowanie?

zrobić następujące rzeczy:

public Collection<MyObject> add(MyObject o) { 
PersistenceManager pm = PMF.get().getPersistenceManager(); 
try { 
    pm.makePersistent(o); 
    Query query = pm.newQuery(MyObject.class);// fetch all objects incl. o. But o only sometimes comes... 
List<MyObject> rs = (List<MyObject>) query.execute(); 
ArrayList<MyObject> list= new ArrayList<MyObject>(); 
for (MyObject r : rs) { 
    list.add(r); 
} 
return list; 
} finally { 
    pm.close(); 
} 
} 

już ustawione <property name="datanucleus.appengine.datastoreReadConsistency" value="STRONG" /> w moim jdoconfig.xml. Czy muszę ustawić inne elementy transakcji w konfiguracji? Czy ktoś dostał działający jdoconfig.xml? Czy problem występuje gdzie indziej? Jakieś buforowanie pomiędzy nimi?

EDIT: Czego próbowałem:

  • Ustawianie NontransactionalRead/zapis do fałszywego
  • stosując tę ​​samą/inną PersistenceManager choć wzywającą PMF.get().getPersistenceManager() wielokrotnie
  • wykorzystaniem transakcji
  • ignoreCache = true pod numerem PersistenceManager
  • dzwoniąc pod numer flush i checkConsistency

jdoconfig:

<persistence-manager-factory name="transactions-optional"> 
<property name="datanucleus.appengine.datastoreReadConsistency" value="STRONG" /> 
    <property name="javax.jdo.PersistenceManagerFactoryClass" 
     value="org.datanucleus.store.appengine.jdo.DatastoreJDOPersistenceManagerFactory"/> 
    <property name="javax.jdo.option.ConnectionURL" value="appengine"/> 
    <property name="javax.jdo.option.NontransactionalRead" value="true"/> 
    <property name="javax.jdo.option.NontransactionalWrite" value="true"/> 
    <property name="javax.jdo.option.RetainValues" value="true"/> 
    <property name="datanucleus.appengine.autoCreateDatastoreTxns" value="true"/> 
</persistence-manager-factory> 

I musi być brakuje czegoś centralną tutaj, ponieważ wszystkie podejścia nie ...

EDIT2: Kiedy podzielić pracę na dwie transakcji dziennik mówi że transakcja zapisu została wyłowiona, a następnie rozpoczyna się transakcja odczytu. Ale nie znajduje obiektu, który jest właśnie persytem. Zawsze jest napisane: Level 1 Cache of type "weak" initialised. Czy tydzień jest zły czy dobry?

To około 30% żądań, które idą źle ... Może będę jakiś leniwy zapytanie ładowanie problemu?

+1

ja również zmierzyć sam problem. Dodaję obiekty za pośrednictwem mojej aplikacji, ale czasami nie odzwierciedlają one wyników, a czasem tak się dzieje! –

+0

, a obiekt jest w magazynie danych w momencie wykonywania zapytania? Oczywiście dziennik by ci to powiedział. Co to ma wspólnego z GWT jest niejasne ... – DataNucleus

+0

Gdzie znajdę dziennik?Co to ma wspólnego z GWT? Dużo, ponieważ jest to projekt GWT. Nie mogę tak naprawdę wytyczyć wyraźnej granicy między GWT a aplikacją, dlatego nazywam wszystko GWT, które pochodzi z google. I dlaczego buforowanie byłoby tak zepsute, że ta sama instancja nie może nawet odczytać danych właśnie napisanych? Czy możesz opublikować plik jdoconfig.xml, który zawsze będzie spójny dla tego samego klienta? –

Odpowiedz

2

Franz, domyślna spójność odczytu w konfiguracji JDO jest WYTRZYMAŁA. więc jeśli próbujesz podejść w tym kierunku, to nie doprowadzi cię nigdzie.

Sprawdź to, ponieważ myślę, że wspomina coś podobnego do scenariusza, którego doświadczasz, z zatwierdzonymi danymi, które nie zostały zwrócone w zapytaniu. To nie jest współbieżne, jak wspomniano, ale wyjaśnia proces zatwierdzania.

http://code.google.com/appengine/articles/transaction_isolation.html

Również inne podejście byłoby kwerendy przy użyciu Extents i dowiedzieć się, czy to rozwiązuje konkretnego przypadku użycia ty patrzysz, ponieważ wierzę, że są wyciągając wszystkie rekordy w tabeli.

EDIT:

Ponieważ w urywek kodu, które zostały wymienione, to pyta całą tabelę. A jeśli to jest to, czego potrzeba, można użyć pewnego stopnia ... sposób wykorzystania jest przez wywołanie

Extent ext = getExtent(<Entity Class name>)

na singleton obiektu persistenceManager. Następnie można wykonać iterację za pomocą Extent

Zapoznaj się z dokumentacją i wyszukaj tutaj zakresy na stronie. http://code.google.com/appengine/docs/java/datastore/jdo/queries.html

+0

Okay mówi, kiedy commit zwraca, że ​​nie jest zagwarantowane, że zmiany są widoczne (kto wymyśliłby taką głupią koncepcję?). Teraz pytanie brzmi: jak mogę wymusić widoczność? Czy mogę zrobić kilka sztuczek z moją klauzulą ​​where, ponieważ powiedziałeś coś o odpytywaniu na cały stół? –

+1

Zaktualizowano komentarz na temat korzystania z zakresów. Oto wyjaśnienie Buforowania w JDO. To może być przydatne. http://book.javanb.com/using-and-understanding-java-data-objects/LiB0046.html – Hrishikesh

+0

Zakres klasy i zapytanie o klasę to dokładnie to samo FWIW – DataNucleus

2

Wywołanie metody makePersistent() nie zapisuje danych w magazynie danych; zamykanie menedżera PersistenceManager lub zatwierdzanie zmian. Ponieważ nie zrobiłeś tego po uruchomieniu zapytania, dostajesz wszystkie obiekty z magazynu danych, które nie zawierają jeszcze obiektu, który właśnie nazwałeś makePersistent.

Przeczytaj o stanach obiektów tutaj: http://db.apache.org/jdo/state_transition.html

Istnieją dwa sposoby obejścia tego, można umieścić to wewnątrz transakcji od popełnienia pisze do magazynu danych (należy pamiętać GAE 5 transakcji/podmiot limitu typu o transakcjach) i commit przed uruchomieniem zapytania; Przykład wykorzystania transakcji ...

public Collection<MyObject> add(MyObject o) { 
    PersistenceManager pm = PMF.get().getPersistenceManager(); 
    ArrayList<MyObject> list = null; 
    try { 
     Transaction tx=pm.currentTransaction(); 
     try { 
      tx.begin(); 
      pm.makePersistent(o); 
      tx.commit(); 
     } finally { 
      if (tx.isActive()) { 
       tx.rollback(); 
      } 
     } 

     Query query = pm.newQuery(MyObject.class); 
     List<MyObject> rs = (List<MyObject>) query.execute(); 
     ArrayList<MyObject> list = new ArrayList<MyObject>(); 
     for (MyObject r : rs) { 
      list.add(r); 
     } 
    } finally { 
     pm.close(); 
    } 

    return list; 
} 

czy można zamknąć menedżera trwałości po wywołaniu makePersistent na O, a następnie otworzyć jeszcze jeden do uruchomienia na zapytanie.

// Note that this only works assuming the makePersistent call is successful 
public Collection<MyObject> add(MyObject o) { 
    PersistenceManager pm = PMF.get().getPersistenceManager(); 
    try { 
     pm.makePersistent(o); 
    } finally { 
     pm.close(); 
    } 

    pm = PMF.get().getPersistenceManager(); 
    ArrayList<MyObject> list = null; 
    try { 

     Query query = pm.newQuery(MyObject.class); 
     List<MyObject> rs = (List<MyObject>) query.execute(); 
     list= new ArrayList<MyObject>(); 
     for (MyObject r : rs) { 
      list.add(r); 
     } 

    } finally { 
     pm.close(); 
    } 

    return list; 
} 

UWAGA: I początkowo powiedział, że może po prostu dodać o do listy wynikowej przed powrotem; ale nie jest to mądrą rzeczą, ponieważ w przypadku, gdy istnieje problem zapisywania do magazynu danych, jest to o; wtedy zwrócona lista nie odzwierciedla faktycznych danych w magazynie danych.Wykonanie tego, co teraz mam (zatwierdzenie transakcji lub zamknięcie pm, a następnie uzyskanie kolejnej) powinno zadziałać, ponieważ masz ustawioną opcję datastoreReadPolicy na STRONG.

+2

Próbowałem obu podejść i owijania czytać i pisać w dwóch różnych transakcje. Czasami to działa, a czasami nie, jest to bardzo pomieszane. Czyściłem projekt, obniżono go do jdk6, teraz nie mam opcji. Nawet zadzwonię do flush i stałość Check po popełnieniu, ale to wszystko nie pomaga. Czasami dane nie docierają do magazynu danych wystarczająco szybko. Twój wcześniejszy pomysł z ręcznym dodaniem nowego obiektu do wyników. Zrobiłem to, ale czasami mam problemy z późniejszym zgłoszeniem, ponieważ ta wartość nadal nie jest dostępna w sklepie. Odświeżanie przeglądarki działa wtedy (głównie?). –

+0

Czy robisz wszelkiego rodzaju buforowanie; albo z jakąś mapą albo poprzez api Memcache? – Dave

1

Napotkałem ten sam problem, a to nie pomogło. Ponieważ wydaje się, że jest to najlepszy wynik w Google dla "zgodności silnika aplikacji jdo w eclipse" pomyślałem, że udostępnię dla mnie poprawkę!

Okazuje się, że używałem wielu instancji produktu PersistenceManagerFactory, co doprowadziło do dziwnego zachowania. Poprawka ma mieć singleton, do którego dostęp ma każdy kod. Jest to w rzeczywistości documented correctly na tutoriali GAE, ale myślę, że znaczenie jest zaniżone.

Uzyskanie PersistenceManager Instance

Aplikacja współdziała z użyciem JDO instancję klasy PersistenceManager . Otrzymasz tę instancję, tworząc instancję i wywołując metodę na instancji klasy PersistenceManagerFactory. Fabryka używa konfiguracji JDO do tworzenia instancji PersistenceManager.

Ponieważ inicjalizacja instancji PersistenceManagerFactory wymaga czasu, aplikacja powinna ponownie użyć jednej instancji. Łatwy sposób zarządzać PersistenceManagerFactory instancji jest stworzenie singleton wrapper klasę ze statycznym przykład w następujący sposób:

PMF.java

import javax.jdo.JDOHelper; 
import javax.jdo.PersistenceManagerFactory; 

    public final class PMF { 
     private static final PersistenceManagerFactory pmfInstance = 
      JDOHelper.getPersistenceManagerFactory("transactions-optional"); 

     private PMF() {} 

     public static PersistenceManagerFactory get() { 
      return pmfInstance; 
     } 
    } 
+0

Chociaż rozwiązuje to wiele innych problemów, nie rozwiązało to problemów, z którymi boryka się oryginalny plakat (również). Interfejs administratora devserver również nie odzwierciedla poprawnie zmian danych. Jeśli zostawiam wszystko, po prostu usiądę na jakiś czas, czasami widzę, że rzeczy się utrzymują i stają się dostępne. Czuje się przypadkowo, chociaż jestem pewien, że dzieje się coś jeszcze. –

Powiązane problemy