2017-01-17 8 views
7

У меня есть функция Oracle, которая принимает таблицу POINTS% ROWTYPE. Я хочу вызвать эту функцию из JPA, используя класс CriteriaBuilder, который имеет функцию для функций базы данных. Когда я пытаюсь построить запрос, он умирает, жалуясь, что ArrayLists не являются допустимыми параметрами запроса для функции.JPA Criteria Builder: Как передать ArrayList в функцию Oracle?

Как передать в ArrayList из JPA функцию Oracle?

Oracle Функция подписи:

CREATE OR REPLACE FUNCTION LOCATION_CONTAINS 
(
LATITUDE_IN IN DOUBLE PRECISION, 
LONGITUDE_IN IN DOUBLE PRECISION, 
points IN types_pkg.point_array, 
numPoints IN INTEGER 
) 

Oracle Тип:

create or replace package types_pkg 
as 
type point_array is table of FILTERPOINT%ROWTYPE; 
end types_pkg; 

JPA Критерии Builder вызова

List<FilterPoint> points = getPoints(location_name); 
int numPoints = points.size(); 

Expression ex = 
      cb.function("LOCATION_CONTAINS", 
      Integer.class, 
      entity.get("latitude"), 
      entity.get("longitude"), 
      cb.literal(points), 
      cb.literal(numPoints)); 

Исключение:

org.apache.openjpa.persistence.ArgumentException: 
The specified parameter of type "class middle.ware.FilterPoint" is not a valid query parameter. 

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

Мне нужно использовать построитель критериев для этой функции, это только часть запроса.

Спасибо за любую помощь.

+0

Первое что нет ни одного решения для доступа уровня пакета типа таблицы из Явы [выборка-оракул стола -типа-из-хранимой процедуры-с использованием-JDBC] (http://stackoverflow.com/questions/6410452/fetch-oracle-table-type-from-stored-procedure-using-jdbc). Secound Я думаю, что нет возможности получить доступ к любому типу User Definde (UDT), используя стандартную JPA. (Exlipse link from 2.4 имеет некоторое расширение для достижения этого). Решение, описанное @Andremoniy, работает только для типов уровня sql. –

ответ

3

Это может помочь. Как описано here, соответствующий тип Java для пользовательского типа TABLE - java.sql.Array. Я полагаю, вам нужно преобразовать свой список в этот тип. Один из возможных способов сделать это, просто вызовите methodcreateArrayOf на подключении к (смотрите также этот answer):.

Session session = (Session)em.getDelegate(); 
Connection conn = session.connection(); 
String[] data = points.toArray(new FilterPoint[points.size()]); 
java.sql.Array sqlArray = conn.createArrayOf(typeName, data); 
+0

Я получаю java.sql.SQLException: Неподдерживаемое исключение. От небольшого копания, похоже, есть другой способ сделать это в Oracle специально (OracleConnection.createARRAY()), поэтому я посмотрю на это и посмотрю, как это работает. – GuitarStrum

+1

После большего количества тестов я не могу получить свой массив со стороны JPA для слияния с типом SQL-уровня Oracle. Я следовал советам по подобным вопросам, которые я нашел (например, капитализация и использование STRUCT), но по какой-то причине он не хотел работать. Мне пришлось отложить эту часть проекта из-за крайних сроков, но, видя, что ваш ответ привел меня по правильному пути, и никакого другого ответа не было дано вам, и спасибо. – GuitarStrum