Что вызывает это исключение keepAll?

java.lang.UnsupportedOperationException: This operation is not supported on Query Results
    at org.datanucleus.store.query.AbstractQueryResult.contains(AbstractQueryResult.java:250)
    at java.util.AbstractCollection.retainAll(AbstractCollection.java:369)
    at namespace.MyServlet.doGet(MyServlet.java:101)

Я пытаюсь взять один список, который я получил из запроса к хранилищу данных, и сохранить только те результаты, которые также находятся в списке, который я получил из списка ключей. Оба моих списка заполнены, как и ожидалось, но я не могу сохранить все в одном из них.

//           List<Data> listOne = new ArrayList(query.execute(theQuery));
//           DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
//           List<Data> listTwo = new ArrayList(ds.get(keys).values());
//           listOne.retainAll(listTwo);

РЕДАКТИРОВАТЬ

Хорошо, в попытке упростить, поскольку это, по-видимому, несколько проблем в одной, я перестал использовать низкоуровневый API для хранилища данных и вместо того, чтобы просто вытягивать по одному с циклом.

                List<MyClass> test = (List<MyClass>) query.execute();
                List<MyClass> test2 = new ArrayList<MyClass>();

                for (String key : favorites) {
                    test2.add(pm.getObjectById(MyClass.class, key));
                }

                log.info(test.toString());
                test.retainAll(test2);

Выше работает. Он не генерирует исключение. Ниже приведено исключение. Единственная разница заключается в файле log.info. Я в тупике.

                List<MyClass> test = (List<MyClass>) query.execute();
                List<MyClass> test2 = new ArrayList<MyClass>();

                for (String key : favorites) {
                    test2.add(pm.getObjectById(MyClass.class, key));
                }

                test.retainAll(test2);

person Joren    schedule 20.05.2010    source источник
comment
Странно, вы уверены, что использовали new ArrayList() для помещения элементов в новый список массивов? Трассировка стека предполагает, что вы не использовали new ArrayList() для listTwo.   -  person BalusC    schedule 20.05.2010
comment
Извините, я вырезал часть кода, чтобы упростить его. Я определяю listOne ранее как новый ArrayList, а затем привожу запрос в ArrayList. Это не позволит мне сделать новый ArrayList() для результата запроса, поскольку он возвращает массив объектов.   -  person Joren    schedule 20.05.2010


Ответы (3)


Это не позволит мне сделать новый ArrayList() для результата запроса, поскольку он возвращает массив объектов.

Однако вам нужно поместить их в файл new ArrayList(). Возвращенная реализация List, по-видимому, не поддерживает retainAll(). Это то, что говорит вам исключение.

"Обычный" ArrayList поддерживает его. Если прохождение через конструктор ArrayList невозможно из-за разницы в универсальном типе, вам нужно будет вручную перебрать его и привести каждый элемент перед добавлением.

List<Data> listTwo = new ArrayList<Data>();
for (Object object : ds.get(keys).values()) {
    listTwo.add((Data) object);
}
listOne.retainAll(listTwo);

Обновление: согласно вашему обновлению, объекты, по-видимому, лениво загружаются/заполняются. Большинство ORM (одним из них является DataNucleus) действительно могут это делать. Поскольку я не использую DataNucleus, я не могу подробно рассказать, как это исправить «хорошим» способом. Но вы, по крайней мере, теперь знаете первопричину проблемы, и ее можно решить так же, как описано выше. Также заполните список test в цикле.

person BalusC    schedule 20.05.2010
comment
Хм, ds.get позволяет мне создать новый ArrayList. Я обнаружил, что это не позволит мне преобразовать Entity в мой тип объекта. Я не могу понять, как превратить сущность во что-то еще. Кроме того, очень странно, если после приведения listOne я делаю log.info(listOne.toString()); Я не получаю исключение UnsupportedOperationException. Если я не позвоню в log.info, я получаю сообщение об ошибке. Я понятия не имею, что с этим делать. - person Joren; 20.05.2010
comment
Ой. Хорошо, наконец-то работает. Я надеюсь, что кто-нибудь предложит менее глупое решение, чем создание списка вручную, но пока это работает. Спасибо! - person Joren; 20.05.2010
comment
Пожалуйста. Однако я бы заглянул в документацию DataNucleus, используя ключевые слова ленивая загрузка, чтобы увидеть, можно ли это как-то настроить, чтобы вам не нужно было с этим возиться. - person BalusC; 20.05.2010

Если тип коллекции, который вы используете для своего «списка ключей», не поддерживает retainAll, будет выдано исключение. Какой тип вы используете?

person Lars Andren    schedule 20.05.2010

СОВЕТ: вам не нужно выполнять итерацию, чтобы заполнить listTwo. просто делать:

listTwo.addAll(ds.get(keys).values())

person Black    schedule 21.07.2011