2011-12-17 31 views
5

Hôm nay, đây là lần đầu tiên tôi sử dụng GWT và JDO. Tôi đang chạy nó với Eclipse trong chế độ gỡ lỗi cục bộ.App-Engine JDO nhất quán đọc không hoạt động, có thể bộ nhớ đệm?

tôi làm những điều sau đây:

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(); 
} 
} 

tôi đã thiết lập <property name="datanucleus.appengine.datastoreReadConsistency" value="STRONG" /> trong jdoconfig.xml tôi. Tôi có phải đặt một số giao dịch khác trong cấu hình không? Có ai đó đã làm việc jdoconfig.xml? Hay là vấn đề ở đâu đó khác? Một số bộ nhớ đệm inbetween?

EDIT: Những điều tôi đã cố gắng:

  • Thiết NontransactionalRead/Viết false
  • Sử dụng cùng/A khác nhau PersistenceManager dù gọi PMF.get().getPersistenceManager() nhiều lần
  • Sử dụng giao dịch
  • ignoreCache = đúng trên PersistenceManager
  • gọi flushcheckConsistency

Các 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> 

tôi phải mất một cái gì đó trung tâm ở đây bởi vì tất cả các cách tiếp cận thất bại ...

EDIT2: Khi tôi chia công việc thành hai giao dịch các bản ghi nói rằng giao dịch ghi được đánh bắt và sau đó giao dịch đọc bắt đầu. Nhưng nó không tìm thấy đối tượng vừa bị thuyết phục. Nó luôn luôn nói Level 1 Cache of type "weak" initialised là tốt. Tuần xấu hay tốt?

Có khoảng 30% yêu cầu bị lỗi ... Tôi có thể gặp vấn đề tải truy vấn lười biếng không?

+1

Tôi cũng phải đối mặt với cùng một vấn đề. Tôi thêm một số đối tượng thông qua ứng dụng của tôi, nhưng họ không phản ánh trong kết quả, đôi khi, và đôi khi họ làm! –

+0

và đối tượng nằm trong kho dữ liệu tại thời điểm thực hiện truy vấn? Rõ ràng là nhật ký sẽ cho bạn biết điều đó. Điều này liên quan đến GWT là không rõ ràng ... – DataNucleus

+0

Tôi tìm nhật ký ở đâu?Những gì nó đã làm với GWT? Rất nhiều, bởi vì nó là một dự án GWT. Tôi không thể thực sự kéo một ranh giới rõ ràng giữa GWT và công cụ ứng dụng vì vậy tôi gọi mọi thứ GWT đến từ google. Và tại sao bộ nhớ đệm lại bị rối tung lên đến mức cùng một ví dụ không thể đọc được dữ liệu vừa được viết? Bạn có thể đăng tệp jdoconfig.xml sẽ luôn nhất quán cho cùng một ứng dụng không? –

Trả lời

2

Franz, tính nhất quán đọc mặc định trong Cấu hình JDO là STRONG. vì vậy nếu bạn đang cố gắng tiếp cận nó theo hướng đó, nó sẽ không dẫn bạn đến bất cứ đâu

Kiểm tra điều này vì tôi nghĩ nó đề cập đến một điều gì đó tương tự như kịch bản bạn đang gặp phải, với dữ liệu đã cam kết không được trả về trong truy vấn. Nó không đồng thời như đã đề cập, nhưng nó giải thích quy trình cam kết.

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

Ngoài ra, cách tiếp cận khác sẽ được truy vấn sử dụng Extents và tìm hiểu xem có thể giải quyết các trường hợp sử dụng cụ thể bạn đang nhìn vào, kể từ khi tôi tin rằng bạn đang kéo ra tất cả các bản ghi trong bảng.

EDIT:

Vì trong đoạn mã mà bạn đã đề cập, nó sẽ truy vấn toàn bộ bảng. Và nếu đó là những gì bạn cần, bạn có thể sử dụng một Mức độ ... Cách sử dụng nó là bằng cách gọi

Extent ext = getExtent(<Entity Class name>)

trên đối tượng singleton persistenceManager. Sau đó, bạn có thể lặp lại thông qua các tài liệu Extent

Kiểm tra tài liệu và tìm kiếm các phần Mở rộng trên trang tại đây. http://code.google.com/appengine/docs/java/datastore/jdo/queries.html

+0

Được rồi nó nói khi cam kết trả về nó không phải là đảm bảo rằng những thay đổi có thể nhìn thấy (người sẽ phát minh ra một khái niệm ngu ngốc như vậy?). Bây giờ câu hỏi là: làm thế nào tôi có thể buộc visiblity? Hoặc tôi có thể làm một số thủ đoạn với mệnh đề where của tôi, bởi vì bạn đã nói điều gì đó về truy vấn toàn bộ bảng? –

+1

Đã cập nhật nhận xét về cách sử dụng các Mức độ phổ biến. Ngoài ra, đây là một giải thích về Caching trong JDO. Nó có thể được sử dụng. http://book.javanb.com/using-and-understanding-java-data-objects/LiB0046.html – Hrishikesh

