LINUX.ORG.RU

PL/Java как оно?

 ,


0

1

Сейчас прилаживаю его к своему ПО на PostgreSQL 9.5, полгода назад вышла новая версия с аннотациями для автоматической генерации DDL. По оверхеду на одно соединение +11Мб (итого ~13Мб), на первый взгляд всё шустренько работает.

★★★★★

Последнее исправление: foror (всего исправлений: 2)

Ответ на: комментарий от Legioner

Чтобы было похоже на концепцию RethinkDB (кстати, которая - всё, привет хипстерам).

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

К тому же в данном случае к БД будут подключаться в обход официального клиента, а потому нужен сложный набор правил, чтобы поддерживать консистентность БД. Писать это на PL/!Java означает дублирование кода предметной области. А с помощью PL/Java у меня единный код предметной области, как на клиенте, так и на БД, без дублирование классов и бизнес логики.

foror ★★★★★
() автор топика
Последнее исправление: foror (всего исправлений: 1)
Ответ на: комментарий от foror

Код в БД это порочная концепция. В БД могут быть ограничения в декларативном виде в разумном количестве. В БД может быть код, который просто не может работать вне БД из-за производительности, это необходимое зло (правда нужно такое ну очень редко). И если вдруг в БД кому-то упёрлось сувать код, то этот код должен быть на языке, в котором интегрированы SQL-запросы и работа с ними. Java к этим языкам не относится.

Я не просто так говорю, я видел и работал с DB2, в которой куча хранимок была написана на Java. Это было ужасно. Лучше так не делать.

Legioner ★★★★★
()
Ответ на: комментарий от Legioner

Почему порочная концепция? Мне нравится, в некоторой степени, концепция RethinkDB и не только мне.

я видел и работал с DB2, в которой куча хранимок была написана на Java

Ну видимо эти хранимки были написаны отдельными файлами и никак не шарились с общим кодом в IDE? В моём случае у меня есть классы в Eclipse, в некоторых из них есть статичные методы с аннотацией @Function/@Trigger.

Мой ORM фреймворк автоматически подхватывает данные классы и статичные методы, после чего маппит их на таблицы (добавляет констрейнты, тригеры из статичных методов), домены (класс только с одним полем и логикой для проверки этого поля) или композитные типы (если я не хочу маппить класс на таблицу, например javax.money).

Т.е. все функции/тригеры лежат прямо в классах, с которыми я тут же работаю на клиенте-БД/сервере-http обрабатывая http запросы. А не в каких-то левых файлах, в которых IDE в лучшем случае подсветит синтаксис.

А потому работает рефакторинг и автодополнение. Очень удобно. Примерно вот так:

public class Inn {
    
    public enum message {
        bad_checksum,
        bad_length;
    }    

    private static final int[] MULT_N1 = { 7, 2, 4, 10, 3, 5, 9, 4, 6, 8 };
    private static final int[] MULT_N2 = { 3, 7, 2, 4, 10, 3, 5, 9, 4, 6, 8 };
    private static final int[] MULT_N =  { 2, 4, 10, 3, 5, 9, 4, 6, 8 };      

    public final long value;
    
    public Inn(long value) {
        this.value = value;
    }

    @Function(schema="check", name="inn")
    public static boolean check(long value) throws SQLException {
        int length = (int)(Math.log10(value) + 1);
        boolean valid = false;
        
        switch (length) {
        case 12:
            int n1 = getChecksum(value / 100, MULT_N1);
            int n2 = getChecksum(value / 10, MULT_N2);
            valid = value % 10 == n2 && (value / 10) % 10 == n1;
            break;
            
        case 10:
            int n = getChecksum(value / 10, MULT_N);
            valid = value % 10 == n;
            break;
        default:
            throw new SQLException(message.bad_length.name());
        }
        
        if (valid)
            return true;
        
        throw new SQLException(message.bad_checksum.name());
    }
    
    private static int getChecksum(long value, int[] multipliers) {
        int checksum = 0;
        
        for (int i = multipliers.length - 1; i >= 0; i--) {
            checksum += (value % 10) * multipliers[i];
            value /= 10;
        }
        
        return (checksum % 11) % 10;
    }     
}

В БД будет создан домен:

CREATE DOMAIN public.inn
  AS bigint
  CONSTRAINT inn_check CHECK (check.inn(VALUE));

