Jakie macie sposoby na pracę z bazą SQL'ową bez ORM'ów?

0

jw.

Sposoby, albo nawet pomysły?

1

Klepanie SQLi. Używanie prostej biblioteki, która mapuje wiersze na obiekty/struktury. Zalety: w każdym języku wygląda to tak samo, więc nie trzeba się uczyć ORMa. Wady? Czasami jest ciężko.

Warto dodać, że np. w takim go jest taka "moda", że raczej domyślnym podejściem jest klepanie SQLi na żywca https://www.reddit.com/r/golang/comments/t08oox/are_orms_considered_an_antipattern_in_go/ . Wiem, że C# ma dappera, który chyba działa na podobnej zasadzie

5

tak jak wyżej - micro ORM

np.

using (var connection = new SQLiteConnection(connString))
{
    var sql = "SELECT * FROM Customers";
    var customers = connection.Query<Customer>(sql);
    
    foreach(var customer in customers)
    {
        Console.WriteLine($"{customer.CustomerId} {customer.CompanyName}");
    }
    
    Console.ReadLine();
}
6
  1. Pisze SQLa który robi to co mi potrzebne
  2. Wyniki zamieniam w jakieś ładne obiekty domenowe
  3. Profit!
1

DataSety

2

DSle

0

W Javie - np JdbcTemplate jesli mozna - https://www.baeldung.com/spring-jdbc-jdbctemplate

W COBOLu na iSeries mozna sie bylo dostac do DB2 przez file-io, ale to koncertowo zrypany interfejs.

2

Bez ORM też trzeba pamiętać o podatności SQL injection, przed którą w pewnym stopniu ORM chroni, poprzez:

  • Zapytania parametryzowane
  • Walidacja typów danych: spr czy odpowiedni format
  • Hardening bazy danych
2
bakunet napisał(a):

Bez ORM też trzeba pamiętać o podatności SQL injection, przed którą w pewnym stopniu ORM chroni, poprzez:

  • Zapytania parametryzowane

Słabych języków używasz :P np w Javie zapytania parametryzowane są częścią biblioteki standardowej, bo Java jest super :D

Jak sobie radzę bez ormów? Świetnie, używam bibliotek do typowanego SQLa:

  • Dla Javy - JOOQ
  • Dla Scali - Slicka. Slick robi jeszcze podstawowe mapowania z tabel na obiekty
0
KamilAdam napisał(a):

Słabych języków używasz :P np w Javie zapytania parametryzowane są częścią biblioteki standardowej, bo Java jest super :D

To była tylko ogólna uwaga ;p Poza tym C# też posiada narzędzia do parametryzacji zapytań. Nie wiem czy w Javie to działa podobnie?

0

Czyli jedyną alternatywą jest jednak pisanie SQLI?

4

komponenty jak w Delphi

1

@TomRiddle:

TomRiddle napisał(a):

Czyli jedyną alternatywą jest jednak pisanie SQLI?

W .NET jest SqlKata, taki fajny query builder. Pewnie w innych językach da się znaleźć podobne biblioteki.

Poza tym zawsze można klepać widoki bazodanowe i je wołać prostymi selectami

0

Skarlały obiekt "record", de facto implementujący map<String,Object>, czasem z referencją na rodzicielski obiekt "metadane"
ALE to w szczególnych okolicznościach, np zakres kolumn jest określany dynamicznie na wdrożeniu a nie kompilacji (chociaż nie rani palców jak zakres jest w miarę stały)

To na poziomie religii wzorców się jakoś nazywa Xxxx Record Yyyy - ale zapomniałem jak.

To sie dobrze sprzęga z języków kompilowanych C_++/ C#/ Java do dynamicznych (jeśli w nich implementowane sa biznesowe reguły na wdrożeniu)

2
TomRiddle napisał(a):

Czyli jedyną alternatywą jest jednak pisanie SQLI?

W Javie w JOOQ można pisać SQLe ale tak "lepiej", DSLem.
Robisz schemę (ja najczęściej się spotykam z migracjami Flyway), podczas kompilacji/budowania/mvn generate-sources TestCointainer stawia prawdziwą bazę danych, na tej bazie wykonywane są migracje. Następnie jest jakiś generator, który łączy się do tej bazy i generuje klasy, normalnie generuje entity.
W kodzie możesz robić SQL kodem javowym

context.update(Author.AUTHOR)
  .set(Author.AUTHOR.FIRST_NAME, "David")
  .set(Author.AUTHOR.LAST_NAME, "Brown")
  .where(Author.AUTHOR.ID.eq(1))
  .execute();

Klasa Author jest właśnie klasą wygenerowaną przez JOOQ. Sama biblioteka potrafi przemapować wynik zapytania na prostą klasę albo rekord, czasami trzeba niestety ręcznie maper zrobić, ale jest to bardzo proste.
Generator JOOQ poza prostymi encjami rozpoznaje też klucze obce (możesz zrobić .join(OTHER_TABLE).on(SOME_FK_KEY) gdzie SOME_FK_KEY to jakiś public static). Wykrywa funkcje więc możesz jak zrobisz własną funkcję/widok/trigger to do wszystkiego masz dostęp z kodu i możesz wywołać.

