Sdscompany.ru

Компьютерный журнал
0 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Ljava lang string

Ljava lang string

В настоящее время Android-приложения хранят свой код в файле «classes.dex».
При декомпиляции приложения, «classes.dex» разберается на файлы *.SMALI, в каждом из которых содержется своя часть кода — которая доступна нам для редактирования.

GetInternalFilesDir() — назначает место расположения кэша при невозможности сохранения на SD-карту.
На данный момент располагается в «smalicomblizzardwtcghearthstoneFileUtils.smali»
Заменив содержимое метода целиком на нижеприведенный, кэш будет устанавливаться в «Android/data» пользовательской памяти, вместо «data/data» системного раздела

SetHSTextureFormat — определяет тип используемого кэша.
На данный момент располагается в «smalicomblizzardwtcghearthstoneDeviceSettings.smali»
Заменив содержимое метода целиком на нижеприведенный, игра будет работать только с кэшем «ETC1», игнорируя поддержку «ASTC», «ATC», «PVRTC» и «DXT»

installApk — запускает процедуру проверки и обновления приложения.
Заменив содержимое метода целиком на нижеприведенный, приложение будет пропускать данную проверку.

Assembly-CSharp.dll содержит в себе множество функций всего происходящего в игре.
Изменяя их, мы можем поменять практически любое событие.

Network > GetPlatformBuilder — определяет информацию об устройстве, которая в итоге отправляется на игровой сервер.
Можно использовать для получения подарков по акции «Galaxy Gift», изменив код на такой:

TimeScaleMgr > Update — здесь можно изменить скорость проигрывания анимаций в игре.
В данном примере выставлено трехкратное ускорение игры.

Текстуры в форматах ETC и RGBA поддерживаются практически во всех устройствах на Android.
ATC, PVRTC и DXT — чипо-зависимые, и, обычно, устройством поддерживается только один из этих форматов.
ETC2 — требует Android 4.3 или новее, и поддержку OpenGL ES 3.0
ASTC — требует Android 5.0 или новее, и поддержку OpenGL ES 3.2 (либо OpenGL ES 3.1 + Android Extension Pack).
Если устройство не поддерживает текстуры используемого вами кэша, то игра попытается их переконвертировать на лету в RGBA32 — что позволит отобразить весь игровой контент, но из-за дополнительной нагрузки на процессор — появятся фризы и провисания FPS.

Для сборки Low-End Mod’а рекомендую уменьшать текстуры с каналом прозрачности (альфа-каналом) до 64x64px, и сохранять в DDS с форматом ARGB4444, без мипмапов.

[Mobile]
Store = Google
Mode = Production

Если на мобильном устройстве отсутствует GooglePlayMarket, то в игре перестаёт быть доступным внутриигровой магазин.
Но если мы изменим значение параметра Store на Battle.net, то магазин будет доступен и без стороних сервисов.

Также есть возможность включить симуляцию запуска игры на устройстве иного типа.
Например, чтобы запустить игру с мобильным интерфейсом, нужно добавить эти строки:

