Почему java.lang.Long не сохраняется?

Я пытаюсь запросить список идентификаторов типа Long в GAE/JDO. И я получаю следующее исключение, когда я вызываю detachCopyAll() для набора результатов.

org.datanucleus.jdo.exceptions.ClassNotPersistenceCapableException: The class "The class "java.lang.Long" is not persistable. This means that it either hasnt been enhanced, or that the enhanced version of the file is not in the CLASSPATH (or is hidden by an unenhanced version), or the Meta-Data/annotations for the class are not found." is not persistable. This means that it either hasnt been enhanced, or that the enhanced version of the file is not in the CLASSPATH (or is hidden by an unenhanced version), or the Meta-Data for the class is not found.
at org.datanucleus.jdo.NucleusJDOHelper.getJDOExceptionForNucleusException(NucleusJDOHelper.java:241)
at org.datanucleus.jdo.JDOPersistenceManager.jdoDetachCopy(JDOPersistenceManager.java:1110)
at org.datanucleus.jdo.JDOPersistenceManager.detachCopyAll(JDOPersistenceManager.java:1183)
...

Я могу запросить список объектов User и просто отсоединить их. Я ожидал, что все примитивные классы-оболочки, такие как Long, будут сохраняемыми. Что я делаю неправильно? Ниже приведен код, с которым я работаю.

@PersistenceCapable(identityType=IdentityType.APPLICATION, detachable="true")
public class User
{
    @PrimaryKey
    @Persistent(valueStrategy=IdGeneratorStrategy.IDENTITY) 
    private Long id;

    private String email;
}

@SuppressWarnings("unchecked")
public static List<Long> getUserKeys(String email)
{
    assert email != null;
    List<Long> keyList = null;
    PersistenceManager pm = null;
    Query query = null;
    try {
        pm = PMF.get().getPersistenceManager();    
        query = pm.newQuery("select id from " + User.class.getName());
        query.declareParameters("String emailParam");
        query.setFilter("email == emailParam");
        List<Long> resultList = (List<Long>) query.execute(email);          

        // next line causes the ClassNotPersistenceCapableException
        keyList = (List<Long>) pm.detachCopyAll(resultList);
    }
    finally {
        if (query != null) query.closeAll();
        if (pm != null) pm.close();
    }

    return keyList;
}

person KenSV    schedule 04.12.2011    source источник


Ответы (1)


    List<Long> resultList = (List<Long>) query.execute(email);          

    // next line causes the ClassNotPersistenceCapableException
    keyList = (List<Long>) pm.detachCopyAll(resultList);

Я не понимаю, что ты здесь делаешь. List<Long> не нужно отсоединять. Вы хотели бы отсоединить экземпляры своего класса сущностей User, но Long — это Long, и вы можете просто делать все, что вам нужно, с resultList.

Сообщение об ошибке сбивает с толку, но оно вызвано тем, что Long не является классом сущностей.

person Thilo    schedule 04.12.2011
comment
Лонги на самом деле должны быть отсоединены. В противном случае, если вы попытаетесь использовать какие-либо данные из запроса после закрытия PersistenceManager, вы получите следующее исключение. Попробуй. org.datanucleus.exceptions.NucleusUserException: Object Manager has been closed Но так как я не могу отсоединить List‹Long›, мне приходится копировать его элементы вручную в цикле. Это похоже на недосмотр DataNucleus. - person KenSV; 04.12.2011
comment
Нет, вы не отсоединяете Long. Объект, передаваемый в detachCopyAll, должен быть сохраняемого типа в соответствии со спецификацией JDO и документацией DataNucleus, а также ответом Thilo. - person DataNucleus; 04.12.2011
comment
Если мне не нужно отсоединять List<Long>, то почему я получаю исключение "Диспетчер объектов закрыт" при попытке его использования? - person KenSV; 04.12.2011
comment
@DataNucleus Это обходной путь, который я использую сейчас вместо detachCopyAll() keyList = new ArrayList<Long>(resultList.size()); for (Long uid : resultList) { keyList.add(uid); } - person KenSV; 04.12.2011
comment
Вы получаете, что ObjectManager не был закрыт, потому что Google не удосужился добавить логику в свой плагин, чтобы прочитать все результаты до закрытия соединения. т.е. НИЧЕГО СВЯЗАННОГО С ОТСОЛОМ. Как уже было сказано, вы только отсоединяете постоянные объекты - person DataNucleus; 04.12.2011
comment
Хм. Может быть, сам список загружен лениво (поэтому вам нужен диспетчер объектов, когда вы к нему обращаетесь)? Что вы получаете в качестве класса для списка? Ваш обходной путь кажется хорошим, более коротким будет keyList = new ArrayList<Long>(resultList). - person Thilo; 04.12.2011
comment
@Thilo и @DataNucleus, спасибо, причиной проблемы была ленивая загрузка. Я работаю над этой проблемой со следующей строкой. for (@SuppressWarnings("unused") Long uid : resultList) ; Он использует меньше памяти. - person KenSV; 05.12.2011