Теперь моя ORM может маппить всё это дело, например так:

public class Customer {
    private Inn inn;
}

CREATE TABLE public.customer
(
  inn inn
)

foror ★★★★★
() автор топика
Последнее исправление: foror (всего исправлений: 2)
Ответ на: комментарий от foror

RethinkDB (кстати, которая - всё, привет хипстерам).

предпоследний твит от них содержит солово awesome. символiчно.

mos ★★☆☆☆
()
Ответ на: комментарий от Legioner

Ну и самое интересное в моём подходе в возможности одним флагом в конфиге убрать все проверки из БД и делать их на уровне ORM. Это будет использоваться для будущей адаптации фреймворка под android+sqlite.

foror ★★★★★
() автор топика
Ответ на: комментарий от foror

Ну и самое интересное в моём подходе в возможности одним флагом в конфиге убрать все проверки из БД и делать их на уровне ORM

У нас на работе тоже свой горе-фреймворк написали с такой хренью, теперь все плюются и исправляют кучу багов.
Если БД может сделать какую-то проверку, то именно она ее и должна делать, а не код (который выше уровнем).

http://programmers.stackexchange.com/questions/171024/never-do-in-code-what-y...

«Ну и самое интересное в моём подходе в возможности одним флагом в конфиге превратить базу в неконсистентное говно.»

kovrik ★★★★★
()
Последнее исправление: kovrik (всего исправлений: 2)
Ответ на: комментарий от foror

Чтобы было похоже на концепцию RethinkDB (кстати, которая - всё, привет хипстерам).

а чего с ней случилось? а то новости не читаю ;/

umren ★★★★★
()
Ответ на: комментарий от kovrik

Если БД может сделать какую-то проверку, то именно она ее и должна делать, а не код (который выше уровнем)

У меня так и сделано. Просто если переходишь на обрезок типа sqlite, то можно пилить под неё почти в том же стиле как и под postresql. С поддержкой композитов/тригеров/функций/констрейнтов. Но конечно с определенными ограничениями.

Или если пилишь веб-сайт и не хочется нагружать БД лишними проверками (PL/Java функциями), то валидацию доменов можно вынести на уровень ORM.

Я не пытаюсь заместить вещи типа:

joins - codewise it'd require complex array manipulation
filtering data (where) - codewise it'd require heavy inserting and deleting of items in lists
selecting columns - codewise it'd require heavy list or array manipulation
aggregate functions - codewise it'd require arrays to hold values and complex switch cases
foreign key integrity - codewise it'd require queries prior to insert and assumes nobody will use the data outside app
primary key integrity - codewise it'd require queries prior to insert and assumes nobody will use the data outside app
foror ★★★★★
() автор топика
Ответ на: комментарий от Legioner

И если вдруг в БД кому-то упёрлось сувать код, то этот код должен быть на языке, в котором интегрированы SQL-запросы и работа с ними.

иногда хочется странного: wsdl-клиент, забрать почту по имапу, что-то забрать с ftps... ынтерпрайз он такой, суровый...

Rastafarra ★★★★
()
Ответ на: комментарий от foror

с помощью PL/Java у меня единный код предметной области, как на клиенте, так и на БД, без дублирование классов и бизнес логики.

раньше такая радость называлась application server вроде, уже не в моде?

вынеси в веб/рест/всдл, будет щясье.

Rastafarra ★★★★
()
Ответ на: комментарий от Rastafarra

раньше такая радость называлась application server вроде, уже не в моде?

Уже не помню как там было раньше. Ибо был юн и всё не запомнил. Заполнил лишь, что J2EE это такое страшное легаси и тормозилище, что аж жуть. Но «вынеси в веб/рест/всдл, будет щясье» это куча лишнего кода как раз про "http://programmers.stackexchange.com/questions/171024/never-do-in-code-what-y...

Я пилю данный фреймворк под десктопное/планшентное приложение, а не под веб-сайты. База данных не будет спрятана за сервер-сайдом и обрабатывать +100500 одновременных соединений.

В моём случае (случае десктопного приложения) БД может быть изменена сторонними приложениями. А потому мне нужна гарантия, что БД останется консистентной, когда в ней начнут копаться сторонние самописные утилиты/приложения.