Здесь значение Android Phone можно заменить на Android Tablet, и это привёд к тому что будет принудительно запускаться планшетный интерфейс.
Более подробное описание доступно в этом посте: Hearthstone[3D, Online] (Пост zloyted #63567819)

Для игроков PC-версии игры, существуют параметры запуска игры минуя Battle.net-клиент.
Делается это просто, добавлением вот этих строк:

  • кэш размещается в «Android/data» пользовательской памяти, вместо «data/data» системной памяти
  • занижены минимальные требованиятройству для запуска приложения

Hearthstone v11.4.25447 mod.apk ( 41,7 МБ )

Hearthstone v11.4.25447 LEM ETC1.apk ( 37,71 МБ )
Hearthstone v11.4 LEM ETC1 cache.7z ( 108,33 МБ )

Ссылка на заметку со всеми пояснениями
Hearthstone v11.4.25447 LEM ASTC.apk ( 37,71 МБ )

Распаковать Assembly-CSharp.dll и поместить по пути «HearthstoneHearthstone_DataManaged«, заменив оригинал (строго рекомендуется сделать копию оригинального файла).

Список изменений:

  • добавлено управление скоростью анимации в игре ползунком в левой части окна игры, и стрелками на клавиатуре
  • убран эффект тряски камеры
  • добавлена возможность получить подарки по акции GalaxyGift
  • принудительно используется магазин Blizzard (полезно при использовании мобильного интерфейса)
  • все отсутствующие карты в коллекции отображаются в цвете

Hearthstone PC 11.4 MixMod.zip ( 2,34 МБ )

JNI взаимодействие Java с C/C++

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

Однако иногда без использования вспомогательных средств создать полноценную программу согласно техническим требования невозможно. Например, необходимо воспользоваться кодом, который обеспечивает низкоуровневый доступ к «железу» компьютера, на котором выполняется программа. В языке программирования Java, который по своей идеологии является многоплатформенным, средства низкоуровневого доступа к аппаратной части просто-напросто не предусмотрены. С другой стороны, к моменту появления языка Java в мире программирования уже существовали колоссальные «залежи» программ и библиотек, позволяющих решать практически любые задачи, начиная от математических вычислений и заканчивая управлением сложными системами. Естественно, не замечать это богатство было бы просто неразумно.

Разработчики Java включили в язык возможность обращения из приложений к программам, реализованным на других языках программирования с использованием так называемых native-методов. Подсистема Java, реализующая данную возможность, называется JNI (Java Native Interface – интерфейс обращения к native-методам). К native методам следует прибегать в том случае, когда необходимо воспользоваться сторонней dll библиотекой, чтобы ускорить критичный алгоритм за счет оптимизированного кода на C/С++ или ассемблере. Например, для обработки потокового медиа, сжатия, шифрования и т.п.

Зачастую native-методы просты: они не вызывают исключений, не создают новые объекты в heap’e, не обходят stack, не работают с handle’ами и не синхронизованы. Можно ли для них не делать лишних действий? В статье будет затронуты вопросы о недокументированных возможностях HotSpot JVM для ускоренного вызова простых JNI методов.

Процедуры, обеспечивающие связь native-метода с программой Java, зависят от применяемой операционной системы и языка программирования, на котором native-методы реализованы. В статье рассматривается связь языка Java с библиотеками DLL операционных систем семейства Microsoft Windows. Рассмотрим простой вариант использования JNI. Пример показывает насколько несложно использовать данный механизм.

Пример использования JNI в java приложениях

Допустим, необходимо создать dll библиотеку, методы которой получают и обрабатывают текстовые и целочисленные значения. Результат обработки возвращается также в текстовом и целочисленном виде. Для решения данной задачи создаем проект jnicall-desk, в который включаем обычный класс JNICall.java с описанием методов. Реализация методов будет выполнена в библиотеке dll. На следующем скриншоте приведена структура проекта. Класс JNICallTest.java будет использоваться для тестирования методов библиотеки dll.

Листинг класса JNICall.java

Класс JNICall.java включает три метода, при описании которых указываем модификаторы native. Для загрузки библиотеки dll (JNICall.dll) используется системный вызов loadLibrary(). Необходимо отметить, что наименование загружаемой библиотеки указывается без расширения «.dll».

Читать еще:  Словарь на ошибки

Класс располагается в пакете com.example, и на это следует обратить пристальное внимание. Это очень важный момент, поскольку наименование пакета будет использовано в наименованиях методов в коде С/С++. Далее перемещать данный класс в другой пакет не следует; иначе не будет загружаться динамическая библиотека.

В проекте классы .java компилируются в директорию bin, где «раскладываются» по пакетам (поддиректориям). После компиляции класса JNICall получаем в проекте файл com.example.JNICall.class. Для создания файла с заголовком для C/C++ обработаем класс утилитой javah, которая создаст файл «com_example_JNICall.h».

Параметр classpath ссылается на директорию bin (-classpath bin). Для класса JNICall приводится полное имя : [package].[Class.name].

Листинг com_example_JNICall.h

В результате выполнения команды javah в корневой директории проекта (где была выполнена команда) будет создан файл com_example_JNICall.h следующего вида:

Следует обратить внимание на 2-ю строчку, в которой выполняется импорт файла . Месторасположение данного файла следует искать в JDK в директории include. На моем компьютере он располагается в директории
«C:Program FilesJavajdk1.8.0_131include». Файл «jni.h» потребовал дополнительно «jni_md.h» из поддиректории win32
(«C:Program FilesJavajdk1.8.0_131includewin32»).

Проект создания dll

Для создания библиотеки JNICall.dll был использован CodeBlocks, который «легко» устанавливается на компьютер. При создании проекта выбран тип «Dynamic Link Library», в который включен файл com_example_JNICall.h и добавлен файл com_example_JNICall.cpp. На следующем скриншоте представлен проект создания библиотеки из двух файлов.

Редактировать заголовок не следует; его необходимо включить в файл CPP (com_example_JNICall.cpp), который представлен ниже :

В коде класса com_example_JNICall.cpp следует обратить внимание на обработку строк. Целочисленные переменные обычно не так сложны. Текстовые же значения нужно «вытащить» из Unicode в обычный char.

Метод doMultiply возвращает значение произведения двух чисел. Метод doCombine — создает одну строку из двух строк. Метод getMessage к текстовой строке «Get text : » добавляет строку, полученную в качестве параметра.

Примечание : в Windows создаваемая библиотека будет называться JNICall.dll; в Linux она должна иметь наименование libJNICall.so, т.е. обязательно начинаться с префикса ‘lib’. Несмотря на то, что в Linux наименование библиотеки .so имеет префикс, при загрузке в LoadLibrary префикс не используется.

Класс тестирования JNI

Обратите внимание, что в проекте jnicall-desk созданная библиотека располагается в поддиректории «dll». Чтобы JVM могла найти эту библиотеку следует внести исправления в строку загрузки класса JNICall.java :

Это работает для standalone-приложения, но это НЕПРАВИЛЬНО. А если динамическую библиотеку необходимо будет использовать в WEB-приложении, то данный подход уже не сработает, библиотека не будет найдена и Вы увидите исключение java.lang.UnsatisfiedLinkError. ПРАВИЛЬНЫЙ подход — это использование «java.library.path», который работает как в standalone приложении, так и WEB-приложении. Пример использования JNI в сервлете WEB-приложения, включающего ajax-вызов библиотеки JQuery, можно увидеть здесь.

Коротко о java.library.path

«java.library.path» это, если можно так выразиться, аналог classpath, но только не для Java классов и *.jar файлов, а для нативных библиотек. Т.е. является свойством, которое указывает JVM, где искать нативные библиотеки. Свойство «java.library.path» устанавливается перед запуском java-приложения (читай JVM), через глобальные system properties, или как ключ -Dname=value. После этого оно становится read-only.

На просторах Интернета можно найти 2 примера как изменить данное свойство в run-time. Вы можете посмотреть первоисточник откуда получен следующий метод setLibraryPath :

Данный метод был протестирован, он рабочий, но мне, откровенно говоря, не очень понравился, поскольку обнуляет поля. В примере JNICallTest.java для тестирования JNI был использован второй метод addLibraryPath.

Листинг класса JNICallTest.test

В классе выполняется проверка наличия библиотеки dll в поддиректории. Если библиотека найдена, то добавляется путь к dll в переменную «usr_paths» загрузчика класса ClssLoader. Остальное все тривиально и прозрачно, особых комментариев не требуется. Помните, что в системный метод загрузки библиотеки loadLibrary в классе JNICall необходимо передать только ее наименование, т.е. использовать код : System.loadLibrary(«JNICall»).

В классе выполняется проверка наличия библиотеки в поддиректории, после чего определяется путь к директории и вызывается метод addLibraryPath, который добавляет этот путь в соответствующее свойство загрузчика. Далее вызываются native методы.

Результат выполнения программы выводится в консоль :

Исходный код примера можно скачать в конце страницы.

Особенности использования JNI

Но зачастую native методы просты: они не вызывают исключений, не создают новые объекты в heap’e, не обходят стек, не работают с хендлами и не синхронизованы. Можно ли для них не делать лишних действий?

Далее в статье будут рассмотрены недокументированные возможности HotSpot JVM для ускоренного вызова простых JNI методов.
Рассмотрим для примера простой native метод, получающий на вход массив byte[] и возвращающий сумму элементов. Есть несколько способов работы с массивом в JNI:

1. GetByteArrayRegion – копирует элементы Java массива в указанное место нативной памяти.

2. GetByteArrayElements – то же самое, только JVM сама выделяет область памяти, куда будут скопированы элементы. По окончании работы с массивом необходимо вызвать ReleaseByteArrayElements.

Здесь можно задаться вопросом:»Зачем делать копию массива?». Но ведь работать с объектами в Java Heap напрямую из натива нельзя, так как они могут перемещаться сборщиком мусора прямо во время работы JNI метода. Однако есть функция GetPrimitiveArrayCritical, которая возвращает прямой адрес массива в heap’e, но при этом запрещает работу GC до вызова ReleasePrimitiveArrayCritical.

Метод Critical Native

А вот и секретный инструмент. Внешне он похож на обычный JNI метод, только с приставкой JavaCritical_ вместо Java_. Среди аргументов отсутствуют JNIEnv* и jclass, а вместо jbyteArray передаются два аргумента: jint length – длина массива и jbyte* data – «сырой» указатель на элементы массива. Таким образом, Critical Native методу не нужно вызывать дорогие JNI функции GetArrayLength и GetByteArrayElements – можно сразу работать с массивом. На время выполнения такого метода GC будет отложен.

Как можно увидеть, в реализации не осталось ничего лишнего. Но чтобы метод мог стать Critical Native, он должен удовлетворять строгим ограничениям:

  • метод должен быть static и не synchronized;
  • среди аргументов поддерживаются только примитивные типы и массивы примитивов;
  • Critical Native не может вызывать JNI функции, а, следовательно, аллоцировать Java объекты или вызывать исключения;
  • метод должен завершаться за короткое время (самое главное), поскольку на время выполнения он блокирует GC.
Читать еще:  Java arraylist object

Critical Natives задумывался как приватный API HotSpot’a для JDK, чтобы ускорить вызов криптографических функций, реализованных в native методе.

Важная особенность: JavaCritical_ функции вызываются только из горячего (скомилированного) кода, поэтому помимо JavaCritical_ реализации у метода должна быть еще и «запасная» традиционная JNI реализация. Впрочем, для совместимости с другими JVM так даже лучше.

Давайте, измерим, какова же экономия при работе с массивами разной длины: 16, 256, 4KB, 64KB и 1MB. Естественно, с помощью JMH.

Оказывается, для маленьких массивов стоимость JNI вызова в разы превосходит время работы самого метода! Для массивов в сотни байт накладные расходы сравнимы с полезной работой. Ну, а для многокилобайтных массивов способ вызова не столь важен – всё время тратится собственно на обработку.

Critical Natives – приватное расширение JNI в HotSpot, появившееся с JDK 7. Реализовав JNI-подобную функцию по определенным правилам, можно значительно сократить накладные расходы на вызов native метода и обработку Java-массивов в нативном коде. Однако для долгоиграющих функций такое решение не подойдет, поскольку GC не сможет запуститься, пока исполняется Critical Native.

Источник информации об особенностях использования JNI можно увидеть здесь.

Скачать пример

Рассмотренный на странице пример, включающий проект Eclipse с использованием JNI, можно скачать здесь (37.2 Кб). Библиотека JNICall.dll создана для windows x64.

Пример использования JNI в сервлете WEB-приложения можно увидеть здесь.

Ljava lang string

66686 просмотра

6 ответа

56 Репутация автора

На этот вопрос уже есть ответ здесь:

У меня есть массив строк с четырьмя элементами, которые я определил. Почему, когда я печатаю System.out.println(name of Array) , элементы не выводятся? Но вместо этого дает мне странный вывод.

Вот вывод, который я получил:

Ответы (6)

1 плюс

11347 Репутация автора

Вам нужно перебрать свой массив (например, с for циклом) и распечатать каждое значение отдельно.

Если вы попытаетесь напечатать массив, он напечатает информацию об объекте, которая вам не покажется действительно интересной.

2 плюса

64131 Репутация автора

Каждый объект имеет toString() метод, который вы видите, строковый массив toString.

Автор: Joe Размещён: 07.12.2011 04:13

18 плюса

47111 Репутация автора

toString() Метод массива возвращает String описывающий идентификатор массива , а не его содержание. Это потому, что массивы не переопределяются Object.toString() , чья документация объясняет, что вы видите:

toString Метод класса Object возвращает строку , состоящую из имени класса которого объект является экземпляром, на-знак символ `@», и без знака шестнадцатеричное представление хэш — кода объекта. Другими словами, этот метод возвращает строку, равную значению:

Чтобы получить String представление содержимого массива, вы можете использовать Arrays.toString(Object[]) .

String Возвращенное этот метод , состоит из каждого элемента toString() представления, в том порядке , они появляются в массиве , и заключенных в квадратных скобках ( «[]» ). Смежные элементы разделяются запятой и пробелом ( «, » ).

Например, вызов этого метода в вашем массиве приведет к следующему String :

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

Затем метод вернет это String :

Важно отметить, что использование этого метода не дает вам никакого контроля над форматированием полученного результата String . Это удобно для быстрой проверки содержимого массива, но оно ограничено этой целью. Например, что, если вы не хотите, чтобы эти квадратные скобки были заключены в скобки, или хотите перечислять каждый элемент построчно?

На этом этапе вы должны начать видеть значение реализации вашего собственного метода для вывода содержимого вашего массива способом, специфичным для вашей задачи. Как уже предлагали другие, попрактикуйтесь в этом, используя for цикл и создавая новый результат, String который вы хотите вывести.

Вы можете найти больше информации о for циклах в этой статье Java Tutorials . В целом, Java Tutorials отлично подходят для начинающих и должны хорошо сопровождать ваш курс.

Ljava lang string

Классы и объекты в Java должны быть инициализированы перед их использованием. Поля класса могут инициализироваться значениями по умолчанию, когда классы загружаются, но есть и другие способы. В данной статье мы рассмотрим все функции Java для инициализации классов.

Перед тем как мы исследуем поддержку в Java для инициализации класса, давайте резюмируем основы инициализации Java. Рассмотрим листинг 1.

Листинг 1. Инициализация полей класса значения по умолчанию В листинге 1 объявляется класс Up. Этот класс объявляет девять типов полей boolean, byte, char, double, float, int, long, short и String. Когда Up загружен, биты каждого поля устанавливаются в ноль, что вы можете интерпретировать следующим образом:

Предыдущие поля класса были неявно инициализированы нулем. Тем не менее, вы можете также явно инициализировать поля класса путем непосредственного присвоения им значений, как показано в листинге 2.

Листинг 2. Инициализация полей класса явными значениями Значение каждой переменной должно быть совместимым по типу с типом поля класса. Каждая переменная хранит значение непосредственно в себе, за исключением st. Переменная st хранит ссылку на String объект, который содержит upread.

Ссылка на объявленные ранее поля

При инициализации поля класса возможно инициализировать его значением ранее инициализированного другого поля класса. Например, в листинге 3 y инициализируетcя x.

Листинг 3. Ссылаемся на ранее объявленное поле Однако обратное будет неверным: вы не можете инициализировать поле класса еще не объявленным значением. Компилятор Java выведет illegal forward reference, когда встретит листинг 4.

Листинг 4. Попытка сослаться на поле со значением, присвоенным позже Компилятор будет сообщать о illegal forward reference, когда он встречает static int x = y;. Это происходит потому, что исходный код компилируется сверху вниз, и компилятор еще не видел y . (Также это сообщение было бы выведено, если бы y не была явно инициализирована.)

Инициализация класса блоков

Читать еще:  Javascript обработчик формы

Вы можете выполнять сложные инициализации класса после того, как был загружен класс и прежде, чем любые объекты создаются из этого класса (при условии, что класс не является утилитой класса). Для выполнения этой задачи вы можете использовать блок инициализации класса. Блок инициализации класса представляет собой блок операторов, которым предшествует ключевое слово static. Когда класс загружается, эти операторы выполняются. Рассмотрим листинг 5.

Листинг 5. Инициализация массивов синус и косинус значений В листинге 5 объявляется класс Up, в котором имеются sin и cos массивы переменных. Он также объявляет блок инициализации класса, который создает 360-элементные массивы, ссылки присваиваются sin и cos. Затем он использует цикл for, чтобы инициализировать эти элементы массива соответствующими синус и косинус значениями, с помощью вызова методов из класса Math — sin() и cos(). (Math является частью стандартной библиотеки классов Java.)

Трюк с производительностью

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

Объединение полей классов и инициализация класса блоков

Вы можете объединить несколько инициализаторов полей класса и класса блоков в приложении. В листинге 6 приведен пример.

Листинг 6. Выполнение инициализации класса в порядке сверху вниз В листинге 6 объявляем и инициализируем пару полей классов ( x и y ), и пару static инициализаторов. Скомпилируйте:

Затем запустите полученное приложение:

Вы должны получить следующее:

Этот вывод показывает, что инициализация класса выполняется в порядке сверху вниз.

При компиляции класса компилятор Java сохраняет байт-код в специальный метод под названием (). Угловые скобки предотвращают конфликт имен, вы не можете объявить () метод в исходном коде , так как символы являются незаконными в контексте идентификатора. После загрузки класса, виртуальная машина вызывает этот метод перед вызовом main() (когда main() присутствует).

Давайте заглянем внутрь MCFICIB.class. Там мы увидим сохраненную информацию для полей x, temp и y:

Descriptor определяет дескриптор типа для поля виртуальной машины. Тип представлен одной буквой: I для int и D для double . Следующее частичное дизассемблирование показывает последовательность команд байт-кода для () метода. Каждая строка начинается с десятичного числа, которое идентифицирует с нуля смещение адреса последующей инструкции:

Последовательность команд от смещения 0 до смещения 2 эквивалентно следующему инициализатору полей классов:

Последовательность команд от смещения 5 по смещению 8 эквивалентно следующему инициализатору полей классов:

Последовательность команд от смещения с 11 по 80 смещения эквивалентно следующему блоку инициализации класса:

Последовательность команд от смещения 83 по смещению 88 эквивалентно следующему инициализатору полей классов:

Последовательность команд от смещения 91 через смещение 115 эквивалентно следующему блоку инициализации класса:

И, наконец, return инструкция по смещению выполнения 118 возвращается из () в той части виртуальной машины Java , который вызвал этот метод.


Автор этого материала — я — Пахолков Юрий. Я оказываю услуги по написанию программ на языках Java, C++, C# (а также консультирую по ним) и созданию сайтов. Работаю с сайтами на CMS OpenCart, WordPress, ModX и самописными. Кроме этого, работаю напрямую с JavaScript, PHP, CSS, HTML — то есть могу доработать ваш сайт или помочь с веб-программированием. Пишите сюда.

статьи IT, java, классы, теория, инициализация

Исправление ошибки JPA «java.lang.String не может быть приведен к[Ljava.lang.String;»

1. Вступление

Конечно, мы никогда не предполагали, что можем привести String к массиву _String _ в Java:

Но это оказывается распространенной ошибкой JPA. **

В этом быстром уроке мы покажем, как это происходит и как ее решить.

2. Распространенная ошибка в JPA

В JPA нередко возникает эта ошибка , когда мы работаем с собственными запросами, и мы используем метод createNativeQuery EntityManager .

Его Javadoc фактически предупреждает нас о том, что этот метод вернет список Object[] или просто Object , если запрос возвращает только один столбец.

Давайте посмотрим на пример. Во-первых, давайте создадим исполнителя запросов, который мы хотим использовать повторно для выполнения всех наших запросов:

Как показано выше, мы используем метод createNativeQuery () , и мы всегда ожидаем результирующий набор, содержащий массив String .

После этого давайте создадим простую сущность для использования в наших примерах:

И, наконец, давайте создадим тестовый класс, который вставит Message перед запуском тестов:

Теперь мы можем использовать наш QueryExecutor для выполнения запроса, который извлекает поле text нашей сущности:

Как мы видим, поскольку в запросе есть только один столбец, JPA фактически возвращает список строк, а не список строковых массивов. Мы получаем ClassCastException , потому что запрос возвращает один столбец, и мы ожидали массив.

3. Исправление ручного литья

Самый простой способ исправить эту ошибку — проверить тип объектов результирующего набора ** , чтобы избежать ClassCastException. Давайте реализуем метод для этого в нашем QueryExecutor :

Затем мы можем использовать этот метод для выполнения нашего запроса без исключения:

Это не идеальное решение, поскольку мы должны преобразовать результат в массив, если запрос возвращает только один столбец.

4. Исправление сопоставления сущностей JPA

Еще один способ исправить эту ошибку — сопоставить результирующий набор с сущностью. Таким образом, мы можем решить, как отобразить результаты наших запросов заранее ** и избежать ненужных приведений.

Давайте добавим еще один метод к нашему исполнителю для поддержки использования пользовательских сопоставлений сущностей:

После этого давайте создадим собственный _SqlResultSetMapping , чтобы отобразить набор результатов нашего предыдущего запроса в сущность Message_

В этом случае мы также должны добавить конструктор, который соответствует нашему вновь созданному SqlResultSetMapping :

Наконец, мы можем использовать наш новый метод executor для запуска нашего тестового запроса и получения списка Message :

Это решение намного чище, поскольку мы делегируем отображение набора результатов в JPA.

5. Заключение

В этой статье мы показали, что собственные запросы — это обычное место для получения этого ClassCastException . Мы также смотрели как на саму проверку типа, так и на решение проблемы путем сопоставления результатов запроса с транспортным объектом.

Как всегда, полный исходный код примеров доступен over на GitHub .

Ссылка на основную публикацию
ВсеИнструменты 220 Вольт
Adblock
detector