[JAVA] Typesafe Queries: do or don't?

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • Oljoner
  • Registratie: Augustus 2013
  • Laatst online: 13-06 08:46
Deze week was ik aangenaam verrast door het interessante artikel over sql queries op de frontpage.

Het schrijven van goede queries is een kunst en verdient inderdaad de nodige aandacht. Maar toch blijf ik me erover verbazen dat velen toch blijven vasthouden aan pure sql of jpql (namedqueries) (toch in de code die ik bekijk, zowel online als van directe collega's) , terwijl er nu mooie (imo) en typesafe oplossingen zijn.

Zo gebruik ik al enige tijd Spring Data Jpa in combinatie met QueryDSL.
  • Spring data jpa maakt je DAO repositories aan, dit louter aan de hand van een simpele interface die je definieerd (extend de Spring interface met een generics verwijzing naar de entity class die je wil gebruiken). Vervolgens maakt spring deze DAO automatisch aan en zijn default CRUD methodes & paging aanwezig.
  • QueryDSL maakt met behulp van classpathscanning (at compiletime) static classes aan van je entities. Deze bevatten al de informatie ivm de persistance (tabellen, kolommen,..). Deze kan je dan gebruiken om heel leesbaar (domain specific language) je queries op te bouwen.
Voorbeeld:
code:
1
2
3
4
5
6
7
//Spring data jpa repository bean (implementation constructed by spring from provided interface)
@Inject
PersonRepository personRepository;

public List<Person> getPersonsLivingIn(Country country, Set<Postcode> postcodes){
this.personRepository.findAll(QPerson.person.address().postcode.in(postcodes).and(QPerson.person.address().country.eq(country)));
}

Address is in dit voorbeeld een andere tabel, dus de .address() is impliciet een join :) .

Dit laat me ook toe om makkelijk aan "paging" te doen, om hapbare lijsten aan de UI voor te schotelen.
code:
1
2
3
4
5
6
7
8
9
10
11
{
int currentPage = 0;
int pageSize = 20;

PageRequest firstPageRequest = new PageRequest(currentPage, PageSize, new Sort(Sort.Direction.ASC, "lastName"));
Page<Person> firstTwentyPersons = this.getAllPersons(firstPageRequest, new Country("NL"));
}

public Page<Person> getAllPersons(PageRequest pageRequest, Country country){
this.personRepository.findAll(QPerson.person.address().country.eq(country), pageRequest);
}



Gebruiken jullie gelijkaardige, of misschien zelfs betere frameworks die ik niet ken? Of blijf je liever ver van deze aanpak weg? Waarom dan wel? Zijn er nadelen die ik over het hoofd zie? Of maak ik het allemaal moeilijker dan het zou moeten zijn?
Wat zijn jullie bedenkingen hierover?

Acties:
  • 0 Henk 'm!

Verwijderd

Dit topic heeft de potentie om heel religieus te worden en valt in de categorie "welke programmeertaal is de beste". Er is heel veel over te zeggen en heel weinig zonder de context te kennen.

Ja, type safe is ideaal om dubbel werk te voorkomen bij uitbreiden en onderhouden van je applicatie. Ook het automatisch aanmaken van migraties op basis van codewijzigingen is ideaal en voorkomt dubbel werk. De meeste systemen waar ik bij betrokken ben zijn complexere back-ends waarbij entities centraal staan, en een applicatie toevallig diezelfde entities mapt naar een database.

Je levert natuurlijk in op performance omdat je meestal meer data selecteert dan dat je op dat moment nodig hebt. Ook heb je weinig controle over hoe de SQL opgebouwd wordt, en zie je soms bizarre dingen voorbij komen in een SQL profiler. Met enige achtergrondkennis van ORM en de werking van het betreffende framework is dat prima netter te krijgen. Ik zweer wat dat betreft wel bij Entity Framework code first.

Wat mij betreft is de tijd van MySQL queries als string literals in PHP allang voorbij. Leuk als voorbeeldje in het artikel, maar als je dan nog zelf je queries schrijft, zet ze dan in ieder geval in een aparte data access class en niet tussen de business logic.

Acties:
  • 0 Henk 'm!

  • SPee
  • Registratie: Oktober 2001
  • Laatst online: 18:50
De JPQL in JavaEE is ook gebaseerd op Objecten. Enkel voer je dit in als String en lijkt het veel op SQL (maar is het niet).
Dit is afgekeken van Hibernate's HQL.
Waarom ik deze prefereer ten opzicht van code? Leesbaarheid!

Ik begrijp bij het lezen van de ingevoerde query (vrijwel) direct al wat de query wil doen.
Bij volledige opbouw in code, moet ik meer moeite doen om de gebruikte functies te begrijpen en waar de haakjes staan.
Daarnaast is het makkelijker om te testen. Open je DBA tool, knippen/plakken, eventueel wat kleine wijzigingen en je bent klaar. En andersom is ook makkelijker. Kopieer de query, haal er wat dingen weg en klaar.

let the past be the past.


Acties:
  • 0 Henk 'm!

Verwijderd

SPee schreef op woensdag 13 mei 2015 @ 16:25:
moet ik meer moeite doen om de gebruikte functies te begrijpen en waar de haakjes staan.
Slecht argument imo.
Daarnaast is het makkelijker om te testen. Open je DBA tool, knippen/plakken, eventueel wat kleine wijzigingen en je bent klaar. En andersom is ook makkelijker. Kopieer de query, haal er wat dingen weg en klaar.
Is afhankelijk van framework. In Entity Framework is de string representatie (die je in debugger ziet, of als je ToString()) aanroept de achterliggende SQL. En anders kijk in de DB profiler/log. Sowieso een goed idee om regelmatig een profiler mee te laten lopen om te zien wat een ORM ervan maakt.

Acties:
  • 0 Henk 'm!

  • Lethalis
  • Registratie: April 2002
  • Niet online
Tsja TS, ja en nee :P

Ik gebruik de laatste tijd nHibernate voor .Net development met C#, maar moet zeggen dat ik nog steeds erg van de eenvoud en flexibiliteit van pure SQL houdt.

Daar staat tegenover dat directe SQL refactoring moeilijker maakt en dat ik bij client development makkelijk 500ms startup tijd kan besparen door bijvoorbeeld de criteria API te gebruiken ipv HQL (hoeft de Antlr parser niet geladen te worden).

In de praktijk kies ik dus vooral voor de strongly typed criteria API (QueryOver<T>) voor eenvoudige CRUD, maar kies ik voor directe SQL voor complexe updates en queries. Met name vanwege performance en eenvoud dus.

nHibernate is gelukkig erg flexibel en staat ook native SQL toe, waardoor ik alles goed kan combineren in mijn domein services / repositories.

PS:
In zekere zin is het gebruik van QueryDSL voor JPA hetzelfde als de QueryOver<T> in nHibernate en al met al lijkt het mij een stuk fijner werken dan zelf queries schrijven wanneer dat niet nodig is.

[ Voor 13% gewijzigd door Lethalis op 15-05-2015 14:15 ]

Ask yourself if you are happy and then you cease to be.