SlideShare a Scribd company logo
1 of 115
Download to read offline
ORM                            Database



                          Developers




      http://www.flickr.com/photos/hoyvinmayvin/5103806609/     Guilherme Blanco
Thursday, March 1, 2012
ORMs donʼt kill your DB, developers do!




               @guilhermeblanco

               http://github.com/guilhermeblanco

               InstaClick Inc.



                                                       Learning about good ORM
                                                   practices on @guilhermeblanco
                                                          talk at @confooca!




Thursday, March 1, 2012
Agenda




      http://www.flickr.com/photos/emerzh/3072428824/
Thursday, March 1, 2012
General Rule




           RTFM
Thursday, March 1, 2012
Dependency management




      http://www.flickr.com/photos/ollesvensson/3694625903/
Thursday, March 1, 2012
Dependency Management




Thursday, March 1, 2012
Dependency Management
                          namespace AppBundleBlogBundleEntity;

                          /**
                           * @ORMEntity
                           */
                          class Post
                          {
                              /**
                               * @ORMOneToMany(
                               *   targetEntity="AppComment:Comment",
                               *   mappedBy="post"
                               * )
                               */
                              protected $comments;
                          }

                          namespace AppBundleCommentBundleEntity;

                          /**
                           * @ORMEntity
                           */
                          class Comment
                          {
                              /**
                               * @ORMManyToOne(
                               *   targetEntity="AppBlog:Post",
                               *   inversedBy="comments"
                               * )     
                               */
                              protected $post;
                          }
Thursday, March 1, 2012
Dependency Management




Thursday, March 1, 2012
Dependency Management




Thursday, March 1, 2012
Dependency Management

                          namespace AppBundleBlogBundleEntity;

                          /**
                           * @ORMEntity
                           */
                          class Post
                          {
                              // ...
                          }




                          namespace AppBundleCommentBundleEntity;

                          /**
                           * @ORMEntity
                           */
                          class Comment
                          {
                              /**
                               * @ORMManyToOne(targetEntity="AppBlog:Post")
                               */
                              protected $post;
                          }




Thursday, March 1, 2012
Fetch Mode




      http://www.flickr.com/photos/comedynose/5318259802/
Thursday, March 1, 2012
Fetch Mode




         A fetching strategy is what ORM will use to retrieve
        associated objects if the application needs to navigate
                             through them




Thursday, March 1, 2012
Fetch Mode




                          Supported by all association types...




Thursday, March 1, 2012
Fetch Mode




     • OneToOne
     • OneToMany
     • ManyToOne
     • ManyToMany


Thursday, March 1, 2012
Fetch Mode




                          Available fetch modes...




Thursday, March 1, 2012
Fetch Mode




     • EAGER
     • LAZY (default)
     • EXTRA_LAZY


Thursday, March 1, 2012
Fetch Mode


                An association (collection or attribute), is
               fetched immediately when owner is loaded


     • EAGER
     • LAZY (default)
     • EXTRA_LAZY


Thursday, March 1, 2012
Fetch Mode


                An association (collection or attribute), is
               fetched immediately when owner is loaded


     • EAGER                         An association (collection or attribute),
     • LAZY (default)                is fetched when the application invokes
                                               an operation over it
     • EXTRA_LAZY


Thursday, March 1, 2012
Fetch Mode


                An association (collection or attribute), is
               fetched immediately when owner is loaded


     • EAGER                         An association (collection or attribute),
     • LAZY (default)                is fetched when the application invokes
                                               an operation over it
     • EXTRA_LAZY
                  Individual elements from association are
                 accessed from Database as needed. ORM
                    does not fetch the whole association
                       unless it is absolutely necessary
Thursday, March 1, 2012
Fetch Mode
                          /**
                           * @ORMEntity
                           */
                          class Post {
                              /**
                               * @ORMManyToOne(targetEntity="User", fetchMode="EAGER")
                               */
                              protected $author;

                              /**
                               * @ORMManyToMany(targetEntity="Tags", fetchMode="EXTRA_LAZY")
                               * @ORMJoinTable(name="posts_tags")
                               */
                              protected $tagList;
                          }

                          /**
                           * @ORMEntity
                           */
                          class Comment {
                              /**
                               * @ORMOneToMany(targetEntity="Post", fetchMode="LAZY")
                               * @JoinColumn(name="post_id", referencedColumnName="id")
                               */
                              protected $post;
                          }




Thursday, March 1, 2012
Fetch Mode
                          /**
                           * @ORMEntity
                           */
                                                                        Deadly sin
                          class Post {
                              /**
                               * @ORMManyToOne(targetEntity="User", fetchMode="EAGER")
                               */
                              protected $author;

                              /**
                               * @ORMManyToMany(targetEntity="Tags", fetchMode="EXTRA_LAZY")
                               * @ORMJoinTable(name="posts_tags")
                               */
                              protected $tagList;
                          }

                          /**
                           * @ORMEntity
                           */
                          class Comment {
                              /**
                               * @ORMOneToMany(targetEntity="Post", fetchMode="LAZY")
                               * @JoinColumn(name="post_id", referencedColumnName="id")
                               */
                              protected $post;
                          }




Thursday, March 1, 2012
Querying




      http://www.flickr.com/photos/pschadler/4932737690/