Jak zmienią się skrypty migracyjne to trzeba przegenerować kod i wiecznie masz aktualny. Efektem tego jest, że jak zmieni się schema w sposób niekompatybilny wstecznie to kod się przestanie kompilować.

Generalnie nie widziałem nic lepszego w życiu w Javie, działa świetnie. ale powstaje poro kodu w porównaniu do hibernate (przy czym w porównaniu do hibernate wiadomo jakie zapytanie jest wykonywane)

0

No już widzę jak czymś takim napiszesz np INSERT ... RETURNING

0

Jak już muszę to najczęściej zamykam wszystko w procedury i widoki oraz robię użytkowników o odpowiednich prawach (wielu), z prawami np. do wykonania procedury, ale już bez praw do tabel, która ta procedura trzepie, a to sama procedura otrzymuje prawa do tabel. Pozwala to zachować bezpieczeństwo i jako tak nie robi syfu w kodzie i jest hermetyzacja w procedurach. Z drugiej strony to rozproszenie warstwy mapowania danych na dwa systemy... ale coś za coś - albo składamy SQLe w kodzie, albo wypychamy to do procedur i rozpraszamy. Ewidentnie brakuje tutaj warstwy abstrakcji którą jest... ORM. Jeśli nie pełen ORM to może jakiś Dapper ale i tak unikał bym składania zapytać w kodzie i dawaniu userom praw do całych tabel.

0
TomRiddle napisał(a):

Czyli jedyną alternatywą jest jednak pisanie SQLI?

Dla mnie ?
Dwoiście ...albo SQL-e i odebrane dane mapować na "jakieś" obiekty. Argument "za" to optymalizowanie sobie tych SQL-i w narzędziu typowo SQL-owym (Managamentn studio w MS), i wklejanie do kodu w języku. w C# chyba Dapper mi pasował, JDBI w Javie
Co na pewno nie? Pseudo DSL kompilowany niby do baz danych, ale pełne stringów z nazwami pól (Criteria JPA i okolice)

Zawsze życzliwie próbuję 100% type safe jak JOQQ ... ale nie znalazłem swojego Graala, w każdym coś na "nie"
Np w rodzinie JPA + CDI było takie Delta Spike, 100% type safe, ale runtime do tego to jakiś koszmar, kruche jak domek z kart

KamilAdam napisał(a):

Słabych języków używasz :P np w Javie zapytania parametryzowane są częścią biblioteki standardowej, bo Java jest super :D

Parametry przez pytajnik ? Koszmar. To może 25 lat temu było nowoczesne.
Tylko nazwane parametry, to oczywiście jest wspierane w Javie, ale w libkach a nie standardzie

1

NoSQL, jak nie ma relacji, to nie ma potrzeby (ani możliwości) używania ORM. Swoją drogą, im dłużej myślę, tym mniej widzę powodów do używania ORM+SQL. W większości przypadków, albo potrzeba przechowywać dane nierelacyjne, albo faktycznie te relacje i ich elastyczność jest potrzebna i ORM przestają mieć większy sens. Pozostają systemy, które muszą połączyć obiektowość z elastyczną analityką i zrobić to koniecznie w oparciu o pojedynczą bazę danych.

0

E tam. Elastyczność prowadzi do degradacji zbioru danych a te sztywne mechanizmy z bazy jak typy, relacje, checki, klucze obce przenosi się do serwisu o robisz to ręcznie.

0

@pieczarek: Chyba odpisałeś na mój post.
Elastyczność oferowana przez RDBMS pozwala na wiele, co nie oznacza, że należy z tego "wiele" korzystać zawsze. Bazy danych to szerokie zagadnienie z masą teorii i jest też sporo miejsc gdzie można coś zrąbać (np. pominąć nałożenie constraints o których piszesz). Elastyczność o której myślę, to to, ze da się na pojedynczej bazie danych zrobić zarówno "aplikację", jak i dorobić do tego analitykę, za pomocą mniej, lub bardziej pokręconego zapytania, a w przypadku NoSQL zwykłe sumowanie wartości, może zaskoczyć rozmachem.

0

Query buildery, w moim przypadku Ecto. Daje nakładkę na surowe SQLe, która bardziej przypomina QUEL dzięki czemu zapytania wyglądają logiczniej i łatwiej się je czyta.

6

Zastanawiam dlaczego ludzie tak boją się tego "raw" SQLa w ich kodzie i napisania prostych mapperów do obiektów, a zamiast tego pakują te ORMy do każdego nowego projektu. Obstawiam, że wynika to z tego, że tak ich nauczono od lat juniorskich kilkanaście lat temu, gdy użycie ORMa było czymś cool. Dużo programistów do lat seniorskich dalej bezmyślnie podąża tymi zasadami wpojonymi im za lat młodości gdy przeczytali clean code i doznali oświecenia - i tym sposobem kierują się prostymi zero jedynkowymi zasadami bez chwili refleksji po co im to w zasadzie potrzebne. Albo druga opcja - poświęcili kilka lat na doktoryzowanie się w ORMach i nie na rękę im, żeby ta nauka poszła w piach.