Даже если делать SaaS, то масшатбируется всё очень просто, т.к. на группу пользователей одного приложения, поднимается новая БД. И размещай её хоть на дедике, хоть в виртуалке - в зависимости от потребностей.

foror ★★★★★
() автор топика
Ответ на: комментарий от foror

В моём случае (случае десктопного приложения) БД может быть изменена сторонними приложениями.

как будто что-то хорошее...

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

ты, кстати, уже придумал как запретить простой select для чужих данных? :)

масшатбируется всё очень просто, т.к. на группу пользователей одного приложения, поднимается новая БД.

мне кажется кто-то из нас своеобразно понимает масштабируемость :)

Rastafarra ★★★★
()
Ответ на: комментарий от Rastafarra

ты, кстати, уже придумал как запретить простой select для чужих данных?

https://www.postgresql.org/docs/9.6/static/ddl-rowsecurity.html

бд на хранимках --- это жесткая привязка к языку

Все моё приложение пишется на Java, никто же не бухтит, что Линух привязан к Си? Хочешь изменять приложение, изучай язык на котором оно создано.

Или если бизнес логику выбросить из БД от этого будет легче понять взаимосвязи между таблицами? Без знания бизнес логики, которая всегда пишется на определенном языке? Так можно тогда сделать проще, в постгресе например можно отключить все тригеры/констрейнты и даже внешние ключи и работать c БД как со sqlite.

плохо контролируемый мрак

Где там мрак? Наоборот хрен разрушишь консистентность если залезешь кривыми ручками. Но в прочем да, с тем подходом когда хранимки лежат отдельно от приложения - это мрак. Но у меня приложение прозрачно пересекается с хранимками.

как минимум средств разработки нормальных нет

Еще раз повторяю у меня приложение прозрачно пересекается с хранимками, выше приводил пример. В eclipse для кода хранимок работает автодополнение, рефакторинг, дебаг и все остальное, что работает для обычного Java кода приложения. Запускается PL/Java на той же JVM, что и приложение.

В Java коде все статичные методы помеченные как @Function/@Trigger/@MappedUDT автоматически преобразуются в код PL/Java. Преобразования композитных типов делается также автоматически через java.sql.SQLData интерфейс. Я ничего не пишу руками - PL/Java код генерируется автоматически. Мне в итоге нужно просто выполнить функцию:

SELECT sqlj.install_jar(
  'file:'
  '/buildroot/pljava-examples/target/pljava-code-1.5.0.jar',
  'examples', true);
foror ★★★★★
() автор топика
Последнее исправление: foror (всего исправлений: 2)
Ответ на: комментарий от Deleted

Жалко то как. А у нас новый проект на RethinkDB идет. Что теперь на гнилую монгу прыгать ? Пожалуй лучше на CouchDB...

abc
()
Ответ на: комментарий от abc

Так а сообщество стухло что-ли? Не тянут хипстеры Си++ или на чем она там написана?

foror ★★★★★
() автор топика
Ответ на: комментарий от foror

https://www.postgresql.org/docs/9.6/static/ddl-rowsecurity.html

However, there is a race condition here.

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

если бизнес логику выбросить из БД от этого будет легче понять работу приложения без знания языка на котором оно написано?

да. это называется API и документация, хоть диаграммами нарисуй последовательность get-set-update-delete и клиента можно будет нарисовать даже на баше с курлом. круто, да?

и да, не надо писать на клиенте селекты с джойнами, не надо знать структуру БД. у тебя получается очень сильное связывание. ты можешь выкатить +/- стабильное АПИ, которое меняется раз в месяц, а внутри свою базулю крутить по 10 раз в день, ломая и меняя таблицы и связи.

Наоборот хрен разрушишь консистентность если залезешь кривыми ручками.

update легко прилетает соседу по его id-шнику и превед ))

Rastafarra ★★★★
()
Ответ на: комментарий от foror

в постгресе например можно отключить все тригеры/констрейнты и даже внешние ключи и работать c БД как со sqlite.

это другая крайность, которая ведет к тому что постгрес будет работать медленно и не эффективно.

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

но это если у тебя есть прослойка в виде аппликухи, если же у тебя прямой доступ в БД, всех клиентов надо быренько переписать ))

Rastafarra ★★★★
()
Последнее исправление: Rastafarra (всего исправлений: 1)
Ответ на: комментарий от Rastafarra

