дизайн: одни и те же логические вычисления необходимы как в базе данных, так и в Java

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

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

IDEAL_WEIGHT = (height/100) * age

Итак, мы покажем все записи, где IDEAL_WEIGHT ‹ вес, это можно сделать с помощью SQL, хранимых процедур и т. д. Суть в том, что мы фильтруем с помощью SQL. Что касается этапа «оформление результатов», это может быть, например, расчет WEIGHT_PER_INCH для каждого результата, определяемого как

WEIGHT_PER_INCH = height / weight

Эти «декоративные» вычисления могут быть намного сложнее, чем приведенные выше, и на самом деле шире, чем математические формулы — они могут включать данные, находящиеся на удаленных хостах, или полагаться на другие вычислительные устройства. Таким образом, кажется, что SQL и, возможно, PL/SQL не подходят для этой работы, скорее подходит Java, суть в том, что мы "украшаем" Java.

Выше мы упомянули фильтрацию по IDEAL_WEIGHT и декорирование по WEIGHT_PER_INCH, но что произойдет, если мы захотим сделать наоборот? (например, отфильтровать по WEIGHT_PER_INCH и декорировать по IDEAL_WEIGHT).

Вы можете сказать, что все эти вычислительные блоки должны быть одного типа — либо хранимые SQL-процедуры, либо Java-классы. Но если это процедуры SQL, они недостаточно выразительны, а если это классы Java, их нельзя использовать для быстрого поиска в базе данных.

Мой вопрос:

Существует ли чистый, широко используемый и быстрый способ вызова Java из SQL, например

Select * from Persons p where IDEAL_WEIGHT(p) < p.weight

где IDEAL_WEIGHT() — это метод Java, а не процедура SQL.

или: Есть ли какой-нибудь другой способ обойти все это?

Большое спасибо за ваши мысли.


person bloodcell    schedule 27.10.2011    source источник
comment
Вы имеете в виду конкретный продукт БД?   -  person p.marino    schedule 27.10.2011
comment
Существует ли чистый, широко используемый и быстрый способ вызова Java из SQL? Ответ на этот вопрос — хранимые процедуры. Во многих базах данных (включая DB2 и Oracle) вы можете писать хранимые процедуры на языке java. Какую базу данных вы используете? изменить: Ах, mysql. Я не уверен, что он поддерживает, но если критерием является бесплатная база данных, то PostgreSQL имеет хранимые процедуры Java, доступные через ПЛ/Ява.   -  person jmelesky    schedule 27.10.2011


Ответы (2)


Боюсь, что эта идея вообще неосуществима (тем более, если вы используете MySQL).

Были предприняты некоторые попытки сделать Java напрямую вызываемой MySQL, как вы можете видеть здесь:

Как вызвать код Java из MySQL?

но, по-видимому, это не получило дальнейшего развития (единственные ссылки, которые я нашел с помощью, по общему признанию, поверхностного поиска в Google, относятся к 2008 году).

Некоторые другие СУБД разрешали (или, может быть, все еще разрешают) использовать Java для написания хранимой процедуры. Oracle точно, а кто-то уже упоминал Postgres. Дело в том, что даже в случае Oracle (который использует встроенную JVM) вам приходится иметь дело с некоторыми ограничениями — я сомневаюсь, что вы действительно могли бы написать хранимую процедуру, которая может использовать полный набор библиотек Java или которая может вызывать удаленные службы. и т. д.

Пожалуйста, поймите, что СУБД — это своего рода «идеальный мир», который должен быть автосогласованным. Идея о том, что запрос может быть отфильтрован (или украшен) фактами из внешнего мира, противоречит сути философии СУБД (и сделает механизм запросов неспособным сделать какой-либо разумный выбор в отношении того, как выполнять запрос), поэтому я действительно сомневаюсь. это может работать любым полезным способом.

person p.marino    schedule 27.10.2011
comment
Это хороший способ выразить это :) Итак, есть ли способ удовлетворить эту потребность в быстром поиске БД, но с использованием вычислений, используемых в этом поиске в коде Java? - person bloodcell; 27.10.2011
comment
Лучше всего написать свой SQL-запрос как можно более ограничительным, а затем применить вычисления Java (на стороне клиента) к результирующему набору. Посмотрите, сможете ли вы придумать какую-нибудь эвристику, которая может быть выражена на вашем диалекте SQL, чтобы уменьшить количество возвращаемых строк перед отправкой их клиенту. - person p.marino; 27.10.2011

Являются ли данные статическими и детерминированными? Под этим я подразумеваю (1) после ввода записи (скажем, для человека), изменяется ли она либо путем обновления пользователем, либо путем периодической/автоматической корректировки, и (2) для сложных вычислений, если вы вводите данные X, будете ли вы всегда и неизбежно получать результаты Y?

В зависимости от ответов на них вы можете рассмотреть решение, подобное хранилищу данных. Когда все ваши «базовые» данные (возраст, рост, вес) вводятся, также выполняйте сложные вычисления и сохраняйте эти результаты в базе данных. При этом вы можете фильтровать свои запросы на основе этих сохраненных результатов. Это не сработает, если (по какой-либо причине) вычисления должны выполняться каждый раз при извлечении данных, и может быть неэффективным, если базовые данные изменяются со слишком большой частотой.

person Philip Kelley    schedule 27.10.2011
comment
Мои мысли точно. @bloodcell Почему вас беспокоит динамический расчет этих значений? Вы должны вычислять результаты на Java и сохранять их в базе данных только при изменении входных данных. - person meagar; 27.10.2011
comment
Пожалуйста, предположим, что статический расчет значений невозможен — расчет может иметь множество параметров конфигурации, и предварительный расчет для всех конфигураций невозможен. Кроме того, сами данные являются динамическими, а вычисления детерминированными. - person bloodcell; 27.10.2011