Thursday, March 1, 2012
Querying


                          $query    = $entityManager->createQuery('
                              SELECT p 
                                FROM Post p
                          ');
                          $postList = $query->getResult();

                          foreach ($postList as $post) {
                              $tagList = $post->getTagList();

                              foreach ($tagList as $tag) {
                                  echo $tag->getName();
                              }
                          }




Thursday, March 1, 2012
Querying


                          $query    = $entityManager->createQuery('
                              SELECT p 
                                FROM Post p
                          ');
                          $postList = $query->getResult();

                          foreach ($postList as $post) {
                              $tagList = $post->getTagList();     N + 1 trolls?
                              foreach ($tagList as $tag) {
                                  echo $tag->getName();
                              }
                          }




Thursday, March 1, 2012
Querying


                          $query    = $entityManager->createQuery('
                              SELECT p, t 
                                FROM Post p 
                                LEFT JOIN p.tagList t
                          ');
                          $postList = $query->getResult();

                          foreach ($postList as $post) {
                              $tagList = $post->getTagList();

                              foreach ($tagList as $tag) {
                                  echo $tag->getName();
                              }
                          }




Thursday, March 1, 2012
Querying


                          $query    = $entityManager->createQuery('
                              SELECT p, t 
                                FROM Post p                 Pardon? DQL is
                                LEFT JOIN p.tagList t
                          ');
                                                            powerful! RTFM
                          $postList = $query->getResult();

                          foreach ($postList as $post) {
                              $tagList = $post->getTagList();

                              foreach ($tagList as $tag) {
                                  echo $tag->getName();
                              }
                          }




Thursday, March 1, 2012
Querying




                          I know you all don’t trust me...




Thursday, March 1, 2012
Querying




                          ...but take a look at its EBNF grammar...




Thursday, March 1, 2012
QueryLanguage                                ::=   SelectStatement | UpdateStatement | DeleteStatement
 SelectStatement                              ::=   SelectClause FromClause [WhereClause] [GroupByClause] [HavingClause] [OrderByClause]
 UpdateStatement                              ::=   UpdateClause [WhereClause]
 DeleteStatement                              ::=   DeleteClause [WhereClause]
 JoinAssociationPathExpression                ::=   IdentificationVariable "." (CollectionValuedAssociationField | SingleValuedAssociationField)
 AssociationPathExpression                    ::=   CollectionValuedPathExpression | SingleValuedAssociationPathExpression
 SingleValuedPathExpression                   ::=   StateFieldPathExpression | SingleValuedAssociationPathExpression
 StateFieldPathExpression                     ::=   IdentificationVariable "." StateField | SingleValuedAssociationPathExpression "." StateField
 SingleValuedAssociationPathExpression        ::=   IdentificationVariable "." SingleValuedAssociationField
 CollectionValuedPathExpression               ::=   IdentificationVariable "." {SingleValuedAssociationField "."}* CollectionValuedAssociationField
 StateField                                   ::=   {EmbeddedClassStateField "."}* SimpleStateField
 SimpleStateFieldPathExpression               ::=   IdentificationVariable "." StateField
 SelectClause                                 ::=   "SELECT" ["DISTINCT"] SelectExpression {"," SelectExpression}*
 SimpleSelectClause                           ::=   "SELECT" ["DISTINCT"] SimpleSelectExpression
 UpdateClause                                 ::=   "UPDATE" AbstractSchemaName ["AS"] AliasIdentificationVariable "SET" UpdateItem {"," UpdateItem}*
 DeleteClause                                 ::=   "DELETE" ["FROM"] AbstractSchemaName ["AS"] AliasIdentificationVariable
 FromClause                                   ::=   "FROM" IdentificationVariableDeclaration {"," IdentificationVariableDeclaration}*
 SubselectFromClause                          ::=   "FROM" SubselectIdentificationVariableDeclaration {"," SubselectIdentificationVariableDeclaration}*
 WhereClause                                  ::=   "WHERE" ConditionalExpression
 HavingClause                                 ::=   "HAVING" ConditionalExpression
 GroupByClause                                ::=   "GROUP" "BY" GroupByItem {"," GroupByItem}*
 OrderByClause                                ::=   "ORDER" "BY" OrderByItem {"," OrderByItem}*
 Subselect                                    ::=   SimpleSelectClause SubselectFromClause [WhereClause] [GroupByClause] [HavingClause] [OrderByClause]
 UpdateItem                                   ::=   IdentificationVariable "." (StateField | SingleValuedAssociationField) "=" NewValue
 OrderByItem                                  ::=   (ResultVariable | SingleValuedPathExpression) ["ASC" | "DESC"]
 GroupByItem                                  ::=   IdentificationVariable | SingleValuedPathExpression
 NewValue                                     ::=   ScalarExpression | SimpleEntityExpression | "NULL"
 IdentificationVariableDeclaration            ::=   RangeVariableDeclaration [IndexBy] {JoinVariableDeclaration}*
 SubselectIdentificationVariableDeclaration   ::=   IdentificationVariableDeclaration | (AssociationPathExpression ["AS"] AliasIdentificationVariable)
 JoinVariableDeclaration                      ::=   Join [IndexBy]
 RangeVariableDeclaration                     ::=   AbstractSchemaName ["AS"] AliasIdentificationVariable
 Join                                         ::=   ["LEFT" ["OUTER"] | "INNER"] "JOIN" JoinAssociationPathExpression ["AS"] AliasIdentificationVariable ["WITH" ConditionalExpression]
 IndexBy                                      ::=   "INDEX" "BY" SimpleStateFieldPathExpression
 SelectExpression                             ::=   IdentificationVariable | PartialObjectExpression | (AggregateExpression | "(" Subselect ")" | FunctionDeclaration | ScalarExpression) [["AS"] AliasResultVariable]
 SimpleSelectExpression                       ::=   ScalarExpression | IdentificationVariable | (AggregateExpression [["AS"] AliasResultVariable])
 PartialObjectExpression                      ::=   "PARTIAL" IdentificationVariable "." PartialFieldSet
 PartialFieldSet                              ::=   "{" SimpleStateField {"," SimpleStateField}* "}"
 ConditionalExpression                        ::=   ConditionalTerm {"OR" ConditionalTerm}*
 ConditionalTerm                              ::=   ConditionalFactor {"AND" ConditionalFactor}*
 ConditionalFactor                            ::=   ["NOT"] ConditionalPrimary
 ConditionalPrimary                           ::=   SimpleConditionalExpression | "(" ConditionalExpression ")"
 SimpleConditionalExpression                  ::=   ComparisonExpression | BetweenExpression | LikeExpression | InExpression | NullComparisonExpression |
                                                    ExistsExpression | EmptyCollectionComparisonExpression | CollectionMemberExpression | InstanceOfExpression
 EmptyCollectionComparisonExpression          ::=   CollectionValuedPathExpression "IS" ["NOT"] "EMPTY"
 CollectionMemberExpression                   ::=   EntityExpression ["NOT"] "MEMBER" ["OF"] CollectionValuedPathExpression
 Literal                                      ::=   string | char | integer | float | boolean
 InParameter                                  ::=   Literal | InputParameter
 InputParameter                               ::=   PositionalParameter | NamedParameter
 PositionalParameter                          ::=   "?" integer
 NamedParameter                               ::=   ":" string
 ArithmeticExpression                         ::=   SimpleArithmeticExpression | "(" Subselect ")"
 SimpleArithmeticExpression                   ::=   ArithmeticTerm {("+" | "-") ArithmeticTerm}*
 ArithmeticTerm                               ::=   ArithmeticFactor {("*" | "/") ArithmeticFactor}*
 ArithmeticFactor                             ::=   [("+" | "-")] ArithmeticPrimary
 ArithmeticPrimary                            ::=   SingleValuedPathExpression | Literal | "(" SimpleArithmeticExpression ")" | FunctionsReturningNumerics | AggregateExpression |
                                                    FunctionsReturningStrings | FunctionsReturningDatetime | IdentificationVariable | InputParameter | CaseExpression
 ScalarExpression                             ::=   SimpleArithmeticExpression | StringPrimary | DateTimePrimary | StateFieldPathExpression | BooleanPrimary | EntityTypeExpression | CaseExpression
 StringExpression                             ::=   StringPrimary | "(" Subselect ")"
 StringPrimary                                ::=   StateFieldPathExpression | string | InputParameter | FunctionsReturningStrings | AggregateExpression | CaseExpression
 BooleanExpression                            ::=   BooleanPrimary | "(" Subselect ")"
 BooleanPrimary                               ::=   StateFieldPathExpression | boolean | InputParameter
 EntityExpression                             ::=   SingleValuedAssociationPathExpression | SimpleEntityExpression
 SimpleEntityExpression                       ::=   IdentificationVariable | InputParameter
 DatetimeExpression                           ::=   DatetimePrimary | "(" Subselect ")"
 DatetimePrimary                              ::=   StateFieldPathExpression | InputParameter | FunctionsReturningDatetime | AggregateExpression
 AggregateExpression                          ::=   ("AVG" | "MAX" | "MIN" | "SUM") "(" ["DISTINCT"] StateFieldPathExpression ")" | "COUNT" "(" ["DISTINCT"] (IdentificationVariable | SingleValuedPathExpression) ")"
 CaseExpression                               ::=   GeneralCaseExpression | SimpleCaseExpression | CoalesceExpression | NullifExpression
 GeneralCaseExpression                        ::=   "CASE" WhenClause {WhenClause}* "ELSE" ScalarExpression "END"
 WhenClause                                   ::=   "WHEN" ConditionalExpression "THEN" ScalarExpression
 SimpleCaseExpression                         ::=   "CASE" CaseOperand SimpleWhenClause {SimpleWhenClause}* "ELSE" ScalarExpression "END"
 CaseOperand                                  ::=   StateFieldPathExpression | TypeDiscriminator
 SimpleWhenClause                             ::=   "WHEN" ScalarExpression "THEN" ScalarExpression
 CoalesceExpression                           ::=   "COALESCE" "(" ScalarExpression {"," ScalarExpression}* ")"
 NullifExpression                             ::=   "NULLIF" "(" ScalarExpression "," ScalarExpression ")"
 QuantifiedExpression                         ::=   ("ALL" | "ANY" | "SOME") "(" Subselect ")"
 BetweenExpression                            ::=   ArithmeticExpression ["NOT"] "BETWEEN" ArithmeticExpression "AND" ArithmeticExpression
 ComparisonExpression                         ::=   ArithmeticExpression ComparisonOperator ( QuantifiedExpression | ArithmeticExpression )
 InExpression                                 ::=   StateFieldPathExpression ["NOT"] "IN" "(" (InParameter {"," InParameter}* | Subselect) ")"
 InstanceOfExpression                         ::=   IdentificationVariable ["NOT"] "INSTANCE" ["OF"] (InstanceOfParameter | "(" InstanceOfParameter {"," InstanceOfParameter}* ")")
 InstanceOfParameter                          ::=   AbstractSchemaName | InputParameter
 LikeExpression                               ::=   StringExpression ["NOT"] "LIKE" string ["ESCAPE" char]
 NullComparisonExpression                     ::=   (SingleValuedPathExpression | InputParameter) "IS" ["NOT"] "NULL"
 ExistsExpression                             ::=   ["NOT"] "EXISTS" "(" Subselect ")"
 ComparisonOperator                           ::=   "=" | "<" | "<=" | "<>" | ">" | ">=" | "!="
 FunctionDeclaration                          ::=   FunctionsReturningStrings | FunctionsReturningNumerics | FunctionsReturningDateTime
 FunctionsReturningNumerics                   ::=   "LENGTH" "(" StringPrimary ")" | "LOCATE" "(" StringPrimary "," StringPrimary ["," SimpleArithmeticExpression]")" | "ABS" "(" SimpleArithmeticExpression ")" |
                                                    "SQRT" "(" SimpleArithmeticExpression ")" | "MOD" "(" SimpleArithmeticExpression "," SimpleArithmeticExpression ")" | "SIZE" "(" CollectionValuedPathExpression ")"
 FunctionsReturningDateTime                   ::=   "CURRENT_DATE" | "CURRENT_TIME" | "CURRENT_TIMESTAMP"
 FunctionsReturningStrings                    ::=   "CONCAT" "(" StringPrimary "," StringPrimary ")" | "SUBSTRING" "(" StringPrimary "," SimpleArithmeticExpression "," SimpleArithmeticExpression ")" |
                                                    "TRIM" "(" [["LEADING" | "TRAILING" | "BOTH"] [char] "FROM"] StringPrimary ")" | "LOWER" "(" StringPrimary ")" | "UPPER" "(" StringPrimary ")"




Thursday, March 1, 2012
Querying




         Since the letter size is 6, you may still not believe me




Thursday, March 1, 2012
Querying




                          let’s try a real world example!




Thursday, March 1, 2012
Querying




                          Do you know Facebook activity wall?




Thursday, March 1, 2012
Querying




                          Do you know Facebook activity wall?
                                    Let’s show it!




Thursday, March 1, 2012
SELECT  e, a
   FROM  Entry e
   JOIN  e.wall w
   JOIN  e.user u
   LEFT  JOIN u.avatar av
  WHERE  u = :user
     OR  w IN (
              SELECT uw
                FROM UserWall uw
               WHERE uw.user = :user
                  OR uw.user IN (
                         SELECT CASE WHEN ua = us.subscriber
                                     THEN ub.id
                                     ELSE ua.id
                                 END
                           FROM UserSubscription us
                           JOIN us.friendship f
                           JOIN f.userA ua
                           JOIN f.userB ub
                          WHERE us.muted      = FALSE
                            AND us.subscriber = :user
                            AND f.status      = 'Approved'
                     )
         )
      OR w IN (
              SELECT gw
                FROM GroupWall gw
               WHERE gw.group IN (
                         SELECT DISTINCT g.id
                           FROM GroupSubscription gs
                           JOIN gs.group g
                          WHERE gs.subscriber = :user
                            AND gs.muted      = FALSE
                            AND gs.status     = 'Approved'
                     )
         )
   ORDER BY e.created DESC
Thursday, March 1, 2012
SELECT  e, a
   FROM  Entry e
   JOIN  e.wall w           Entry you wrote
   JOIN  e.user u
   LEFT  JOIN u.avatar av
  WHERE  u = :user
     OR  w IN (
              SELECT uw
                FROM UserWall uw
               WHERE uw.user = :user
                  OR uw.user IN (
                         SELECT CASE WHEN ua = us.subscriber
                                      THEN ub.id
                                      ELSE ua.id
                                 END
                           FROM UserSubscription us
                           JOIN us.friendship f
                           JOIN f.userA ua
                           JOIN f.userB ub
                          WHERE us.muted       = FALSE
                            AND us.subscriber = :user
                            AND f.status       = 'Approved'
                     )
         )
      OR w IN (
              SELECT gw
                FROM GroupWall gw
               WHERE gw.group IN (
                         SELECT DISTINCT g.id
                           FROM GroupSubscription gs
                           JOIN gs.group g
                          WHERE gs.subscriber = :user
                            AND gs.muted       = FALSE
                            AND gs.status      = 'Approved'
                     )
         )
   ORDER BY e.created DESC
Thursday, March 1, 2012
SELECT  e, a
   FROM  Entry e
   JOIN  e.wall w           Entry you wrote
   JOIN  e.user u
   LEFT  JOIN u.avatar av
  WHERE  u = :user
     OR  w IN (                                  Entry was in your Wall
              SELECT uw
                FROM UserWall uw
               WHERE uw.user = :user
                  OR uw.user IN (
                         SELECT CASE WHEN ua = us.subscriber
                                      THEN ub.id
                                      ELSE ua.id
                                 END
                           FROM UserSubscription us
                           JOIN us.friendship f
                           JOIN f.userA ua
                           JOIN f.userB ub
                          WHERE us.muted       = FALSE
                            AND us.subscriber = :user
                            AND f.status       = 'Approved'
                     )
         )
      OR w IN (
              SELECT gw
                FROM GroupWall gw
               WHERE gw.group IN (
                         SELECT DISTINCT g.id
                           FROM GroupSubscription gs
                           JOIN gs.group g
                          WHERE gs.subscriber = :user
                            AND gs.muted       = FALSE
                            AND gs.status      = 'Approved'
                     )
         )
   ORDER BY e.created DESC
Thursday, March 1, 2012
SELECT  e, a
   FROM  Entry e
   JOIN  e.wall w           Entry you wrote
   JOIN  e.user u
   LEFT  JOIN u.avatar av
  WHERE  u = :user
     OR  w IN (                                  Entry was in your Wall
              SELECT uw
                FROM UserWall uw
               WHERE uw.user = :user
                  OR uw.user IN (
                         SELECT CASE WHEN ua = us.subscriber
                                      THEN ub.id
                                      ELSE ua.id
                                 END
                           FROM UserSubscription us
                                                              User is your friend, the friendship is
                           JOIN us.friendship f             approved and subscription is not muted
                           JOIN f.userA ua
                           JOIN f.userB ub
                          WHERE us.muted       = FALSE
                            AND us.subscriber = :user
                            AND f.status       = 'Approved'
                     )
         )
      OR w IN (
              SELECT gw
                FROM GroupWall gw
               WHERE gw.group IN (
                         SELECT DISTINCT g.id
                           FROM GroupSubscription gs
                           JOIN gs.group g
                          WHERE gs.subscriber = :user
                            AND gs.muted       = FALSE
                            AND gs.status      = 'Approved'
                     )
         )
   ORDER BY e.created DESC
Thursday, March 1, 2012
SELECT  e, a
   FROM  Entry e
   JOIN  e.wall w           Entry you wrote
   JOIN  e.user u
   LEFT  JOIN u.avatar av
  WHERE  u = :user
     OR  w IN (                                  Entry was in your Wall
              SELECT uw
                FROM UserWall uw
               WHERE uw.user = :user
                  OR uw.user IN (
                         SELECT CASE WHEN ua = us.subscriber
                                      THEN ub.id
                                      ELSE ua.id
                                 END
                           FROM UserSubscription us
                                                              User is your friend, the friendship is
                           JOIN us.friendship f             approved and subscription is not muted
                           JOIN f.userA ua
                           JOIN f.userB ub
                          WHERE us.muted       = FALSE
                            AND us.subscriber = :user
                            AND f.status       = 'Approved'
                     )
         )
      OR w IN (
              SELECT gw
                FROM GroupWall gw
               WHERE gw.group IN (
                         SELECT DISTINCT g.id
                           FROM GroupSubscription gs
                           JOIN gs.group g                      Group that you participate, is not
                          WHERE gs.subscriber = :user
                            AND gs.muted       = FALSE
                                                                muted and have an approved status
                            AND gs.status      = 'Approved'
                     )
         )
   ORDER BY e.created DESC
Thursday, March 1, 2012
Caching




      http://www.flickr.com/photos/eszter/3851576235/
Thursday, March 1, 2012
Caching




                          Doctrine supports 3 levels of caching...




Thursday, March 1, 2012
Caching




     • Metadata cache
     • Query cache
     • Result cache


Thursday, March 1, 2012
Caching


                      Cache mapping of entities


     • Metadata cache
     • Query cache
     • Result cache


Thursday, March 1, 2012
Caching


                      Cache mapping of entities


     • Metadata cache
     • Query cache                     Cache DQL to SQL conversion

     • Result cache


Thursday, March 1, 2012
Caching


                      Cache mapping of entities


     • Metadata cache
     • Query cache                       Cache DQL to SQL conversion

     • Result cache
                          Cache PDO result set



Thursday, March 1, 2012
Caching



                    $query   = $entityManager->createQuery('
                        SELECT p 
                          FROM Post p
                    ');

                    $query->useResultCache(true, 600, 'find-all-posts');

                    $postList = $query->getResult();




Thursday, March 1, 2012
Indexing




      http://www.flickr.com/photos/osuarchives/2659419894/
Thursday, March 1, 2012
Indexing




         Doctrine is able to hint the Schema Tool to generate
            database indexes on specified table columns




Thursday, March 1, 2012
Indexing
                          /**
                           * @ORMEntity
                           * @ORMTable(
                           *     name = "users",
                           *     uniqueConstraints = {
                           *         @ORMUniqueConstraint(
                           *             name    = "user_unique",
                           *             columns = { "name" }
                           *         )
                           *     },
                           *     indexes = {
                           *         @ORMIndex(
                           *             name    = "login_idx", 
                           *             columns = { "name", "password" }
                           *         )
                           *     }
                           * )
                           */
                          class User
                          {
                              // ...
                          }
Thursday, March 1, 2012
Indexing



                          @ORMUniqueConstraint(
                              name    = "user_unique", 
                              columns = { "name" }
                          )




                 CREATE UNIQUE INDEX user_unique
                     ON TABLE users (name);


Thursday, March 1, 2012
Indexing



                  @ORMIndex(
                      name    = "login_idx", 
                      columns = { "name", "password" }
                  )




       CREATE INDEX login_idx
           ON TABLE users (name, password);


Thursday, March 1, 2012
Indexing



                  @ORMIndex(
                      name    = "login_idx", 
                      columns = { "name", "password" }
                  )
                                Some drivers restrict to
                                 32 chars as index name


       CREATE INDEX login_idx
           ON TABLE users (name, password);


Thursday, March 1, 2012
Inheritance




      http://www.flickr.com/photos/duanekeys/307005468/
Thursday, March 1, 2012
Inheritance




                          Inheritance is a very deep topic in ORMs




Thursday, March 1, 2012
Inheritance




      Each inheritance type has advantages and disadvantages




Thursday, March 1, 2012
Inheritance




     • Concrete Table Inheritance
     • Single Table Inheritance
     • Class Table Inheritance


Thursday, March 1, 2012
Inheritance



               One Class, one Table


     • Concrete Table Inheritance
     • Single Table Inheritance
     • Class Table Inheritance


Thursday, March 1, 2012
Inheritance



               One Class, one Table


     • Concrete Table Inheritance
     • Single Table Inheritance Multiple Classes, one Table
     • Class Table Inheritance


Thursday, March 1, 2012
Inheritance



               One Class, one Table


     • Concrete Table Inheritance
     • Single Table Inheritance Multiple Classes, one Table
     • Class Table Inheritance
                Multiple Classes, multiple Tables



Thursday, March 1, 2012
Inheritance



     • Concrete Table Inheritance




Thursday, March 1, 2012
Inheritance



     • Concrete Table Inheritance
           •      Pros




Thursday, March 1, 2012
Inheritance



     • Concrete Table Inheritance
           •      Pros
                 •        No locking problems




Thursday, March 1, 2012
Inheritance



     • Concrete Table Inheritance
           •      Pros
                 •        No locking problems

                 •        No irrelevant columns




Thursday, March 1, 2012
Inheritance



     • Concrete Table Inheritance
           •      Pros
                 •        No locking problems

                 •        No irrelevant columns


           •      Cons




Thursday, March 1, 2012
Inheritance



     • Concrete Table Inheritance
           •      Pros
                 •        No locking problems

                 •        No irrelevant columns


           •      Cons
                 •        Difficult to deal with primary keys




Thursday, March 1, 2012
Inheritance



     • Concrete Table Inheritance
           •      Pros
                 •        No locking problems

                 •        No irrelevant columns


           •      Cons
                 •        Difficult to deal with primary keys

                 •        Search base class means search all tables




Thursday, March 1, 2012
Inheritance



     • Concrete Table Inheritance
           •      Pros
                 •        No locking problems

                 •        No irrelevant columns


           •      Cons
                 •        Difficult to deal with primary keys

                 •        Search base class means search all tables

                 •        Update on columns means update on all hierarchy tables




Thursday, March 1, 2012
Inheritance
                          /**
                           * @ORMMappedSuperclass
                           */
                          class Person
                          {
                              /**
                               * @ORMColumn(type="string", length=50)
                               */
                              protected $firstName;

                              /**
                               * @ORMColumn(type="string", length=50)
                               */
                              protected $lastName;
                          }

                          /**
                           * @ORMEntity
                           * @ORMTable(name="users")
                           */
                          class User extends Person
                          {
                              /**
                               * @ORMId
                               * @ORMGeneratedValue
                               * @ORMColumn(type="integer")
                               */
                              protected $id;
                          }
Thursday, March 1, 2012
Inheritance



             CREATE TABLE users (
                 id INTEGER AUTO_INCREMENT NOT NULL,
                 firstName VARCHAR(50) NOT NULL,
                 lastName VARCHAR(50) NOT NULL,
                 PRIMARY KEY (id)
             ) ENGINE=InnoDB;




Thursday, March 1, 2012
Inheritance


     • Single Table Inheritance




Thursday, March 1, 2012
Inheritance


     • Single Table Inheritance
           •      Pros




Thursday, March 1, 2012
Inheritance


     • Single Table Inheritance
           •      Pros
                 •        Only one table for hierarchy




Thursday, March 1, 2012
Inheritance


     • Single Table Inheritance
           •      Pros
                 •        Only one table for hierarchy

                 •        No joins




Thursday, March 1, 2012
Inheritance


     • Single Table Inheritance
           •      Pros
                 •        Only one table for hierarchy

                 •        No joins

                 •        Refactoring of fields means no change to database table




Thursday, March 1, 2012
Inheritance


     • Single Table Inheritance
           •      Pros
                 •        Only one table for hierarchy

                 •        No joins

                 •        Refactoring of fields means no change to database table


           •      Cons




Thursday, March 1, 2012
Inheritance


     • Single Table Inheritance
           •      Pros
                 •        Only one table for hierarchy

                 •        No joins

                 •        Refactoring of fields means no change to database table


           •      Cons
                 •        Waste of space in database




Thursday, March 1, 2012
Inheritance


     • Single Table Inheritance
           •      Pros
                 •        Only one table for hierarchy

                 •        No joins

                 •        Refactoring of fields means no change to database table


           •      Cons
                 •        Waste of space in database

                 •        Too many locks due to many accesses




Thursday, March 1, 2012
Inheritance


     • Single Table Inheritance
           •      Pros
                 •        Only one table for hierarchy

                 •        No joins

                 •        Refactoring of fields means no change to database table


           •      Cons
                 •        Waste of space in database

                 •        Too many locks due to many accesses

                 •        No duplicated field names with different meanings



Thursday, March 1, 2012
Inheritance
                          namespace MyAppEntity;

                          /**
                           * @ORMEntity
                            * @ORMTable(name= "people")
                           * @ORMInheritanceType("SINGLE_TABLE")
                           * @ORMDiscriminatorColumn(name="discr", type="string")
                           * @ORMDiscriminatorMap({
                           *     "user"     = "MyAppEntityUser",
                           *     "employee" = "MyAppEntityEmployee"
                           * })
                           */
                          class User
                          {
                              // ...
                          }

                          /**
                           * @ORMEntity
                           */
                          class Employee extends User
                          {
                               // ...
                          }




Thursday, March 1, 2012
Inheritance


                   CREATE TABLE people (
                       id INT AUTO_INCREMENT NOT NULL,
                       firstName VARCHAR(50) NOT NULL,
                       lastName VARCHAR(50) NOT NULL,
                       discr VARCHAR(20) NOT NULL,
                       role VARCHAR(100) DEFAULT NULL,
                       PRIMARY KEY (id)
                   ) ENGINE=InnoDB;




Thursday, March 1, 2012
Inheritance


     • Class Table Inheritance




Thursday, March 1, 2012
Inheritance


     • Class Table Inheritance
           •      Pros




Thursday, March 1, 2012
Inheritance


     • Class Table Inheritance
           •      Pros
                 •        Easy to understand




Thursday, March 1, 2012
Inheritance


     • Class Table Inheritance
           •      Pros
                 •        Easy to understand

                 •        Database space is optimized due to table normalization




Thursday, March 1, 2012
Inheritance


     • Class Table Inheritance
           •      Pros
                 •        Easy to understand

                 •        Database space is optimized due to table normalization

                 •        Direct relationship between Domain Model and Database




Thursday, March 1, 2012
Inheritance


     • Class Table Inheritance
           •      Pros
                 •        Easy to understand

                 •        Database space is optimized due to table normalization

                 •        Direct relationship between Domain Model and Database


           •      Cons




Thursday, March 1, 2012
Inheritance


     • Class Table Inheritance
           •      Pros
                 •        Easy to understand

                 •        Database space is optimized due to table normalization

                 •        Direct relationship between Domain Model and Database


           •      Cons
                 •        Too many joins




Thursday, March 1, 2012
Inheritance


     • Class Table Inheritance
           •      Pros
                 •        Easy to understand

                 •        Database space is optimized due to table normalization

                 •        Direct relationship between Domain Model and Database


           •      Cons
                 •        Too many joins

                 •        Refactoring of fields needs a database schema update




Thursday, March 1, 2012
Inheritance


     • Class Table Inheritance
           •      Pros
                 •        Easy to understand

                 •        Database space is optimized due to table normalization

                 •        Direct relationship between Domain Model and Database


           •      Cons
                 •        Too many joins

                 •        Refactoring of fields needs a database schema update

                 •        Superclass table accessed a lot, it means it may enter in lock mode



Thursday, March 1, 2012
Inheritance
                          namespace MyAppEntity;

                          /**
                           * @ORMEntity
                            * @ORMTable(name="users")
                           * @ORMInheritanceType("JOINED")
                           * @ORMDiscriminatorColumn(
                            *     name   = "discr", 
                            *     type   = "string",
                            *     length = 20
                            * )
                           * @ORMDiscriminatorMap({
                           *     "user"     = "MyAppEntityUser",
                           *     "employee" = "MyAppEntityEmployee"
                           * })
                           */
                          class User
                          {
                              // ...
                          }

                          /**
                           * @ORMEntity
                           * @ORMTable(name= "employees")
                           */
                          class Employee extends User
                          {
                               // ...
                          }

Thursday, March 1, 2012
Inheritance
                          CREATE TABLE users (
                              id INT AUTO_INCREMENT NOT NULL,
                              firstName VARCHAR(50) NOT NULL,
                              lastName VARCHAR(50) NOT NULL,
                              discr VARCHAR(20) NOT NULL,
                              PRIMARY KEY (id)
                          ) ENGINE = InnoDB;

                          CREATE TABLE employees (
                              id INT NOT NULL,
                              role VARCHAR(100) NOT NULL,
                              PRIMARY KEY (id)
                          ) ENGINE = InnoDB;

                          ALTER TABLE employees
                            ADD CONSTRAINT FK_BA82C300BF396750
                                FOREIGN KEY (id)
                                REFERENCES users (id)
                                ON DELETE CASCADE;




Thursday, March 1, 2012
Inheritance




                          What’s the problem with inheritance?




Thursday, March 1, 2012
Inheritance




                          What’s the problem with inheritance?
                                       Hydration




Thursday, March 1, 2012
Inheritance




Thursday, March 1, 2012
Inheritance




     • Inverse side *ToOne




Thursday, March 1, 2012
Inheritance




     • Inverse side *ToOne
     • Owning side *ToOne with Inheritance



Thursday, March 1, 2012
Inheritance




     • Inverse side *ToOne
     • Owning side *ToOne with Inheritance
     • Disabled deferEagerLoad while Querying


Thursday, March 1, 2012
Cascades




      http://www.flickr.com/photos/over_kind_man/3158552109/
Thursday, March 1, 2012
Cascades




 Ability to tell Unit Of Work of Doctrine how it should act
      when inspecting an association for graph changes




Thursday, March 1, 2012
Cascades




                          Use judiciously




Thursday, March 1, 2012
Cascades




       It can heavily increase the graph edges to be navigated
            once the Compute Changeset algorithm is ran




Thursday, March 1, 2012
Cascades




                                 This means more time to
                          persist, delete, merge, detach, refresh...




Thursday, March 1, 2012
Cascades
                          /**
                           * @ORMEntity
                           */
                          class User
                          {
                              //...

                              /**
                               * Bidirectional - One-To-Many (INVERSE SIDE)
                               *
                               * @ORMOneToMany(
                               *     targetEntity = "Comment", 
                               *     mappedBy     = "author", 
                               *     cascade      = { "persist", "remove" }
                               * )
                               */
                              protected $commentsAuthored;
                          }




Thursday, March 1, 2012
Hydrators




      http://crimsonnightstock.deviantart.com/art/Yellow-Fire-Hydrant-Stock-100121929
Thursday, March 1, 2012
Hydrators




            Doctrine comes with some useful result hydrators




Thursday, March 1, 2012
Hydrators




 This means that not all times you need to retrieve objects




Thursday, March 1, 2012
Hydrators



     • Object
     • Array
     • Scalar
     • Iterable
     • Simple Object
     • Single Scalar

Thursday, March 1, 2012
Hydrators



     •      Object        $resultList = $query->getResult();


     • Array
     • Scalar
     • Iterable
     • Simple Object
     • Single Scalar

Thursday, March 1, 2012
Hydrators



     •      Object           $resultList = $query->getResult();


     • Array              $resultArray = $query->getArrayResult();


     • Scalar
     • Iterable
     • Simple Object
     • Single Scalar

Thursday, March 1, 2012
Hydrators



     •      Object           $resultList = $query->getResult();


     • Array              $resultArray = $query->getArrayResult();


     • Scalar               $result = $query->getScalarResult();


     • Iterable
     • Simple Object
     • Single Scalar

Thursday, March 1, 2012
Hydrators



     •      Object           $resultList = $query->getResult();


     • Array              $resultArray = $query->getArrayResult();


     • Scalar               $result = $query->getScalarResult();


     • Iterable                $iterator = $query->iterate();


     • Simple Object
     • Single Scalar

Thursday, March 1, 2012
Hydrators



     •      Object           $resultList = $query->getResult();


     • Array              $resultArray = $query->getArrayResult();


     • Scalar               $result = $query->getScalarResult();


     • Iterable                $iterator = $query->iterate();


     • Simple Object                     $result = $query->getSingleResult();


     • Single Scalar

Thursday, March 1, 2012
Hydrators



     •      Object           $resultList = $query->getResult();


     • Array              $resultArray = $query->getArrayResult();


     • Scalar               $result = $query->getScalarResult();


     • Iterable                $iterator = $query->iterate();


     • Simple Object                     $result = $query->getSingleResult();


     • Single Scalar                  $result = $query->getSingleScalarResult();




Thursday, March 1, 2012
http://joind.in/6053




                                       Questions?



           @guilhermeblanco

           http://github.com/guilhermeblanco

           InstaClick Inc.

Thursday, March 1, 2012
http://joind.in/6053




                                        Questions?



           @guilhermeblanco

           http://github.com/guilhermeblanco

           InstaClick Inc.      We are hiring! Talk to me privately if interested

Thursday, March 1, 2012
http://joind.in/6053




                                        Questions?
                                        Thank you!


           @guilhermeblanco

           http://github.com/guilhermeblanco

           InstaClick Inc.      We are hiring! Talk to me privately if interested

Thursday, March 1, 2012

More Related Content

Viewers also liked

Your code sucks, let's fix it
Your code sucks, let's fix itYour code sucks, let's fix it
Your code sucks, let's fix itRafael Dohms
 
Object Calisthenics Applied to PHP
Object Calisthenics Applied to PHPObject Calisthenics Applied to PHP
Object Calisthenics Applied to PHPGuilherme Blanco
 
Effective Doctrine2: Performance Tips for Symfony2 Developers
Effective Doctrine2: Performance Tips for Symfony2 DevelopersEffective Doctrine2: Performance Tips for Symfony2 Developers
Effective Doctrine2: Performance Tips for Symfony2 DevelopersMarcin Chwedziak
 
Doctrine In The Real World sflive2011 Paris
Doctrine In The Real World sflive2011 ParisDoctrine In The Real World sflive2011 Paris
Doctrine In The Real World sflive2011 ParisJonathan Wage
 
Doctrine 2 - Not The Same Old Php Orm
Doctrine 2 - Not The Same Old Php OrmDoctrine 2 - Not The Same Old Php Orm
Doctrine 2 - Not The Same Old Php OrmJonathan Wage
 
Granny Was a Hacker (CampJS Version)
Granny Was a Hacker (CampJS Version)Granny Was a Hacker (CampJS Version)
Granny Was a Hacker (CampJS Version)Kristine Howard
 
Introduction to Go programming
Introduction to Go programmingIntroduction to Go programming
Introduction to Go programmingExotel
 

Viewers also liked (8)

Your code sucks, let's fix it
Your code sucks, let's fix itYour code sucks, let's fix it
Your code sucks, let's fix it
 
Doctrine ORM & model
Doctrine ORM & modelDoctrine ORM & model
Doctrine ORM & model
 
Object Calisthenics Applied to PHP
Object Calisthenics Applied to PHPObject Calisthenics Applied to PHP
Object Calisthenics Applied to PHP
 
Effective Doctrine2: Performance Tips for Symfony2 Developers
Effective Doctrine2: Performance Tips for Symfony2 DevelopersEffective Doctrine2: Performance Tips for Symfony2 Developers
Effective Doctrine2: Performance Tips for Symfony2 Developers
 
Doctrine In The Real World sflive2011 Paris
Doctrine In The Real World sflive2011 ParisDoctrine In The Real World sflive2011 Paris
Doctrine In The Real World sflive2011 Paris
 
Doctrine 2 - Not The Same Old Php Orm
Doctrine 2 - Not The Same Old Php OrmDoctrine 2 - Not The Same Old Php Orm
Doctrine 2 - Not The Same Old Php Orm
 
Granny Was a Hacker (CampJS Version)
Granny Was a Hacker (CampJS Version)Granny Was a Hacker (CampJS Version)
Granny Was a Hacker (CampJS Version)
 
Introduction to Go programming
Introduction to Go programmingIntroduction to Go programming
Introduction to Go programming
 

More from Guilherme Blanco

PHPubSP Object Calisthenics aplicado ao PHP
PHPubSP Object Calisthenics aplicado ao PHPPHPubSP Object Calisthenics aplicado ao PHP
PHPubSP Object Calisthenics aplicado ao PHPGuilherme Blanco
 
IPC2010SE Doctrine2 Enterprise Persistence Layer for PHP
IPC2010SE Doctrine2 Enterprise Persistence Layer for PHPIPC2010SE Doctrine2 Enterprise Persistence Layer for PHP
IPC2010SE Doctrine2 Enterprise Persistence Layer for PHPGuilherme Blanco
 
Doctrine 2.0: A evolução da persistência em PHP
Doctrine 2.0: A evolução da persistência em PHPDoctrine 2.0: A evolução da persistência em PHP
Doctrine 2.0: A evolução da persistência em PHPGuilherme Blanco
 
Doctrine 2.0 Enterprise Persistence Layer for PHP
Doctrine 2.0 Enterprise Persistence Layer for PHPDoctrine 2.0 Enterprise Persistence Layer for PHP
Doctrine 2.0 Enterprise Persistence Layer for PHPGuilherme Blanco
 
Desenvolvimento Agil Com Doctrine Orm
Desenvolvimento Agil Com Doctrine OrmDesenvolvimento Agil Com Doctrine Orm
Desenvolvimento Agil Com Doctrine OrmGuilherme Blanco
 

More from Guilherme Blanco (11)

Enterprise php
Enterprise phpEnterprise php
Enterprise php
 
PHP 7
PHP 7PHP 7
PHP 7
 
PHPubSP Object Calisthenics aplicado ao PHP
PHPubSP Object Calisthenics aplicado ao PHPPHPubSP Object Calisthenics aplicado ao PHP
PHPubSP Object Calisthenics aplicado ao PHP
 
Javascript para adultos
Javascript para adultosJavascript para adultos
Javascript para adultos
 
Dependency injection
Dependency injectionDependency injection
Dependency injection
 
Doctrine2 Seminário PHP
Doctrine2 Seminário PHPDoctrine2 Seminário PHP
Doctrine2 Seminário PHP
 
IPC2010SE Doctrine2 Enterprise Persistence Layer for PHP
IPC2010SE Doctrine2 Enterprise Persistence Layer for PHPIPC2010SE Doctrine2 Enterprise Persistence Layer for PHP
IPC2010SE Doctrine2 Enterprise Persistence Layer for PHP
 
Doctrine 2.0: A evolução da persistência em PHP
Doctrine 2.0: A evolução da persistência em PHPDoctrine 2.0: A evolução da persistência em PHP
Doctrine 2.0: A evolução da persistência em PHP
 
PHP, Daemons e Multimedia
PHP, Daemons e MultimediaPHP, Daemons e Multimedia
PHP, Daemons e Multimedia
 
Doctrine 2.0 Enterprise Persistence Layer for PHP
Doctrine 2.0 Enterprise Persistence Layer for PHPDoctrine 2.0 Enterprise Persistence Layer for PHP
Doctrine 2.0 Enterprise Persistence Layer for PHP
 
Desenvolvimento Agil Com Doctrine Orm
Desenvolvimento Agil Com Doctrine OrmDesenvolvimento Agil Com Doctrine Orm
Desenvolvimento Agil Com Doctrine Orm
 

Recently uploaded

Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piececharlottematthew16
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Wonjun Hwang
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024The Digital Insurer
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
Vector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesVector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesZilliz
 

Recently uploaded (20)

Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piece
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
Vector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesVector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector Databases
 

ORM dont kill your DB, developers do

  • 1. ORM Database Developers http://www.flickr.com/photos/hoyvinmayvin/5103806609/ Guilherme Blanco Thursday, March 1, 2012
  • 2. ORMs donʼt kill your DB, developers do! @guilhermeblanco http://github.com/guilhermeblanco InstaClick Inc. Learning about good ORM practices on @guilhermeblanco talk at @confooca! Thursday, March 1, 2012
  • 3. Agenda http://www.flickr.com/photos/emerzh/3072428824/ Thursday, March 1, 2012
  • 4. General Rule RTFM Thursday, March 1, 2012
  • 5. Dependency management http://www.flickr.com/photos/ollesvensson/3694625903/ Thursday, March 1, 2012
  • 7. Dependency Management namespace AppBundleBlogBundleEntity; /**  * @ORMEntity  */ class Post {     /**      * @ORMOneToMany(      *   targetEntity="AppComment:Comment",      *   mappedBy="post"      * )      */     protected $comments; } namespace AppBundleCommentBundleEntity; /**  * @ORMEntity  */ class Comment {     /**      * @ORMManyToOne(      *   targetEntity="AppBlog:Post",      *   inversedBy="comments"      * )      */     protected $post; } Thursday, March 1, 2012
  • 10. Dependency Management namespace AppBundleBlogBundleEntity; /**  * @ORMEntity  */ class Post {     // ... } namespace AppBundleCommentBundleEntity; /**  * @ORMEntity  */ class Comment {     /**      * @ORMManyToOne(targetEntity="AppBlog:Post")      */     protected $post; } Thursday, March 1, 2012
  • 11. Fetch Mode http://www.flickr.com/photos/comedynose/5318259802/ Thursday, March 1, 2012
  • 12. Fetch Mode A fetching strategy is what ORM will use to retrieve associated objects if the application needs to navigate through them Thursday, March 1, 2012
  • 13. Fetch Mode Supported by all association types... Thursday, March 1, 2012
  • 14. Fetch Mode • OneToOne • OneToMany • ManyToOne • ManyToMany Thursday, March 1, 2012
  • 15. Fetch Mode Available fetch modes... Thursday, March 1, 2012
  • 16. Fetch Mode • EAGER • LAZY (default) • EXTRA_LAZY Thursday, March 1, 2012
  • 17. Fetch Mode An association (collection or attribute), is fetched immediately when owner is loaded • EAGER • LAZY (default) • EXTRA_LAZY Thursday, March 1, 2012
  • 18. Fetch Mode An association (collection or attribute), is fetched immediately when owner is loaded • EAGER An association (collection or attribute), • LAZY (default) is fetched when the application invokes an operation over it • EXTRA_LAZY Thursday, March 1, 2012
  • 19. Fetch Mode An association (collection or attribute), is fetched immediately when owner is loaded • EAGER An association (collection or attribute), • LAZY (default) is fetched when the application invokes an operation over it • EXTRA_LAZY Individual elements from association are accessed from Database as needed. ORM does not fetch the whole association unless it is absolutely necessary Thursday, March 1, 2012
  • 20. Fetch Mode /**  * @ORMEntity  */ class Post {     /**      * @ORMManyToOne(targetEntity="User", fetchMode="EAGER")      */     protected $author;     /**      * @ORMManyToMany(targetEntity="Tags", fetchMode="EXTRA_LAZY")      * @ORMJoinTable(name="posts_tags")      */     protected $tagList; } /**  * @ORMEntity  */ class Comment {     /**      * @ORMOneToMany(targetEntity="Post", fetchMode="LAZY")      * @JoinColumn(name="post_id", referencedColumnName="id")      */     protected $post; } Thursday, March 1, 2012
  • 21. Fetch Mode /**  * @ORMEntity  */ Deadly sin class Post {     /**      * @ORMManyToOne(targetEntity="User", fetchMode="EAGER")      */     protected $author;     /**      * @ORMManyToMany(targetEntity="Tags", fetchMode="EXTRA_LAZY")      * @ORMJoinTable(name="posts_tags")      */     protected $tagList; } /**  * @ORMEntity  */ class Comment {     /**      * @ORMOneToMany(targetEntity="Post", fetchMode="LAZY")      * @JoinColumn(name="post_id", referencedColumnName="id")      */     protected $post; } Thursday, March 1, 2012
  • 22. Querying http://www.flickr.com/photos/pschadler/4932737690/ Thursday, March 1, 2012
  • 23. Querying $query    = $entityManager->createQuery('     SELECT p        FROM Post p '); $postList = $query->getResult(); foreach ($postList as $post) {     $tagList = $post->getTagList();     foreach ($tagList as $tag) {         echo $tag->getName();     } } Thursday, March 1, 2012
  • 24. Querying $query    = $entityManager->createQuery('     SELECT p        FROM Post p '); $postList = $query->getResult(); foreach ($postList as $post) {     $tagList = $post->getTagList(); N + 1 trolls?     foreach ($tagList as $tag) {         echo $tag->getName();     } } Thursday, March 1, 2012
  • 25. Querying $query    = $entityManager->createQuery('     SELECT p, t        FROM Post p        LEFT JOIN p.tagList t '); $postList = $query->getResult(); foreach ($postList as $post) {     $tagList = $post->getTagList();     foreach ($tagList as $tag) {         echo $tag->getName();     } } Thursday, March 1, 2012
  • 26. Querying $query    = $entityManager->createQuery('     SELECT p, t        FROM Post p  Pardon? DQL is       LEFT JOIN p.tagList t '); powerful! RTFM $postList = $query->getResult(); foreach ($postList as $post) {     $tagList = $post->getTagList();     foreach ($tagList as $tag) {         echo $tag->getName();     } } Thursday, March 1, 2012
  • 27. Querying I know you all don’t trust me... Thursday, March 1, 2012
  • 28. Querying ...but take a look at its EBNF grammar... Thursday, March 1, 2012
  • 29. QueryLanguage ::= SelectStatement | UpdateStatement | DeleteStatement SelectStatement ::= SelectClause FromClause [WhereClause] [GroupByClause] [HavingClause] [OrderByClause] UpdateStatement ::= UpdateClause [WhereClause] DeleteStatement ::= DeleteClause [WhereClause] JoinAssociationPathExpression ::= IdentificationVariable "." (CollectionValuedAssociationField | SingleValuedAssociationField) AssociationPathExpression ::= CollectionValuedPathExpression | SingleValuedAssociationPathExpression SingleValuedPathExpression ::= StateFieldPathExpression | SingleValuedAssociationPathExpression StateFieldPathExpression ::= IdentificationVariable "." StateField | SingleValuedAssociationPathExpression "." StateField SingleValuedAssociationPathExpression ::= IdentificationVariable "." SingleValuedAssociationField CollectionValuedPathExpression ::= IdentificationVariable "." {SingleValuedAssociationField "."}* CollectionValuedAssociationField StateField ::= {EmbeddedClassStateField "."}* SimpleStateField SimpleStateFieldPathExpression ::= IdentificationVariable "." StateField SelectClause ::= "SELECT" ["DISTINCT"] SelectExpression {"," SelectExpression}* SimpleSelectClause ::= "SELECT" ["DISTINCT"] SimpleSelectExpression UpdateClause ::= "UPDATE" AbstractSchemaName ["AS"] AliasIdentificationVariable "SET" UpdateItem {"," UpdateItem}* DeleteClause ::= "DELETE" ["FROM"] AbstractSchemaName ["AS"] AliasIdentificationVariable FromClause ::= "FROM" IdentificationVariableDeclaration {"," IdentificationVariableDeclaration}* SubselectFromClause ::= "FROM" SubselectIdentificationVariableDeclaration {"," SubselectIdentificationVariableDeclaration}* WhereClause ::= "WHERE" ConditionalExpression HavingClause ::= "HAVING" ConditionalExpression GroupByClause ::= "GROUP" "BY" GroupByItem {"," GroupByItem}* OrderByClause ::= "ORDER" "BY" OrderByItem {"," OrderByItem}* Subselect ::= SimpleSelectClause SubselectFromClause [WhereClause] [GroupByClause] [HavingClause] [OrderByClause] UpdateItem ::= IdentificationVariable "." (StateField | SingleValuedAssociationField) "=" NewValue OrderByItem ::= (ResultVariable | SingleValuedPathExpression) ["ASC" | "DESC"] GroupByItem ::= IdentificationVariable | SingleValuedPathExpression NewValue ::= ScalarExpression | SimpleEntityExpression | "NULL" IdentificationVariableDeclaration ::= RangeVariableDeclaration [IndexBy] {JoinVariableDeclaration}* SubselectIdentificationVariableDeclaration ::= IdentificationVariableDeclaration | (AssociationPathExpression ["AS"] AliasIdentificationVariable) JoinVariableDeclaration ::= Join [IndexBy] RangeVariableDeclaration ::= AbstractSchemaName ["AS"] AliasIdentificationVariable Join ::= ["LEFT" ["OUTER"] | "INNER"] "JOIN" JoinAssociationPathExpression ["AS"] AliasIdentificationVariable ["WITH" ConditionalExpression] IndexBy ::= "INDEX" "BY" SimpleStateFieldPathExpression SelectExpression ::= IdentificationVariable | PartialObjectExpression | (AggregateExpression | "(" Subselect ")" | FunctionDeclaration | ScalarExpression) [["AS"] AliasResultVariable] SimpleSelectExpression ::= ScalarExpression | IdentificationVariable | (AggregateExpression [["AS"] AliasResultVariable]) PartialObjectExpression ::= "PARTIAL" IdentificationVariable "." PartialFieldSet PartialFieldSet ::= "{" SimpleStateField {"," SimpleStateField}* "}" ConditionalExpression ::= ConditionalTerm {"OR" ConditionalTerm}* ConditionalTerm ::= ConditionalFactor {"AND" ConditionalFactor}* ConditionalFactor ::= ["NOT"] ConditionalPrimary ConditionalPrimary ::= SimpleConditionalExpression | "(" ConditionalExpression ")" SimpleConditionalExpression ::= ComparisonExpression | BetweenExpression | LikeExpression | InExpression | NullComparisonExpression | ExistsExpression | EmptyCollectionComparisonExpression | CollectionMemberExpression | InstanceOfExpression EmptyCollectionComparisonExpression ::= CollectionValuedPathExpression "IS" ["NOT"] "EMPTY" CollectionMemberExpression ::= EntityExpression ["NOT"] "MEMBER" ["OF"] CollectionValuedPathExpression Literal ::= string | char | integer | float | boolean InParameter ::= Literal | InputParameter InputParameter ::= PositionalParameter | NamedParameter PositionalParameter ::= "?" integer NamedParameter ::= ":" string ArithmeticExpression ::= SimpleArithmeticExpression | "(" Subselect ")" SimpleArithmeticExpression ::= ArithmeticTerm {("+" | "-") ArithmeticTerm}* ArithmeticTerm ::= ArithmeticFactor {("*" | "/") ArithmeticFactor}* ArithmeticFactor ::= [("+" | "-")] ArithmeticPrimary ArithmeticPrimary ::= SingleValuedPathExpression | Literal | "(" SimpleArithmeticExpression ")" | FunctionsReturningNumerics | AggregateExpression | FunctionsReturningStrings | FunctionsReturningDatetime | IdentificationVariable | InputParameter | CaseExpression ScalarExpression ::= SimpleArithmeticExpression | StringPrimary | DateTimePrimary | StateFieldPathExpression | BooleanPrimary | EntityTypeExpression | CaseExpression StringExpression ::= StringPrimary | "(" Subselect ")" StringPrimary ::= StateFieldPathExpression | string | InputParameter | FunctionsReturningStrings | AggregateExpression | CaseExpression BooleanExpression ::= BooleanPrimary | "(" Subselect ")" BooleanPrimary ::= StateFieldPathExpression | boolean | InputParameter EntityExpression ::= SingleValuedAssociationPathExpression | SimpleEntityExpression SimpleEntityExpression ::= IdentificationVariable | InputParameter DatetimeExpression ::= DatetimePrimary | "(" Subselect ")" DatetimePrimary ::= StateFieldPathExpression | InputParameter | FunctionsReturningDatetime | AggregateExpression AggregateExpression ::= ("AVG" | "MAX" | "MIN" | "SUM") "(" ["DISTINCT"] StateFieldPathExpression ")" | "COUNT" "(" ["DISTINCT"] (IdentificationVariable | SingleValuedPathExpression) ")" CaseExpression ::= GeneralCaseExpression | SimpleCaseExpression | CoalesceExpression | NullifExpression GeneralCaseExpression ::= "CASE" WhenClause {WhenClause}* "ELSE" ScalarExpression "END" WhenClause ::= "WHEN" ConditionalExpression "THEN" ScalarExpression SimpleCaseExpression ::= "CASE" CaseOperand SimpleWhenClause {SimpleWhenClause}* "ELSE" ScalarExpression "END" CaseOperand ::= StateFieldPathExpression | TypeDiscriminator SimpleWhenClause ::= "WHEN" ScalarExpression "THEN" ScalarExpression CoalesceExpression ::= "COALESCE" "(" ScalarExpression {"," ScalarExpression}* ")" NullifExpression ::= "NULLIF" "(" ScalarExpression "," ScalarExpression ")" QuantifiedExpression ::= ("ALL" | "ANY" | "SOME") "(" Subselect ")" BetweenExpression ::= ArithmeticExpression ["NOT"] "BETWEEN" ArithmeticExpression "AND" ArithmeticExpression ComparisonExpression ::= ArithmeticExpression ComparisonOperator ( QuantifiedExpression | ArithmeticExpression ) InExpression ::= StateFieldPathExpression ["NOT"] "IN" "(" (InParameter {"," InParameter}* | Subselect) ")" InstanceOfExpression ::= IdentificationVariable ["NOT"] "INSTANCE" ["OF"] (InstanceOfParameter | "(" InstanceOfParameter {"," InstanceOfParameter}* ")") InstanceOfParameter ::= AbstractSchemaName | InputParameter LikeExpression ::= StringExpression ["NOT"] "LIKE" string ["ESCAPE" char] NullComparisonExpression ::= (SingleValuedPathExpression | InputParameter) "IS" ["NOT"] "NULL" ExistsExpression ::= ["NOT"] "EXISTS" "(" Subselect ")" ComparisonOperator ::= "=" | "<" | "<=" | "<>" | ">" | ">=" | "!=" FunctionDeclaration ::= FunctionsReturningStrings | FunctionsReturningNumerics | FunctionsReturningDateTime FunctionsReturningNumerics ::= "LENGTH" "(" StringPrimary ")" | "LOCATE" "(" StringPrimary "," StringPrimary ["," SimpleArithmeticExpression]")" | "ABS" "(" SimpleArithmeticExpression ")" | "SQRT" "(" SimpleArithmeticExpression ")" | "MOD" "(" SimpleArithmeticExpression "," SimpleArithmeticExpression ")" | "SIZE" "(" CollectionValuedPathExpression ")" FunctionsReturningDateTime ::= "CURRENT_DATE" | "CURRENT_TIME" | "CURRENT_TIMESTAMP" FunctionsReturningStrings ::= "CONCAT" "(" StringPrimary "," StringPrimary ")" | "SUBSTRING" "(" StringPrimary "," SimpleArithmeticExpression "," SimpleArithmeticExpression ")" | "TRIM" "(" [["LEADING" | "TRAILING" | "BOTH"] [char] "FROM"] StringPrimary ")" | "LOWER" "(" StringPrimary ")" | "UPPER" "(" StringPrimary ")" Thursday, March 1, 2012
  • 30. Querying Since the letter size is 6, you may still not believe me Thursday, March 1, 2012
  • 31. Querying let’s try a real world example! Thursday, March 1, 2012
  • 32. Querying Do you know Facebook activity wall? Thursday, March 1, 2012
  • 33. Querying Do you know Facebook activity wall? Let’s show it! Thursday, March 1, 2012
  • 34. SELECT e, a FROM Entry e JOIN e.wall w JOIN e.user u LEFT JOIN u.avatar av WHERE u = :user OR w IN ( SELECT uw FROM UserWall uw WHERE uw.user = :user OR uw.user IN ( SELECT CASE WHEN ua = us.subscriber THEN ub.id ELSE ua.id END FROM UserSubscription us JOIN us.friendship f JOIN f.userA ua JOIN f.userB ub WHERE us.muted = FALSE AND us.subscriber = :user AND f.status = 'Approved' ) ) OR w IN ( SELECT gw FROM GroupWall gw WHERE gw.group IN ( SELECT DISTINCT g.id FROM GroupSubscription gs JOIN gs.group g WHERE gs.subscriber = :user AND gs.muted = FALSE AND gs.status = 'Approved' ) ) ORDER BY e.created DESC Thursday, March 1, 2012
  • 35. SELECT e, a FROM Entry e JOIN e.wall w Entry you wrote JOIN e.user u LEFT JOIN u.avatar av WHERE u = :user OR w IN ( SELECT uw FROM UserWall uw WHERE uw.user = :user OR uw.user IN ( SELECT CASE WHEN ua = us.subscriber THEN ub.id ELSE ua.id END FROM UserSubscription us JOIN us.friendship f JOIN f.userA ua JOIN f.userB ub WHERE us.muted = FALSE AND us.subscriber = :user AND f.status = 'Approved' ) ) OR w IN ( SELECT gw FROM GroupWall gw WHERE gw.group IN ( SELECT DISTINCT g.id FROM GroupSubscription gs JOIN gs.group g WHERE gs.subscriber = :user AND gs.muted = FALSE AND gs.status = 'Approved' ) ) ORDER BY e.created DESC Thursday, March 1, 2012
  • 36. SELECT e, a FROM Entry e JOIN e.wall w Entry you wrote JOIN e.user u LEFT JOIN u.avatar av WHERE u = :user OR w IN ( Entry was in your Wall SELECT uw FROM UserWall uw WHERE uw.user = :user OR uw.user IN ( SELECT CASE WHEN ua = us.subscriber THEN ub.id ELSE ua.id END FROM UserSubscription us JOIN us.friendship f JOIN f.userA ua JOIN f.userB ub WHERE us.muted = FALSE AND us.subscriber = :user AND f.status = 'Approved' ) ) OR w IN ( SELECT gw FROM GroupWall gw WHERE gw.group IN ( SELECT DISTINCT g.id FROM GroupSubscription gs JOIN gs.group g WHERE gs.subscriber = :user AND gs.muted = FALSE AND gs.status = 'Approved' ) ) ORDER BY e.created DESC Thursday, March 1, 2012
  • 37. SELECT e, a FROM Entry e JOIN e.wall w Entry you wrote JOIN e.user u LEFT JOIN u.avatar av WHERE u = :user OR w IN ( Entry was in your Wall SELECT uw FROM UserWall uw WHERE uw.user = :user OR uw.user IN ( SELECT CASE WHEN ua = us.subscriber THEN ub.id ELSE ua.id END FROM UserSubscription us User is your friend, the friendship is JOIN us.friendship f approved and subscription is not muted JOIN f.userA ua JOIN f.userB ub WHERE us.muted = FALSE AND us.subscriber = :user AND f.status = 'Approved' ) ) OR w IN ( SELECT gw FROM GroupWall gw WHERE gw.group IN ( SELECT DISTINCT g.id FROM GroupSubscription gs JOIN gs.group g WHERE gs.subscriber = :user AND gs.muted = FALSE AND gs.status = 'Approved' ) ) ORDER BY e.created DESC Thursday, March 1, 2012
  • 38. SELECT e, a FROM Entry e JOIN e.wall w Entry you wrote JOIN e.user u LEFT JOIN u.avatar av WHERE u = :user OR w IN ( Entry was in your Wall SELECT uw FROM UserWall uw WHERE uw.user = :user OR uw.user IN ( SELECT CASE WHEN ua = us.subscriber THEN ub.id ELSE ua.id END FROM UserSubscription us User is your friend, the friendship is JOIN us.friendship f approved and subscription is not muted JOIN f.userA ua JOIN f.userB ub WHERE us.muted = FALSE AND us.subscriber = :user AND f.status = 'Approved' ) ) OR w IN ( SELECT gw FROM GroupWall gw WHERE gw.group IN ( SELECT DISTINCT g.id FROM GroupSubscription gs JOIN gs.group g Group that you participate, is not WHERE gs.subscriber = :user AND gs.muted = FALSE muted and have an approved status AND gs.status = 'Approved' ) ) ORDER BY e.created DESC Thursday, March 1, 2012
  • 39. Caching http://www.flickr.com/photos/eszter/3851576235/ Thursday, March 1, 2012
  • 40. Caching Doctrine supports 3 levels of caching... Thursday, March 1, 2012
  • 41. Caching • Metadata cache • Query cache • Result cache Thursday, March 1, 2012
  • 42. Caching Cache mapping of entities • Metadata cache • Query cache • Result cache Thursday, March 1, 2012
  • 43. Caching Cache mapping of entities • Metadata cache • Query cache Cache DQL to SQL conversion • Result cache Thursday, March 1, 2012
  • 44. Caching Cache mapping of entities • Metadata cache • Query cache Cache DQL to SQL conversion • Result cache Cache PDO result set Thursday, March 1, 2012
  • 45. Caching $query   = $entityManager->createQuery('     SELECT p        FROM Post p '); $query->useResultCache(true, 600, 'find-all-posts'); $postList = $query->getResult(); Thursday, March 1, 2012
  • 46. Indexing http://www.flickr.com/photos/osuarchives/2659419894/ Thursday, March 1, 2012
  • 47. Indexing Doctrine is able to hint the Schema Tool to generate database indexes on specified table columns Thursday, March 1, 2012
  • 48. Indexing /**  * @ORMEntity  * @ORMTable(  *     name = "users",  *     uniqueConstraints = {  *         @ORMUniqueConstraint(  *             name    = "user_unique",  *             columns = { "name" }  *         )  *     },  *     indexes = {  *         @ORMIndex(  *             name    = "login_idx",   *             columns = { "name", "password" }  *         )  *     }  * )  */ class User {     // ... } Thursday, March 1, 2012
  • 49. Indexing @ORMUniqueConstraint(     name    = "user_unique",      columns = { "name" } ) CREATE UNIQUE INDEX user_unique ON TABLE users (name); Thursday, March 1, 2012
  • 50. Indexing @ORMIndex(     name    = "login_idx",      columns = { "name", "password" } ) CREATE INDEX login_idx ON TABLE users (name, password); Thursday, March 1, 2012
  • 51. Indexing @ORMIndex(     name    = "login_idx",      columns = { "name", "password" } ) Some drivers restrict to 32 chars as index name CREATE INDEX login_idx ON TABLE users (name, password); Thursday, March 1, 2012
  • 52. Inheritance http://www.flickr.com/photos/duanekeys/307005468/ Thursday, March 1, 2012
  • 53. Inheritance Inheritance is a very deep topic in ORMs Thursday, March 1, 2012
  • 54. Inheritance Each inheritance type has advantages and disadvantages Thursday, March 1, 2012
  • 55. Inheritance • Concrete Table Inheritance • Single Table Inheritance • Class Table Inheritance Thursday, March 1, 2012
  • 56. Inheritance One Class, one Table • Concrete Table Inheritance • Single Table Inheritance • Class Table Inheritance Thursday, March 1, 2012
  • 57. Inheritance One Class, one Table • Concrete Table Inheritance • Single Table Inheritance Multiple Classes, one Table • Class Table Inheritance Thursday, March 1, 2012
  • 58. Inheritance One Class, one Table • Concrete Table Inheritance • Single Table Inheritance Multiple Classes, one Table • Class Table Inheritance Multiple Classes, multiple Tables Thursday, March 1, 2012
  • 59. Inheritance • Concrete Table Inheritance Thursday, March 1, 2012
  • 60. Inheritance • Concrete Table Inheritance • Pros Thursday, March 1, 2012
  • 61. Inheritance • Concrete Table Inheritance • Pros • No locking problems Thursday, March 1, 2012
  • 62. Inheritance • Concrete Table Inheritance • Pros • No locking problems • No irrelevant columns Thursday, March 1, 2012
  • 63. Inheritance • Concrete Table Inheritance • Pros • No locking problems • No irrelevant columns • Cons Thursday, March 1, 2012
  • 64. Inheritance • Concrete Table Inheritance • Pros • No locking problems • No irrelevant columns • Cons • Difficult to deal with primary keys Thursday, March 1, 2012
  • 65. Inheritance • Concrete Table Inheritance • Pros • No locking problems • No irrelevant columns • Cons • Difficult to deal with primary keys • Search base class means search all tables Thursday, March 1, 2012
  • 66. Inheritance • Concrete Table Inheritance • Pros • No locking problems • No irrelevant columns • Cons • Difficult to deal with primary keys • Search base class means search all tables • Update on columns means update on all hierarchy tables Thursday, March 1, 2012
  • 67. Inheritance /**  * @ORMMappedSuperclass  */ class Person {     /**      * @ORMColumn(type="string", length=50)      */     protected $firstName;     /**      * @ORMColumn(type="string", length=50)      */     protected $lastName; } /**  * @ORMEntity  * @ORMTable(name="users")  */ class User extends Person {     /**      * @ORMId      * @ORMGeneratedValue      * @ORMColumn(type="integer")      */     protected $id; } Thursday, March 1, 2012
  • 68. Inheritance CREATE TABLE users ( id INTEGER AUTO_INCREMENT NOT NULL, firstName VARCHAR(50) NOT NULL, lastName VARCHAR(50) NOT NULL, PRIMARY KEY (id) ) ENGINE=InnoDB; Thursday, March 1, 2012
  • 69. Inheritance • Single Table Inheritance Thursday, March 1, 2012
  • 70. Inheritance • Single Table Inheritance • Pros Thursday, March 1, 2012
  • 71. Inheritance • Single Table Inheritance • Pros • Only one table for hierarchy Thursday, March 1, 2012
  • 72. Inheritance • Single Table Inheritance • Pros • Only one table for hierarchy • No joins Thursday, March 1, 2012
  • 73. Inheritance • Single Table Inheritance • Pros • Only one table for hierarchy • No joins • Refactoring of fields means no change to database table Thursday, March 1, 2012
  • 74. Inheritance • Single Table Inheritance • Pros • Only one table for hierarchy • No joins • Refactoring of fields means no change to database table • Cons Thursday, March 1, 2012
  • 75. Inheritance • Single Table Inheritance • Pros • Only one table for hierarchy • No joins • Refactoring of fields means no change to database table • Cons • Waste of space in database Thursday, March 1, 2012
  • 76. Inheritance • Single Table Inheritance • Pros • Only one table for hierarchy • No joins • Refactoring of fields means no change to database table • Cons • Waste of space in database • Too many locks due to many accesses Thursday, March 1, 2012
  • 77. Inheritance • Single Table Inheritance • Pros • Only one table for hierarchy • No joins • Refactoring of fields means no change to database table • Cons • Waste of space in database • Too many locks due to many accesses • No duplicated field names with different meanings Thursday, March 1, 2012
  • 78. Inheritance namespace MyAppEntity; /**  * @ORMEntity * @ORMTable(name= "people")  * @ORMInheritanceType("SINGLE_TABLE")  * @ORMDiscriminatorColumn(name="discr", type="string")  * @ORMDiscriminatorMap({  *     "user"     = "MyAppEntityUser",  *     "employee" = "MyAppEntityEmployee"  * })  */ class User {     // ... } /**  * @ORMEntity  */ class Employee extends User {      // ... } Thursday, March 1, 2012
  • 79. Inheritance CREATE TABLE people ( id INT AUTO_INCREMENT NOT NULL, firstName VARCHAR(50) NOT NULL, lastName VARCHAR(50) NOT NULL, discr VARCHAR(20) NOT NULL, role VARCHAR(100) DEFAULT NULL, PRIMARY KEY (id) ) ENGINE=InnoDB; Thursday, March 1, 2012
  • 80. Inheritance • Class Table Inheritance Thursday, March 1, 2012
  • 81. Inheritance • Class Table Inheritance • Pros Thursday, March 1, 2012
  • 82. Inheritance • Class Table Inheritance • Pros • Easy to understand Thursday, March 1, 2012
  • 83. Inheritance • Class Table Inheritance • Pros • Easy to understand • Database space is optimized due to table normalization Thursday, March 1, 2012
  • 84. Inheritance • Class Table Inheritance • Pros • Easy to understand • Database space is optimized due to table normalization • Direct relationship between Domain Model and Database Thursday, March 1, 2012
  • 85. Inheritance • Class Table Inheritance • Pros • Easy to understand • Database space is optimized due to table normalization • Direct relationship between Domain Model and Database • Cons Thursday, March 1, 2012
  • 86. Inheritance • Class Table Inheritance • Pros • Easy to understand • Database space is optimized due to table normalization • Direct relationship between Domain Model and Database • Cons • Too many joins Thursday, March 1, 2012
  • 87. Inheritance • Class Table Inheritance • Pros • Easy to understand • Database space is optimized due to table normalization • Direct relationship between Domain Model and Database • Cons • Too many joins • Refactoring of fields needs a database schema update Thursday, March 1, 2012
  • 88. Inheritance • Class Table Inheritance • Pros • Easy to understand • Database space is optimized due to table normalization • Direct relationship between Domain Model and Database • Cons • Too many joins • Refactoring of fields needs a database schema update • Superclass table accessed a lot, it means it may enter in lock mode Thursday, March 1, 2012
  • 89. Inheritance namespace MyAppEntity; /**  * @ORMEntity * @ORMTable(name="users")  * @ORMInheritanceType("JOINED")  * @ORMDiscriminatorColumn( * name = "discr",  * type = "string", * length = 20 * )  * @ORMDiscriminatorMap({  *     "user"     = "MyAppEntityUser",  *     "employee" = "MyAppEntityEmployee"  * })  */ class User {     // ... } /**  * @ORMEntity  * @ORMTable(name= "employees")  */ class Employee extends User {      // ... } Thursday, March 1, 2012
  • 90. Inheritance CREATE TABLE users ( id INT AUTO_INCREMENT NOT NULL, firstName VARCHAR(50) NOT NULL, lastName VARCHAR(50) NOT NULL, discr VARCHAR(20) NOT NULL, PRIMARY KEY (id) ) ENGINE = InnoDB; CREATE TABLE employees ( id INT NOT NULL, role VARCHAR(100) NOT NULL, PRIMARY KEY (id) ) ENGINE = InnoDB; ALTER TABLE employees ADD CONSTRAINT FK_BA82C300BF396750 FOREIGN KEY (id) REFERENCES users (id) ON DELETE CASCADE; Thursday, March 1, 2012
  • 91. Inheritance What’s the problem with inheritance? Thursday, March 1, 2012
  • 92. Inheritance What’s the problem with inheritance? Hydration Thursday, March 1, 2012
  • 94. Inheritance • Inverse side *ToOne Thursday, March 1, 2012
  • 95. Inheritance • Inverse side *ToOne • Owning side *ToOne with Inheritance Thursday, March 1, 2012
  • 96. Inheritance • Inverse side *ToOne • Owning side *ToOne with Inheritance • Disabled deferEagerLoad while Querying Thursday, March 1, 2012
  • 97. Cascades http://www.flickr.com/photos/over_kind_man/3158552109/ Thursday, March 1, 2012
  • 98. Cascades Ability to tell Unit Of Work of Doctrine how it should act when inspecting an association for graph changes Thursday, March 1, 2012
  • 99. Cascades Use judiciously Thursday, March 1, 2012
  • 100. Cascades It can heavily increase the graph edges to be navigated once the Compute Changeset algorithm is ran Thursday, March 1, 2012
  • 101. Cascades This means more time to persist, delete, merge, detach, refresh... Thursday, March 1, 2012
  • 102. Cascades /**  * @ORMEntity  */ class User {     //...     /**      * Bidirectional - One-To-Many (INVERSE SIDE)      *      * @ORMOneToMany(      *     targetEntity = "Comment",       *     mappedBy     = "author",       *     cascade  = { "persist", "remove" }      * )      */     protected $commentsAuthored; } Thursday, March 1, 2012
  • 103. Hydrators http://crimsonnightstock.deviantart.com/art/Yellow-Fire-Hydrant-Stock-100121929 Thursday, March 1, 2012
  • 104. Hydrators Doctrine comes with some useful result hydrators Thursday, March 1, 2012
  • 105. Hydrators This means that not all times you need to retrieve objects Thursday, March 1, 2012
  • 106. Hydrators • Object • Array • Scalar • Iterable • Simple Object • Single Scalar Thursday, March 1, 2012
  • 107. Hydrators • Object $resultList = $query->getResult(); • Array • Scalar • Iterable • Simple Object • Single Scalar Thursday, March 1, 2012
  • 108. Hydrators • Object $resultList = $query->getResult(); • Array $resultArray = $query->getArrayResult(); • Scalar • Iterable • Simple Object • Single Scalar Thursday, March 1, 2012
  • 109. Hydrators • Object $resultList = $query->getResult(); • Array $resultArray = $query->getArrayResult(); • Scalar $result = $query->getScalarResult(); • Iterable • Simple Object • Single Scalar Thursday, March 1, 2012
  • 110. Hydrators • Object $resultList = $query->getResult(); • Array $resultArray = $query->getArrayResult(); • Scalar $result = $query->getScalarResult(); • Iterable $iterator = $query->iterate(); • Simple Object • Single Scalar Thursday, March 1, 2012
  • 111. Hydrators • Object $resultList = $query->getResult(); • Array $resultArray = $query->getArrayResult(); • Scalar $result = $query->getScalarResult(); • Iterable $iterator = $query->iterate(); • Simple Object $result = $query->getSingleResult(); • Single Scalar Thursday, March 1, 2012
  • 112. Hydrators • Object $resultList = $query->getResult(); • Array $resultArray = $query->getArrayResult(); • Scalar $result = $query->getScalarResult(); • Iterable $iterator = $query->iterate(); • Simple Object $result = $query->getSingleResult(); • Single Scalar $result = $query->getSingleScalarResult(); Thursday, March 1, 2012
  • 113. http://joind.in/6053 Questions? @guilhermeblanco http://github.com/guilhermeblanco InstaClick Inc. Thursday, March 1, 2012
  • 114. http://joind.in/6053 Questions? @guilhermeblanco http://github.com/guilhermeblanco InstaClick Inc. We are hiring! Talk to me privately if interested Thursday, March 1, 2012
  • 115. http://joind.in/6053 Questions? Thank you! @guilhermeblanco http://github.com/guilhermeblanco InstaClick Inc. We are hiring! Talk to me privately if interested Thursday, March 1, 2012