Ja od kiedy nie pracuje z ORMem (Hibernate) a używam prostego wrapera na jdbc (JDBI - polecam, lepsze od jooq bo prostsze) - czuję się znacznie lepiej. Przestałem łysieć, zrobiłem 20kg czystej masy mięśniowej, lepiej się wypróżniam, żona i kochanki też zadowolone bo libido w górę. Naprawdę nie warto tracić życia na ORMy!

0
toSieUda napisał(a):

Zastanawiam dlaczego ludzie tak boją się tego "raw" SQLa w ich kodzie i napisania prostych mapperów do obiektów, a zamiast tego pakują te ORMy do każdego nowego projektu. Obstawiam, że wynika to z tego, że tak ich nauczono od lat juniorskich kilkanaście lat temu, gdy użycie ORMa było czymś cool. Dużo programistów do lat seniorskich dalej bezmyślnie podąża tymi zasadami wpojonymi im za lat młodości gdy przeczytali clean code i doznali oświecenia - i tym sposobem kierują się prostymi zero jedynkowymi zasadami bez chwili refleksji po co im to w zasadzie potrzebne. Albo druga opcja - poświęcili kilka lat na doktoryzowanie się w ORMach i nie na rękę im, żeby ta nauka poszła w piach.

Ja od kiedy nie pracuje z ORMem (Hibernate) a używam prostego wrapera na jdbc (JDBI - polecam, lepsze od jooq bo prostsze) - czuję się znacznie lepiej. Przestałem łysieć, zrobiłem 20kg czystej masy mięśniowej, lepiej się wypróżniam, żona i kochanki też zadowolone bo libido w górę. Naprawdę nie warto tracić życia na ORMy!

Myślę że to wynika z jakiegoś takiego dziwnego przekonania że SQL jest niżej poziomowy, a ORM wyżej poziomowy - że niby takie bardziej cywilizowane podejście. Nie mówiąc już o tym że jak ktoś nie rozumie OOP, a jednocześnie wie że OOP dobre; to sobie używa takiego ORM i jest przekonany że ORM to faktycznie - Object Relational Mapping.

4

@toSieUda: @TomRiddle

rozważaliście opcje że po prostu szybciej się developuje?

5

@1a2b3c4d5e: rozważaliście opcje że po prostu szybciej się developuje?

To jest właśnie największe kłamstwo ORMów: niby oszczędzają czas ale wcale tak nie jest. Np. w takiej Javie jedyną osobą która dobrze się posługuje najpopularniejszym ORMem czyli Hibernatem jest Vlad Mihalcea. Szanse na to, że trafisz do zespołu gdzie akurat będzie taki Vlad są dość małe. Szanse na to, że twoja aplikacja będzie prostym CRUDem też są dość małe. Dlatego prędzej czy później o wiele więcej czasu poświęcasz na dokształcaniu się i debugowaniu ORMa (no chyba, że już w tym siedzisz 10 lat, ale obiektywnie też ten czas trzeba doliczyć do średniego czasu developmentu). A to wszystko po to, żeby oszczędzić te 15 minut na napisanie trywialnego mapowania. Jak dla mnie to dość słaby kompromis.

2

Tak ORMów trzeba się nauczyć, a czasem faktycznie coś zdebugować

pytanie jak często?

Jeżeli raz na 50 querek muszę poszukać czegoś na SO, ale za to z kodu wywalam 10 ton brzydkiego SQLa i w zamian dostaje LINQ które już na etapie kompilacji daje mi jakieś safety (nie w 100% bo czasem dana operacja może nie być możliwa do przełożenia na SQL)

to może jednak się to opłaca?

Np. w takiej Javie jedyną osobą która dobrze się posługuje najpopularniejszym ORMem czyli Hibernatem jest Vlad Mihalcea

to słabo jeżeli tylko 1 osoba potrafi ;)

1

ORM ponieważ składa się z metod, a nie stringów - dla niektórych sprawia wrażenie bardziej przemyślanego, dojrzałego rozwiązania. Tak jednak nie jest.

1

, ale za to z kodu wywalam 10 ton brzydkiego SQLa i w zamian dostaje LINQ które już na etapie kompilacji daje mi jakieś safety (nie w 100% bo czasem dana operacja może nie być możliwa do przełożenia na SQL)

No a ja mogę mieć type safety z JOOQ.

create.select()
      .from(AUTHOR.as("a"))
      .join(BOOK.as("b")).on(a.ID.eq(b.AUTHOR_ID))
      .where(a.YEAR_OF_BIRTH.gt(1920)
      .and(a.FIRST_NAME.eq("Paulo")))
      .orderBy(b.TITLE)
      .fetch();

1 użytkowników online, w tym zalogowanych: 0, gości: 1