私はjpaにeclipselinkを使用していますが、イテレータが奇妙に機能しました...高度なクエリAPIを使用しないで修正した後、問題を絞り込んでみました。マニュアルの何かを完全に誤解しているようです...次の2つのクエリの結果が異なるのはなぜですか?
問題のあるコードは次のとおりです。
if (useAdvancedQuery) {
// doesn't write to db
ReadAllQuery readAllQuery = new ReadAllQuery(type);
readAllQuery.useCursoredStream(500, 500);
Session session = em.unwrap(Session.class);
scrollableCursor = (CursoredStream) session
.executeQuery(readAllQuery);
} else {
Query query = em.createQuery("SELECT e FROM " + type.getName()
+ " e ORDER BY e.id Desc");
query.setHint("eclipselink.cursor", true);
query.setHint("eclipselink.cursor.page-size", 50);
scrollableCursor = (CursoredStream) query.getSingleResult();
}
useAdvancedQuery==false の場合 、すべてが期待どおりに機能します
useAdvancedQueryを有効にすると失敗します...しかし、非常に奇妙な方法で:
- トランザクションは、イテレータを使用して値を正しく書き込むことができます
- 同じentityManagerFactoryからの別のトランザクションは、これらの変更を確認できます
- しかし...このEntityManagerFactoryを閉じて、新しいものを開くと、すべてがなくなります..
私は問題の1つのファイルの例を書きました:
package x;
import java.io.Serializable;
import java.util.*;
import javax.persistence.*;
import junit.framework.Assert;
import org.eclipse.persistence.queries.*
import org.eclipse.persistence.sessions.Session;
@Entity
public class TestEntity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
int id;
private String label;
private static final long serialVersionUID = 1L;
TestEntity() {
}
public TestEntity(String l) {
setLabel(l);
}
public static void main(String[] args) throws ClassNotFoundException {
new Extracted().run();
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
static class Extracted {
// tweakables
boolean useAdvancedQuery = true;
boolean useNewEntityManagers = false;
public <T> Iterator<T> getIterator(Class<T> type) {
final CursoredStream scrollableCursor;
// change this to false..and it will pass
if (useAdvancedQuery) {
// doesn't write to db
ReadAllQuery readAllQuery = new ReadAllQuery(type);
readAllQuery.useCursoredStream(500, 500);
Session session = em.unwrap(Session.class);
scrollableCursor = (CursoredStream) session
.executeQuery(readAllQuery);
} else {
Query query = em.createQuery("SELECT e FROM " + type.getName()
+ " e ORDER BY e.id Desc");
query.setHint("eclipselink.cursor", true);
query.setHint("eclipselink.cursor.page-size", 50);
scrollableCursor = (CursoredStream) query.getSingleResult();
}
return new Iterator<T>() {
@Override
public boolean hasNext() {
return scrollableCursor.hasMoreElements();
}
@Override
public T next() {
if (!scrollableCursor.hasMoreElements()) {
return null;
}
scrollableCursor.clear();
@SuppressWarnings("unchecked")
T c = (T) scrollableCursor.next();
return c;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
private EntityManagerFactory emf;
private EntityManager em;
public void run() {
{
emf = Persistence.createEntityManagerFactory("ptx2");
em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(new TestEntity("a"));
em.persist(new TestEntity("c"));
em.persist(new TestEntity("d"));
em.getTransaction().commit();
System.out.println("asd!");
em.close();
if (useNewEntityManagers)
emf.close();
}
String testStr = "tst" + new Random().nextInt();
{
if (useNewEntityManagers)
emf = getEntityManager();
em = emf.createEntityManager();
em.getTransaction().begin();
Iterator<TestEntity> it = getIterator(TestEntity.class);
while (it.hasNext()) {
TestEntity e = it.next();
e.setLabel(testStr);
// em.merge(e);
}
em.getTransaction().commit();
em.close();
if (useNewEntityManagers)
emf.close();
}
{
if (useNewEntityManagers)
emf = getEntityManager();
checkConsistance(testStr);
System.out.println("persisted in current session - ok");
emf.close();
}
{
System.out.println("persisted after reconnect?");
emf = getEntityManager();
checkConsistance(testStr);
emf.close();
}
System.out.println("passed");
}
private void checkConsistance(String testStr) {
em = emf.createEntityManager();
em.getTransaction().begin();
Iterator<TestEntity> it = getIterator(TestEntity.class);
while (it.hasNext()) {
TestEntity e = it.next();
Assert.assertEquals(testStr, e.getLabel());
}
em.close();
}
}
private static EntityManagerFactory getEntityManager() {
return Persistence.createEntityManagerFactory("ptx2");
}
}
注:私はEclipselink-2.5.0.v20130507-3faac2bを使用しています