WN

WN (https://www.wn.se/forum/index.php)
-   Serversidans teknologier (https://www.wn.se/forum/forumdisplay.php?f=4)
-   -   table joins och objektmodell (https://www.wn.se/forum/showthread.php?t=1046476)

danjel 2011-02-11 12:28

table joins och objektmodell
 
Hur brukar ni hantera table joins i samband med att en objektmodell används och man ska visa data.
Exempelvis om har en "User" klass (som mappar mot en User tabell) för att representera en användare.
Typiskt är att man vill visa data som inte finns i User tabellen och istället hämta detta data via en join, t.ex vilket land en användare tillhör.
Det går ju att lösa med denna princip

<?php

class UserRepository{

public getUsers()
{
$result = mysql_query("select users.*, country.name as CountryName
from users left join user.countryId on country.id");

$objectArray = array();

while ($row = mysql_fetch_array($result)) {
$user = new User();
$user->UserName = $row['username'];
$user->CountryName = $row['CountryName'];
$objectArray[] = $user;
}
return $objectArray;
}

}

?>

Dock känns det inte helt klockrent. Det blir ju b.la beroenden till olika tabeller.
Finns det någon best practice eller tutorial kring detta?


Jag är medveten om ORM , men tänkte främst på en lösning utan att implementera den tekniken.

dAEk 2011-02-11 20:03

Citat:

Ursprungligen postat av danjel (Inlägg 20392514)
Dock känns det inte helt klockrent. Det blir ju b.la beroenden till olika tabeller.

Är det verkligen ett problem? Ett alternativ kan vara att skapa en vy om man inte vill blanda in tabellberoenden i koden.

Adestro 2011-02-14 20:48

Försöker du lagra objekt med många statiska egenskaper och lite relationer i ett RDBMS kanske du istället ska titta på NoSQL-databaser som MongoDB.

danjel 2011-02-15 08:51

Citat:

Ursprungligen postat av dAEk (Inlägg 20392592)
Är det verkligen ett problem? Ett alternativ kan vara att skapa en vy om man inte vill blanda in tabellberoenden i koden.

Det funkar väl rent praktiskt i de flesta fall men känns fel vad gäller objekt/system design.
En grej är att man vill att klassen ska mappa exakt mot tabellen men om man lägger till egenskaper i klassen som inte finns i tabellen så bryter man den principen.

Jag funderar nu istället på att börja köra utan joins så mycket det går och köra lazy loading för att ladda relaterade objekt,dvs mer likt ett ORM.
Vad tror ni om prestanda/skalbarhet vad gäller ett (nästan) "join fritt" system?
Det skulle bli väsentligt fler queries, vilket kan väl tänkas sänka prestanda generellt.
Dock så kan jag tänka mig att det skalar bättre i vissa fall när det blir så mycket data att joins börjar bli sega(?)

Citat:

Ursprungligen postat av Adestro
Försöker du lagra objekt med många statiska egenskaper och lite relationer i ett RDBMS kanske du istället ska titta på NoSQL-databaser som MongoDB.

Ja det kanske är ett alternativ ,ska kika på det. Tack.

Magnus_A 2011-02-15 10:31

Du kan ju mappa till tabellerna med dina modeller och om du har behov av en join så gör du en ny mappning där du extendar den mappningen du redan har.

Då stämmer mappningen med tabeller och med joins.

dAEk 2011-02-15 20:58

Citat:

Ursprungligen postat av danjel (Inlägg 20393006)
Det funkar väl rent praktiskt i de flesta fall men känns fel vad gäller objekt/system design.
En grej är att man vill att klassen ska mappa exakt mot tabellen men om man lägger till egenskaper i klassen som inte finns i tabellen så bryter man den principen.

Ja, jag håller med. Det är ju bättre att bryta upp det och separera entiteterna. Men är det det du vill göra förstår jag inte varför du undviker en ORM. Det är ju det en ORM gör - mappa entiteter mot en datastruktur - men om du vill uppfinna hjulet på nytt så...

Citat:

Ursprungligen postat av danjel (Inlägg 20393006)
Jag funderar nu istället på att börja köra utan joins så mycket det går och köra lazy loading för att ladda relaterade objekt,dvs mer likt ett ORM.
Vad tror ni om prestanda/skalbarhet vad gäller ett (nästan) "join fritt" system?
Det skulle bli väsentligt fler queries, vilket kan väl tänkas sänka prestanda generellt.
Dock så kan jag tänka mig att det skalar bättre i vissa fall när det blir så mycket data att joins börjar bli sega(?)

I dom flesta fallen är inte joins såpass långsamma att man behöver byta ut dem mot något annat. Kanske indexeras inte tabellerna som de borde. Har du kollat vad query analyzern säger? Kanske kan lazy loading vara lösningen på ett par områden, kanske behöver du platta till andra. Vill du veta vad som skalar bäst får du mäta - ändra och mäta igen. Tror inte att någon här kan ge dig ett svar på den frågan. Att skippa joins helt och hållet i en RMDBS måste anses vara ganska radikalt. Ska du ändå göra det - se till att det är befogat. Att anta det ena eller det andra är sällan bra i sådana här sammanhang.

Har du tittat på någon form av cache? Att bara cacha dom tyngsta frågorna kan avlasta databasen en hel del.

danjel 2011-02-17 13:20

Citat:

Ursprungligen postat av dAEk (Inlägg 20393164)
Ja, jag håller med. Det är ju bättre att bryta upp det och separera entiteterna. Men är det det du vill göra förstår jag inte varför du undviker en ORM. Det är ju det en ORM gör - mappa entiteter mot en datastruktur - men om du vill uppfinna hjulet på nytt så...
.

Hmm ja precis det börjar likna ett ORM..tanken var att jag gärna vill undvika ORM system och använda egna klasser för att behålla flexibilitet.

Citat:

Ursprungligen postat av dAEk (Inlägg 20393164)
I dom flesta fallen är inte joins såpass långsamma att man behöver byta ut dem mot något annat. Kanske indexeras inte tabellerna som de borde. Har du kollat vad query analyzern säger? Kanske kan lazy loading vara lösningen på ett par områden, kanske behöver du platta till andra. Vill du veta vad som skalar bäst får du mäta - ändra och mäta igen. Tror inte att någon här kan ge dig ett svar på den frågan. Att skippa joins helt och hållet i en RMDBS måste anses vara ganska radikalt. Ska du ändå göra det - se till att det är befogat. Att anta det ena eller det andra är sällan bra i sådana här sammanhang.

Har du tittat på någon form av cache? Att bara cacha dom tyngsta frågorna kan avlasta databasen en hel del.

Alltså jag har inte upplevt problem med joins och prestanda och vill byta ut dem pga det, tanken är endast att det ger bättre systemdesign utan dem och snabbare att få upp ett relativt enkelt system. Men att helt skippa joins är inget jag tänkt..
Jag tror t.o.m en del ORM kör lazy load per default och då enligt principen en sql fråga per objekt, så det är väl kanske inte så extremt nuförtiden.

Adestro 2011-02-17 14:11

Om du vill ha en flexibel datamodell och "snabbt få upp ett relativt enkelt sytem", kolla på MongoDB! Du verkar ju ändå vara inne på denormalisering. MongoDB är helt schemaless och syntax är 100% JavaScript.

Introduktion:
http://www.youtube.com/watch?v=w5qr4sx5Vt0

Gratis hostning av MongoDB-databas (troligen begränsad prestanda):
https://mongolab.com/about/pricing/

Testa shellkonsolen:
http://try.mongodb.org/

dAEk 2011-02-21 21:43

Citat:

Ursprungligen postat av danjel (Inlägg 20393398)
Hmm ja precis det börjar likna ett ORM..tanken var att jag gärna vill undvika ORM system och använda egna klasser för att behålla flexibilitet.

Jo, jag förstår. Går det inte att använda sina egna klasser om man redan har dem? Min kunskap inom PHP är egentligen obefintlig men i andra språk finns det ORM:s som låter en använda befintliga klasser. Det blir ju en del merjobb om man låter ORM:n skapa/generera DTO:erna eftersom de sedan behöver mappas mot ens egna klasser. Jag har nyligen upptäckt ett lib som gör mycket av det nästan helt magiskt fast det hjälper ju inte dig eftersom det är i ett språk som inte är PHP. Men du kan ju kolla efter "AutoMapper for PHP" eller liknande på t.ex. Stackoverflow. Annars vet jag inte. Det känns ju som att en fråga per objekt kommer belasta databasen mer, göra sidorna långsammare och dessutom kommer det begränsa användningsområdet till viss del om du inte bygger in stöd för eager loading också. Transaktionshantering borde ju också ingå. Nä, jag tror fortfarande att en ORM är rätt väg att gå.

Citat:

Ursprungligen postat av danjel (Inlägg 20393398)
Alltså jag har inte upplevt problem med joins och prestanda och vill byta ut dem pga det, tanken är endast att det ger bättre systemdesign utan dem och snabbare att få upp ett relativt enkelt system. Men att helt skippa joins är inget jag tänkt..
Jag tror t.o.m en del ORM kör lazy load per default och då enligt principen en sql fråga per objekt, så det är väl kanske inte så extremt nuförtiden.

Ah, ser nu att jag läste lite fel.

danjel 2011-02-22 14:16

Citat:

Ursprungligen postat av dAEk (Inlägg 20394035)
Jo, jag förstår. Går det inte att använda sina egna klasser om man redan har dem? Min kunskap inom PHP är egentligen obefintlig men i andra språk finns det ORM:s som låter en använda befintliga klasser. Det blir ju en del merjobb om man låter ORM:n skapa/generera DTO:erna eftersom de sedan behöver mappas mot ens egna klasser. Jag har nyligen upptäckt ett lib som gör mycket av det nästan helt magiskt fast det hjälper ju inte dig eftersom det är i ett språk som inte är PHP. Men du kan ju kolla efter "AutoMapper for PHP" eller liknande på t.ex. Stackoverflow. Annars vet jag inte. Det känns ju som att en fråga per objekt kommer belasta databasen mer, göra sidorna långsammare och dessutom kommer det begränsa användningsområdet till viss del om du inte bygger in stöd för eager loading också. Transaktionshantering borde ju också ingå. Nä, jag tror fortfarande att en ORM är rätt väg att gå.



Ah, ser nu att jag läste lite fel.

Ok, jag ska kika på automapper, tack för ditt svar.
Annars är problemet att jag inte hittat ett ORM som är enkelt och flexibelt än. Doctrine m.fl är för komplexa i mina syften..

Nåväl för den ursprungliga frågan jag tror jag frångår en princip att låta klasser mappa exakt mot databastabeller, och modellerar entiteter i stället (se nedan för bloggposter knutna till en användare).
Sedan får ett repository lager innehålla joins helt fritt..

<?php

class User
{
private $id;
private $name;

private $blogPosts;

public function __construct($id, $name)
{
$this->id = $id;
$this->name = $name;
}

public function addPost(BlogPost $p)
{
$this->blogPosts[] = $p;
}

public function getPost($i)
{
return $this->blogPosts[$i];
}
}

?>


Alla tider är GMT +2. Klockan är nu 01:20.

Programvara från: vBulletin® Version 3.8.2
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Svensk översättning av: Anders Pettersson