Какво причинява това изключение retainAll?

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)

Опитвам се да взема един списък, който извлякох от заявка за хранилище за данни, и да запазя само резултатите, които също са в списък, който извлякох от списък с ключове. И двата ми списъка са попълнени според очакванията, но изглежда не мога да използвам retainAll на нито един от тях.

//           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(), за да поставите елементите в нов списък с масиви? Stacktrace именно подсказва, че не сте използвали new ArrayList() за listTwo.   -  person BalusC    schedule 20.05.2010
comment
Съжалявам, че изрязах малко код, за да го опростя. Дефинирам listOne по-рано като нов ArrayList и след това предавам заявката в ArrayList. Няма да ми позволи да направя new ArrayList() за резултата от заявката, тъй като връща масив от обекти.   -  person Joren    schedule 20.05.2010


Отговори (3)


Няма да ми позволи да направя new 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