+0

Độ rộng của một lớp và Truy vấn của một lớp là chính xác điều tương tự FWIW – DataNucleus

2

Gọi phương thức makePersistent() không ghi vào kho dữ liệu; đóng PersistenceManager hoặc cam kết thay đổi của bạn. Vì bạn chưa thực hiện điều này khi bạn chạy truy vấn của mình, bạn sẽ nhận được tất cả các đối tượng từ kho dữ liệu mà chưa có, bao gồm đối tượng mà bạn vừa gọi là makePersistent.

Đọc về trạng thái đối tượng ở đây: http://db.apache.org/jdo/state_transition.html

Có hai cách này, bạn có thể đặt bên trong một giao dịch kể từ khi cam kết ghi vào kho dữ liệu (lưu ý GAE loại giới hạn/tổ chức 5 giao dịch về giao dịch) và cam kết trước khi chạy truy vấn của bạn; Ví dụ sử dụng giao dịch ...

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; 
} 

hoặc bạn thể đóng người quản lý kiên trì sau khi gọi makePersistent trên o và rồi mở một số khác để chạy truy vấn của bạn trên.

// 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; 
} 

LƯU Ý: tôi ban đầu cho biết bạn chỉ có thể thêm o vào danh sách kết quả trước khi trở về; nhưng đó không phải là một điều thông minh để làm vì trong trường hợp có một vấn đề bằng văn bản o đến kho dữ liệu; sau đó danh sách trả về sẽ không phản ánh dữ liệu thực tế trong kho dữ liệu.Làm những gì tôi có (cam kết một giao dịch hoặc đóng cửa pm và sau đó nhận được một cái khác) nên làm việc kể từ khi bạn có datastoreReadPolicy của bạn thiết lập để STRONG.

+2

Tôi đã thử cả hai cách tiếp cận và gói đọc và viết theo hai cách khác nhau giao dịch. Đôi khi nó hoạt động và đôi khi nó không, điều này là nghiêm trọng sai lầm. Tôi làm sạch dự án, hạ cấp xuống jdk6 bây giờ tôi không còn lựa chọn nào khác. Tôi thậm chí gọi tuôn ra và constancyCheck sau khi cam kết, nhưng tất cả đều không giúp đỡ. Đôi khi dữ liệu không đi vào kho dữ liệu đủ nhanh. Ý tưởng trước đó của bạn bằng cách thêm đối tượng mới vào kết quả theo cách thủ công. Tôi đã làm điều đó, nhưng sau đó đôi khi tôi gặp vấn đề với một yêu cầu sau đó, bởi vì giá trị đó vẫn không có trong cửa hàng. Một trình duyệt làm mới thủ thuật sau đó (chủ yếu?). –

+0

Bạn đang làm bất kỳ loại bộ nhớ đệm nào; hoặc với một số loại Bản đồ hoặc thông qua api Memcache? – Dave

1

Tôi gặp phải vấn đề tương tự và điều này không hữu ích. Vì nó có vẻ là kết quả hàng đầu trên Google về "tính nhất quán của công cụ ứng dụng jdo trong nhật thực", tôi nghĩ rằng tôi sẽ chia sẻ bản sửa lỗi cho tôi!

Hóa ra tôi đã sử dụng nhiều phiên bản PersistenceManagerFactory dẫn đến một số hành vi kỳ quái. Việc sửa chữa là để có một singleton rằng mỗi phần của mã truy cập. Đây là thực tế documented correctly trên hướng dẫn GAE nhưng tôi nghĩ rằng tầm quan trọng của nó là understated.

Bắt một PersistenceManager Instance

Một ứng dụng tương tác với JDO sử dụng một thể hiện của lớp PersistenceManager . Bạn nhận được cá thể này bằng cách khởi tạo và gọi phương thức trên một cá thể của lớp PersistenceManagerFactory. Nhà máy sử dụng cấu hình JDO để tạo các cá thể PersistenceManager.

Vì một cá thể PersistenceManagerFactory cần thời gian để khởi tạo, một ứng dụng sẽ sử dụng lại một cá thể duy nhất. Một cách dễ dàng để quản lý các dụ PersistenceManagerFactory là tạo ra một singleton lớp wrapper với một trường hợp tĩnh, như sau:

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

Trong khi điều này giải quyết được nhiều vấn đề khác, điều này không giải quyết được các vấn đề mà poster ban đầu phải đối mặt (cũng như vậy). Giao diện quản trị devserver cũng không phản ánh đúng các thay đổi dữ liệu. Nếu tôi để mọi thứ chỉ ngồi một lúc, _sometimes_ Tôi sẽ thấy mọi thứ vẫn tồn tại và trở nên có sẵn. Nó cảm thấy ngẫu nhiên, mặc dù tôi chắc chắn có cái gì đó khác đang xảy ra. –

Các vấn đề liên quan