и дальше sql-магия, которую в обязательном поряде должен знать и понимать каждый

Нет там никакой магии, просто выучи как работает данный инструмент и будет всё работать как тебе нужно.

Никто же не плачется, что нужно понимать модель памяти Java, если хочешь разрабатывать многопоточный код? А там еще больше путей прострелить себе ногу.

и да, не надо писать на клиенте селекты с джойнами, не надо знать структуру БД

Так и скажи, что предлагаешь REST. Ну этого есть как плюсы, так и свои минусы.

ты можешь выкатить +/- стабильное АПИ, которое меняется раз в месяц, а внутри свою базулю крутить по 10 раз в день

А если хочу крутить АПИ по 10 раз в день? Спросишь зачем? Я спрошу, а зачем мне крутить базулю по 10 раз в день? Короче шило на мыло. Со своими плюсами и минусами.

Для веб-сайта или какого-то сервиса это может и верный подход. А для десктопного ПО это лишний оверхед.

foror ★★★★★
() автор топика
Последнее исправление: foror (всего исправлений: 1)
Ответ на: комментарий от foror

А для десктопного ПО это лишний оверхед.

Просто потому-что я не контролирую БД на десктопе/стороннем сервере. Я могу хоть всё REST API обложить, а местный аникей всё равно залезет в БД напрямую - потому что может.

foror ★★★★★
() автор топика
Последнее исправление: foror (всего исправлений: 1)
Ответ на: комментарий от foror

Нет там никакой магии, просто выучи как работает данный инструмент и будет всё работать как тебе нужно. Никто же не плачется, что нужно понимать модель памяти Java, если хочешь разрабатывать многопоточный код? А там еще больше путей прострелить себе ногу.

и у тебя клиент внезапно становится в 2 раза сложнее: мало того что надо знать язык на котором ты пишешь клиента, так надо еще и знать тонкости sql-я конкретно и не просто sql-я, а sql-я для постгреса. вторая проблема мало того чтоб совершенно не очевидна, так еще и взялась из совершенно ровного места.

Так и скажи, что предлагаешь REST.

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

А если хочу крутить АПИ по 10 раз в день? Спросишь зачем? Я спрошу, а зачем мне крутить базулю по 10 раз в день?

у тебя может поменяться структура таблиц, способ хранения, сама базуля. но get_cool_request и save_my_cool_data будет все тот же.

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

конечно апи тоже может и будет меняться, но обычно на это закладываются и делают что-то вроде /api/v1/my_cool_request и /api/v2/my_cool_request

с табличками такое плохо прокатывает.

для десктопного ПО это лишний оверхед.

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

но тебе на это пофиг, я понял :)

Rastafarra ★★★★
()
Ответ на: комментарий от Rastafarra

Стандартная работа это один-два клиента к БД. Но периодически может и больше подключаться.

foror ★★★★★
() автор топика
Ответ на: комментарий от Rastafarra

и у тебя клиент внезапно становится в 2 раза сложнее: мало того что надо знать язык на котором ты пишешь клиента, так надо еще и знать тонкости sql-я конкретно и не просто sql-я, а sql-я для постгреса

Так мне нужен row security так или иначе, это не сервер-сайд где БД спрятана. Здесь клиенты имеют логин/пароль для доступа к БД напрямую.

И я же не выбирал для разработки какой-нибудь D и Informix, который знают 2.5 человека. Я выбрал очень популярные в мире стеки технологий. Java и Postgres с большим комьюнити и кучей документации на русском языке. Если заказчику потребуется доработка, то он найдет программистов даже в провинции.

foror ★★★★★
() автор топика
Последнее исправление: foror (всего исправлений: 2)
Ответ на: комментарий от foror

И я пока не вижу смысла посередине ставить REST, так как это так или иначе лишний код и много лишней работы. Сделать row security для меня будет проще.

foror ★★★★★
() автор топика
Последнее исправление: foror (всего исправлений: 2)
Ответ на: комментарий от foror

Стандартная работа это один-два клиента к БД.

у меня похоже ынтерпрайз головного мозга.

клиенты имеют логин/пароль для доступа к БД напрямую.

все равно лазить в нее грязными руками --- порочная практика. обычный подход: что-то мешает update-иться? триггерок? нахер с поля. и весь твой карточный домик рушится ровно так же.

Rastafarra ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.