1

現在、JPA-2.0 ベースのアプリケーションを Hibernate から Google App Engine に移行しています。そこで実行したいからです。

SELECT クエリから結果を取得できないため、行き詰まっています。エンティティを永続化して ID で検索することはできますが、既存のすべてのエンティティを SELECT クエリで取得しようとすると、結果は空になります。

この問題を 1 つの単純なテスト ケースに切り分けました。

persistence.xml

<?xml version="1.0" encoding="UTF-8" ?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0">
    <persistence-unit name="google.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"/>
            <property name="datanucleus.singletonEMFForName" value="true"/>^
        </properties>
    </persistence-unit>
</persistence>

JPAエンティティークラス

import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
class TestEntity
{
    @Id
    String id;
    String name;

    TestEntity(String id, String name)
    {
        this.id = id;
        this.name = name;
    }

    // For deseralization
    @SuppressWarnings("unused")
    private TestEntity()
    {
    }
}

JUnit テストの失敗

import org.junit.*;
import static org.junit.Assert.*;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.TypedQuery;

import com.google.appengine.tools.development.testing.LocalDatastoreServiceTestConfig;
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;

public class SimpleJpaTest
{
    private static final String PERSISTENCE_UNIT = "google.transactions-optional";
    private static final EntityManagerFactory EMF = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT);

    private final LocalServiceTestHelper _helper;

    public SimpleJpaTest()
    {
        _helper = new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig().setDefaultHighRepJobPolicyUnappliedJobPercentage(100));
    }

    @Before
    public void setUp()
    {
        _helper.setUp();
    }

    @After
    public void tearDown()
    {
        _helper.tearDown();
    }

    @Test
    public void testPersistAndGet()
    {
        String id = "test";
        String name = "Test";

        // Persist entity
        EntityManager entityManager1 = EMF.createEntityManager();
        entityManager1.getTransaction().begin();
        TestEntity entity1 = new TestEntity(id, name);
        entityManager1.persist(entity1);
        entityManager1.getTransaction().commit();
        entityManager1.close();

        // Find specific entity
        EntityManager entityManager2 = EMF.createEntityManager();
        entityManager2.getTransaction().begin();
        TestEntity result2 = entityManager2.find(TestEntity.class, id);
        entityManager2.getTransaction().commit();
        entityManager2.close();

        assertNotNull(result2); // succeeds
        assertEquals(id, result2.id); // succeeds
        assertEquals(name, result2.name); // succeeds

        // Get all entities
        EntityManager entityManager3 = EMF.createEntityManager();
        entityManager3.getTransaction().begin();
        String queryString3 = "SELECT e from TestEntity e";
        TypedQuery<TestEntity> query3 = entityManager3.createQuery(queryString3, TestEntity.class);
        List<TestEntity> result3 = query3.getResultList();
        entityManager3.getTransaction().commit();
        entityManager3.close();

        assertNotNull(result3); // succeeds
        assertFalse(result3.isEmpty()); // fails
        assertEquals(1, result3.size());
        assertNotNull(result3.get(0));
        assertEquals(id, result3.get(0).id);
        assertEquals(name, result3.get(0).name);
    }
}

ご覧のとおり、find() による単一エンティティの取得はうまく機能しますが、SELECT クエリはうまく機能しません。同じコードが Hibernate でも問題なく動作します。


DataNucleus のコメントによる編集:

コンソール出力

Jan 30, 2013 2:41:10 PM org.datanucleus.metadata.MetaDataManager loadPersistenceUnit
WARNING: Class SimpleJpaTest was specified in persistence-unit google.transactions-optional but not annotated, so ignoring
Jan 30, 2013 1:41:11 PM com.google.appengine.api.datastore.dev.LocalDatastoreService init
INFO: Local Datastore initialized: 
    Type: High Replication
    Storage: In-memory
Jan 30, 2013 1:41:11 PM org.datanucleus.TransactionImpl internalPreCommit
INFO: >> calling preCommit on org.datanucleus.store.connection.ConnectionManagerImpl$2@15b573da
Jan 30, 2013 1:41:11 PM org.datanucleus.TransactionImpl internalPreCommit
INFO: >> calling preCommit on org.datanucleus.ObjectManagerImpl@5ede1ffa
Jan 30, 2013 1:41:11 PM org.datanucleus.TransactionImpl preFlush
INFO: >> calling preFlush on org.datanucleus.store.connection.ConnectionManagerImpl$2@15b573da
Jan 30, 2013 1:41:11 PM org.datanucleus.TransactionImpl preFlush
INFO: >> calling preFlush on org.datanucleus.ObjectManagerImpl@5ede1ffa
Jan 30, 2013 1:41:11 PM com.google.appengine.datanucleus.MetaDataValidator validate
INFO: Performing appengine-specific metadata validation for TestEntity
Jan 30, 2013 1:41:11 PM com.google.appengine.datanucleus.MetaDataValidator validate
INFO: Finished performing appengine-specific metadata validation for TestEntity
Jan 30, 2013 1:41:11 PM org.datanucleus.TransactionImpl internalPreCommit
INFO: >> calling preCommit on org.datanucleus.store.connection.ConnectionManagerImpl$2@49c54f01
Jan 30, 2013 1:41:11 PM org.datanucleus.TransactionImpl internalPreCommit
INFO: >> calling preCommit on org.datanucleus.ObjectManagerImpl@69eeff74
Jan 30, 2013 1:41:11 PM org.datanucleus.TransactionImpl preFlush
INFO: >> calling preFlush on org.datanucleus.store.connection.ConnectionManagerImpl$2@49c54f01
Jan 30, 2013 1:41:11 PM org.datanucleus.TransactionImpl preFlush
INFO: >> calling preFlush on org.datanucleus.ObjectManagerImpl@69eeff74
Jan 30, 2013 1:41:11 PM org.datanucleus.TransactionImpl preFlush
INFO: >> calling preFlush on org.datanucleus.store.connection.ConnectionManagerImpl$2@16f650e5
Jan 30, 2013 1:41:11 PM org.datanucleus.TransactionImpl preFlush
INFO: >> calling preFlush on org.datanucleus.ObjectManagerImpl@71fcf7e2
Jan 30, 2013 1:41:11 PM org.datanucleus.TransactionImpl internalPreCommit
INFO: >> calling preCommit on org.datanucleus.store.connection.ConnectionManagerImpl$2@16f650e5
Jan 30, 2013 1:41:11 PM org.datanucleus.TransactionImpl internalPreCommit
INFO: >> calling preCommit on org.datanucleus.ObjectManagerImpl@71fcf7e2
Jan 30, 2013 1:41:11 PM org.datanucleus.TransactionImpl preFlush
INFO: >> calling preFlush on org.datanucleus.store.connection.ConnectionManagerImpl$2@16f650e5
Jan 30, 2013 1:41:11 PM org.datanucleus.TransactionImpl preFlush
INFO: >> calling preFlush on org.datanucleus.ObjectManagerImpl@71fcf7e2

ところで: この問題はGoogle App Engine + google cloud sql jpa query does not retrieve data from databaseに似ているようですが、まだ答えはありません。

4

1 に答える 1

0

App Engine Datastoreに移行するよりも、Hibernate にとどまってGoogle Cloud SQLを使用する方がはるかに簡単だと思います...

于 2013-01-31T14:34:14.897 に答える