SlideShare a Scribd company logo
1 of 81
Download to read offline
Performance Anti-Patterns
 in Hibernate
 Patrycja Wegrzynowicz
 CTO
 Yonita, Inc.


Tuesday, November 22, 2011
About Me
   • 10+ years of professional experience
   • PhD in Computer Science
         –Patterns and anti-patterns, static and dynamic code
          analysis, language semantics, compiler design
   • Active author and speaker
         –JavaOne, Devoxx, JavaZone, Jazoon, OOPSLA, ASE...
   • CTO of Yonita, Inc.
         –Bridge the gap between the industry and the academia
         –Automated defects detection and optimization
         –Performance, security, concurrency, databases
   • Twitter @yonlabs                                           2

Tuesday, November 22, 2011
Agenda


   • 4 puzzles
         –Short program with curious behavior
         –Question to you (multiple choice)
         –Mystery revealed
         –Lessons learned
   • 7 performance anti-patterns
         –Description, consequences, solutions


                                                 3

Tuesday, November 22, 2011
Disclaimer




                             I do think Hibernate is a great tool!




                                                                     4

Tuesday, November 22, 2011
5

Tuesday, November 22, 2011
5

Tuesday, November 22, 2011
5

Tuesday, November 22, 2011
Puzzle #1
                                 Less Is More




Tuesday, November 22, 2011
Who knows CaveatEmptor app?




                                                           7

Tuesday, November 22, 2011
Who’s read Java Persistence
                                   with Hibernate?




                                                           8

Tuesday, November 22, 2011
CaveatEmptor



   • Demo application from
     ‘Java Persistence with
     Hibernate’
   • Simple auction system



                              9

Tuesday, November 22, 2011
I’m Gonna Win This Auction!


   public class PlaceBidAction implements Action {
      // invoked in a new transaction
      public String execute(Map even) {
          // ...
          Bid currentMinBid = itemDAO.getMinBid(itemId);
          Bid currentMaxBid = itemDAO.getMaxBid(itemId);

                // uses load with Lock.UPGRADE
                Item item = itemDAO.findById(itemId, true);
                Bid newBid = item.placeBid(userDAO.findById(userId, false),
                                   newAmount,
                                   currentMaxBid,
                                   currentMinBid);
                // ...
       }
   }




                                                                              10

Tuesday, November 22, 2011
What’s the Problem?

                                                              (a) None (code is correct)
                                                              (b) Transaction/lock mgmt
   public class PlaceBidAction implements Action {            (c) Exception thrown
      // invoked in a new transaction                         (d) None of the above
      public String execute(Map even) {
          // ...
          Bid currentMinBid = itemDAO.getMinBid(itemId);
          Bid currentMaxBid = itemDAO.getMaxBid(itemId);

                // uses load with Lock.UPGRADE
                Item item = itemDAO.findById(itemId, true);
                Bid newBid = item.placeBid(userDAO.findById(userId, false),
                                   newAmount,
                                   currentMaxBid,
                                   currentMinBid);
                // ...
       }
   }




                                                                                           11

Tuesday, November 22, 2011
What’s the Problem?

   (a) None (the code is correct)
   (b) Transaction/Lock management
   (c) Exception thrown
   (d) None of the above




       The bids can change between calling getMaxBid
       and locking the item.
                                                   12

Tuesday, November 22, 2011
Another Look


   public class PlaceBidAction implements Action {
       // invoked in a new transaction
       public String execute(Map even) {
          // ...
          Bid currentMinBid = itemDAO.getMinBid(itemId);
          Bid currentMaxBid = itemDAO.getMaxBid(itemId);
          // here, the bids can be modified by a different transaction
          // uses load with Lock.UPGRADE
          Item item = itemDAO.findById(itemId, true);
          Bid newBid = item.placeBid(userDAO.findById(userId, false),
                             newAmount,
                             currentMaxBid,
                             currentMinBid);
          // ...
     }
   }




                                                                         13

Tuesday, November 22, 2011
2 Users and Item with 2 Bids
             Thread A (new amount 100)   Thread B (new amount 30)

                   (1)
   // begin transaction
   // item with 2 bids: 10,20
   Bid curMax = dao.getMaxBid(id);
   // curMax = 20




                                                                    14

Tuesday, November 22, 2011
2 Users and Item with 2 Bids
             Thread A (new amount 100)        Thread B (new amount 30)

                   (1)                                   (2)
   // begin transaction                  // begin transaction
   // item with 2 bids: 10,20            // item with 2 bids: 10,20
   Bid curMax = dao.getMaxBid(id);       Bid curMax = dao.getMaxBid(id);
   // curMax = 20                        // curMax = 20




                                                                           15

Tuesday, November 22, 2011
2 Users and Item with 2 Bids
             Thread A (new amount 100)         Thread B (new amount 30)

                   (1)                                    (2)
   // begin transaction                   // begin transaction
   // item with 2 bids: 10,20             // item with 2 bids: 10,20
   Bid curMax = dao.getMaxBid(id);        Bid curMax = dao.getMaxBid(id);
   // curMax = 20                         // curMax = 20

                   (3)
   // item with 2 bids: 10,20
   // Lock.UPGRADE
   Item item = dao.findById(id,true);
   Bid newBid = item.placeBid(...,
                newAmount,
                curMax, ...);
   // commit transaction
   // item with 3 bids: 10,20,100

                    Successful bid: 100




                                                                            16

Tuesday, November 22, 2011
2 Users and Item with 2 Bids
             Thread A (new amount 100)         Thread B (new amount 30)

                   (1)                                    (2)
   // begin transaction                   // begin transaction
   // item with 2 bids: 10,20             // item with 2 bids: 10,20
   Bid curMax = dao.getMaxBid(id);        Bid curMax = dao.getMaxBid(id);
   // curMax = 20                         // curMax = 20

                   (3)                                    (4)
   // item with 2 bids: 10,20             // item with 3 bids: 10,20,100
   // Lock.UPGRADE                        // Lock.UPGRADE
   Item item = dao.findById(id,true);     Item item = dao.findById(id,true);
   Bid newBid = item.placeBid(...,        Bid newBid = item.placeBid(...,
                newAmount,                             newAmount,
                curMax, ...);                          curMax, ...);
   // commit transaction                  // commit transaction
   // item with 3 bids: 10,20,100         // item with 4 bids: 10,20,100,30

                    Successful bid: 100           Successful bid: 30




                                                                               17

Tuesday, November 22, 2011
How To Fix It?


   public class PlaceBidAction implements Action {
      // invoked in a new transaction
      public String execute(Map even) {
          // ...
          Bid currentMinBid = itemDAO.getMinBid(itemId);
          Bid currentMaxBid = itemDAO.getMaxBid(itemId);

                // uses load with Lock.UPGRADE
                Item item = itemDAO.findById(itemId, true);
                Bid newBid = item.placeBid(userDAO.findById(userId, false),
                                   newAmount,
                                   currentMaxBid,
                                   currentMinBid);
                // ...
       }
   }




                                                                              18

Tuesday, November 22, 2011
How To Fix It?
                                                                          version and
                                                                       optimistic locking

   public class PlaceBidAction implements Action {
      // invoked in a new transaction
      public String execute(Map even) {
          // ...
          Bid currentMinBid = itemDAO.getMinBid(itemId);
          Bid currentMaxBid = itemDAO.getMaxBid(itemId);

                // uses load with Lock.UPGRADE
                Item item = itemDAO.findById(itemId, true);
                Bid newBid = item.placeBid(userDAO.findById(userId, false),
                                   newAmount,
                                   currentMaxBid,
                                   currentMinBid);
                // ...
       }
   }




                                                                                            18

Tuesday, November 22, 2011
How To Fix It?
                                                                          version and
                                                                              NO
                                                                       optimistic locking

   public class PlaceBidAction implements Action {
      // invoked in a new transaction
      public String execute(Map even) {
          // ...
          Bid currentMinBid = itemDAO.getMinBid(itemId);
          Bid currentMaxBid = itemDAO.getMaxBid(itemId);

                // uses load with Lock.UPGRADE
                Item item = itemDAO.findById(itemId, true);
                Bid newBid = item.placeBid(userDAO.findById(userId, false),
                                   newAmount,
                                   currentMaxBid,
                                   currentMinBid);
                // ...
       }
   }




                                                                                            18

Tuesday, November 22, 2011
How To Fix It?
                                                                          version and
                                                                              NO
                                                                       optimistic locking

                                                                         REPEATABLE
   public class PlaceBidAction implements Action {
      // invoked in a new transaction                                      READS
      public String execute(Map even) {
          // ...
          Bid currentMinBid = itemDAO.getMinBid(itemId);
          Bid currentMaxBid = itemDAO.getMaxBid(itemId);

                // uses load with Lock.UPGRADE
                Item item = itemDAO.findById(itemId, true);
                Bid newBid = item.placeBid(userDAO.findById(userId, false),
                                   newAmount,
                                   currentMaxBid,
                                   currentMinBid);
                // ...
       }
   }




                                                                                            18

Tuesday, November 22, 2011
How To Fix It?
                                                                          version and
                                                                              NO
                                                                       optimistic locking

                                                                         REPEATABLE
   public class PlaceBidAction implements Action {
      // invoked in a new transaction                                      READS
      public String execute(Map even) {
          // ...
                                                                        SERIALIZABLE
          Bid currentMinBid = itemDAO.getMinBid(itemId);
          Bid currentMaxBid = itemDAO.getMaxBid(itemId);

                // uses load with Lock.UPGRADE
                Item item = itemDAO.findById(itemId, true);
                Bid newBid = item.placeBid(userDAO.findById(userId, false),
                                   newAmount,
                                   currentMaxBid,
                                   currentMinBid);
                // ...
       }
   }




                                                                                            18

Tuesday, November 22, 2011
How To Fix It?
                                                                          version and
                                                                              NO
                                                                       optimistic locking

                                                                         REPEATABLE
   public class PlaceBidAction implements Action {                           NO
      // invoked in a new transaction                                      READS
      public String execute(Map even) {
          // ...
                                                                        SERIALIZABLE
          Bid currentMinBid = itemDAO.getMinBid(itemId);
          Bid currentMaxBid = itemDAO.getMaxBid(itemId);

                // uses load with Lock.UPGRADE
                Item item = itemDAO.findById(itemId, true);
                Bid newBid = item.placeBid(userDAO.findById(userId, false),
                                   newAmount,
                                   currentMaxBid,
                                   currentMinBid);
                // ...
       }
   }




                                                                                            18

Tuesday, November 22, 2011
How To Fix It?
                                                                          version and
                                                                              NO
                                                                       optimistic locking

                                                                         REPEATABLE
   public class PlaceBidAction implements Action {                           NO
      // invoked in a new transaction                                      READS
      public String execute(Map even) {
          // ...
                                                                        SERIALIZABLE
                                                                            YES
          Bid currentMinBid = itemDAO.getMinBid(itemId);
          Bid currentMaxBid = itemDAO.getMaxBid(itemId);

                // uses load with Lock.UPGRADE
                Item item = itemDAO.findById(itemId, true);
                Bid newBid = item.placeBid(userDAO.findById(userId, false),
                                   newAmount,
                                   currentMaxBid,
                                   currentMinBid);
                // ...
       }
   }




                                                                                            18

Tuesday, November 22, 2011
How To Fix It?
                                                                          version and
                                                                              NO
                                                                       optimistic locking

                                                                         REPEATABLE
   public class PlaceBidAction implements Action {                           NO
      // invoked in a new transaction                                      READS
      public String execute(Map even) {
          // ...
                                                                        SERIALIZABLE
                                                                            YES
          Bid currentMinBid = itemDAO.getMinBid(itemId);
          Bid currentMaxBid = itemDAO.getMaxBid(itemId);               move lock before
                // uses load with Lock.UPGRADE                           getMinBid/
                Item item = itemDAO.findById(itemId, true);              getMaxBid
                Bid newBid = item.placeBid(userDAO.findById(userId, false),
                                   newAmount,
                                   currentMaxBid,
                                   currentMinBid);
                // ...
       }
   }




                                                                                            18

Tuesday, November 22, 2011
How To Fix It?
                                                                          version and
                                                                              NO
                                                                       optimistic locking

                                                                         REPEATABLE
   public class PlaceBidAction implements Action {                           NO
      // invoked in a new transaction                                      READS
      public String execute(Map even) {
          // ...
                                                                        SERIALIZABLE
                                                                            YES
          Bid currentMinBid = itemDAO.getMinBid(itemId);
          Bid currentMaxBid = itemDAO.getMaxBid(itemId);               move lock before
                // uses load with Lock.UPGRADE                           getMinBid/
                                                                            YES
                Item item = itemDAO.findById(itemId, true);              getMaxBid
                Bid newBid = item.placeBid(userDAO.findById(userId, false),
                                   newAmount,
                                   currentMaxBid,
                                   currentMinBid);
                // ...
       }
   }




                                                                                            18

Tuesday, November 22, 2011
How To Fix It?
                                                                          version and
                                                                              NO
                                                                       optimistic locking

                                                                        REPEATABLE
   public class PlaceBidAction implements Action {                          NO
      // invoked in a new transaction                                     READS
      public String execute(Map even) {
          // ...
                                                                        SERIALIZABLE
                                                                            YES
          Bid currentMinBid = itemDAO.getMinBid(itemId);
          Bid currentMaxBid = itemDAO.getMaxBid(itemId);               move lock before
                // uses load with Lock.UPGRADE                           getMinBid/
                                                                            YES
                Item item = itemDAO.findById(itemId, true);              getMaxBid
                Bid newBid = item.placeBid(userDAO.findById(userId, false),
                                   newAmount,
                                   currentMaxBid,                           different
                                   currentMinBid);                        object model
                // ...
       }
   }




                                                                                            18

Tuesday, November 22, 2011
How To Fix It?
                                                                          version and
                                                                              NO
                                                                       optimistic locking

                                                                        REPEATABLE
   public class PlaceBidAction implements Action {                          NO
      // invoked in a new transaction                                     READS
      public String execute(Map even) {
          // ...
                                                                        SERIALIZABLE
                                                                            YES
          Bid currentMinBid = itemDAO.getMinBid(itemId);
          Bid currentMaxBid = itemDAO.getMaxBid(itemId);               move lock before
                // uses load with Lock.UPGRADE                           getMinBid/
                                                                            YES
                Item item = itemDAO.findById(itemId, true);              getMaxBid
                Bid newBid = item.placeBid(userDAO.findById(userId, false),
                                   newAmount,
                                   currentMaxBid,                           different
                                                                              YES
                                   currentMinBid);                        object model
                // ...
       }
   }




                                                                                            18

Tuesday, November 22, 2011
How To Fix It?
                                                                          version and
                                                                              NO
                                                                       optimistic locking

                                                                        REPEATABLE
   public class PlaceBidAction implements Action {                          NO
      // invoked in a new transaction                                     READS
      public String execute(Map even) {
          // ...
                                                                        SERIALIZABLE
                                                                            YES
          Bid currentMinBid = itemDAO.getMinBid(itemId);
          Bid currentMaxBid = itemDAO.getMaxBid(itemId);               move lock before
                // uses load with Lock.UPGRADE                           getMinBid/
                                                                            YES
                Item item = itemDAO.findById(itemId, true);              getMaxBid
                Bid newBid = item.placeBid(userDAO.findById(userId, false),
                                   newAmount,
                                   currentMaxBid,                           different
                                                                              YES
                                   currentMinBid);                        object model
                // ...
       }
   }                                                                         Java
                                                                         synchronized


                                                                                            18

Tuesday, November 22, 2011
How To Fix It?
                                                                          version and
                                                                              NO
                                                                       optimistic locking

                                                                        REPEATABLE
   public class PlaceBidAction implements Action {                          NO
      // invoked in a new transaction                                     READS
      public String execute(Map even) {
          // ...
                                                                        SERIALIZABLE
                                                                            YES
          Bid currentMinBid = itemDAO.getMinBid(itemId);
          Bid currentMaxBid = itemDAO.getMaxBid(itemId);               move lock before
                // uses load with Lock.UPGRADE                           getMinBid/
                                                                            YES
                Item item = itemDAO.findById(itemId, true);              getMaxBid
                Bid newBid = item.placeBid(userDAO.findById(userId, false),
                                   newAmount,
                                   currentMaxBid,                           different
                                                                              YES
                                   currentMinBid);                        object model
                // ...
       }
                                                                             Java
   }                                                                         YES
                                                                         synchronized


                                                                                            18

Tuesday, November 22, 2011
Lessons Learned

   • Nobody’s perfect ;-)
   • ACID is only a theory
         –Simple transaction interceptor/annotation often is not
          enough
         –Query order does matter
         –Learn more about locks and transaction isolation levels
   • Premature optimization is the root of all evil
         –Performance Anti-Pattern #1


                                                                19

Tuesday, November 22, 2011
Performance Lessons



   • Object model
   • Usage patterns
         –Concurrent users
         –Data volume
   • Transaction and locking management


                                          20

Tuesday, November 22, 2011
Puzzle #2
                                Heads of Hydra




Tuesday, November 22, 2011
Heads of Hydra

   @Entity
   public class Hydra {
      private Long id;
      private List<Head> heads = new ArrayList<Head>();

         @Id @GeneratedValue
         public Long getId() {...}
         protected void setId() {...}
         @OneToMany(cascade=CascadeType.ALL)
         public List<Head> getHeads() {
            return Collections.unmodifiableList(heads);
         }
         protected void setHeads(List<Head> heads) {...}
   }

   // creates and persists the hydra with 3 heads

   // new EntityManager and new transaction
   Hydra found = em.find(Hydra.class, hydra.getId());



                                                           22

Tuesday, November 22, 2011
How Many Queries in 2nd Tx?
                                                           (a) 1 select
                                                           (b) 2 selects
   @Entity                                                 (c) 1+3 selects
   public class Hydra {
      private Long id;                                     (d) 2 selects, 1 delete, 3
      private List<Head> heads = new ArrayList<Head>();    inserts
                                                           (e) None of the above
         @Id @GeneratedValue
         public Long getId() {...}
         protected void setId() {...}
         @OneToMany(cascade=CascadeType.ALL)
         public List<Head> getHeads() {
            return Collections.unmodifiableList(heads);
         }
         protected void setHeads(List<Head> heads) {...}
   }

   // creates and persists the hydra with 3 heads

   // new EntityManager and new transaction
   Hydra found = em.find(Hydra.class, hydra.getId());



                                                                                        23

Tuesday, November 22, 2011
How Many Queries in 2nd Tx?
   (a) 1 select
   (b) 2 selects
   (c) 1+3 selects
   (d) 2 selects, 1 delete, 3 inserts
   (e) None of the above



       During commit hibernate checks whether the
       collection property is dirty (needs to be re-
       created) by comparing Java identities (object
       references).                                    24

Tuesday, November 22, 2011
Another Look

   @Entity
   public class Hydra {
      private Long id;
      private List<Head> heads = new ArrayList<Head>();

         @Id @GeneratedValue
         public Long getId() {...}
         protected void setId() {...}
         @OneToMany(cascade=CascadeType.ALL)
         public List<Head> getHeads() {
            return Collections.unmodifiableList(heads);
         }
         protected void setHeads(List<Head> heads) {...}
   }

   // creates and persists hydra with three heads

   // new EntityManager and new transaction
   // during find only 1 select (hydra)
   Hydra found = em.find(Hydra.class, hydra.getId());
   // during commit 1 select (heads),1 delete (heads),3 inserts (heads)


                                                                          25

Tuesday, November 22, 2011
How To Fix It?

  @Entity
  public class Hydra {
     @Id @GeneratedValue
     private Long id;
     @OneToMany(cascade=CascadeType.ALL)
     private List<Head> heads = new ArrayList<Head>();

         public Long getId() {...}
         protected void setId() {...}
         public List<Head> getHeads() {
            return Collections.unmodifiableList(heads);
         }
         protected void setHeads(List<Head> heads) {...}
  }

  // creates and persists hydra with three heads

  // new EntityManager and new transaction
  Hydra found = em.find(Hydra.class, hydra.getId());



                                                           26

Tuesday, November 22, 2011
Lessons Learned




   • Expect unexpected ;-)
   • Prefer field access mappings
   • And...




                                    27

Tuesday, November 22, 2011
Anti-Pattern #2
                             Lost Collection Proxy on Owning Side




Tuesday, November 22, 2011
Lost Collection Proxy


   • Description
         –On the owning side of an association, we assign a new
          collection object to a persistent field/property overriding
          a collection proxy returned by hibernate
   • Consequences
         –The entire collection is re-created: one delete to
          remove all elements and then many element inserts


                                                                   29

Tuesday, November 22, 2011
Lost Collection Proxy - Example

   @Entity
   public class Hydra {
      @Id @GeneratedValue
      private Long id;
      @OneToMany(cascade=CascadeType.ALL)
      private List<Head> heads = new ArrayList<Head>();

         public Long getId() {...}
         protected void setId() {...}
         public List<Head> getHeads() {
            return heads;
         }
         public void setHeads(List<Head> heads) {
            this.heads = heads;
         }
   }




                                                          30

Tuesday, November 22, 2011
Lost Collection Proxy - Solution

   • Operate on collection objects returned by
     hibernate
         –In most cases it’s a much more efficient solution
   • Unless you know what you’re doing
         –It might be performance-wise in some cases to re-
          create the entire collection (bulk delete)
         –However, it’s the place when hibernate could do better,
          having all required data available:
               • Original size, added and removed elements
               • Min(#added + #removed, 1 + #size - #removed + #added)
                                                                         31

Tuesday, November 22, 2011
Puzzle #3
                             Fashionable Developer




Tuesday, November 22, 2011
Fashionable Developer
   @Entity
   public class Developer {
      @Id @GeneratedValue
      private Long id;
      private String mainTechnology;

         public boolean likesMainTechnology() {
            return "hibernate".equalsIgnoreCase(mainTechnology);
         }
   }
   // creates and persists a developer that uses hibernate as mainTechnology

   // new EntityManager and new transaction
   Developer dev = em.find(Developer.class, id);
   boolean foundCoolStuff = false;
   for (String tech : new String[]{"HTML5", "Android", "Scala"}) {
      dev.setMainTechnology(tech);
      // othersAreUsingIt:
      // select count(*) from Developer where mainTechnology = ? and id != ?
      if (othersAreUsingIt(tech, dev) && dev.likesMainTechnology()) {
          foundCoolStuff = true; break;
      }
   }
   if (!foundCoolStuff) {
      // still use hibernate
      dev.setMainTechnology("hibernate");
                                                                               33
   }
Tuesday, November 22, 2011
How Many Queries in 2nd Tx?
   @Entity
   public class Developer {                                (a) 2 select
      @Id @GeneratedValue                                  (b) 4 selects
      private Long id;
      private String mainTechnology;                       (c) 4 selects, 1 update
                                                           (d) 4 selects, 4 updates
         public boolean likesMainTechnology() {
                                                           (e) None of the above
            return "hibernate".equalsIgnoreCase(mainTechnology);
         }
   }
   // creates and persists a developer that uses hibernate as mainTechnology

   // new EntityManager and new transaction
   Developer dev = em.find(Developer.class, id);
   boolean foundCoolStuff = false;
   for (String tech : new String[]{"HTML5", "Android", "Scala"}) {
      dev.setMainTechnology(tech);
      // othersAreUsingIt:
      // select count(*) from Developer where mainTechnology = ? and id != ?
      if (othersAreUsingIt(tech, dev) && dev.likesMainTechnology()) {
          foundCoolStuff = true; break;
      }
   }
   if (!foundCoolStuff) {
      // still use hibernate
      dev.setMainTechnology("hibernate");
                                                                                      34
   }
Tuesday, November 22, 2011
How Many Queries in 2nd Tx?
   (a) 2 selects
   (b) 4 selects
   (c) 4 selects, 1 update
   (d) 4 selects, 4 inserts
   (e) None of the above



       Hibernate must guarantee correctness of
       executed queries, therefore in certain situations it
       must perform flushes during a transaction.
                                                          35

Tuesday, November 22, 2011
Fashionable Developer
   @Entity
   public class Developer {
      @Id @GeneratedValue
      private Long id;
      private String mainTechnology;                               NO UPDATES
         public boolean likesMainTechnology() {
            return "hibernate".equalsIgnoreCase(mainTechnology);
         }
   }
   // creates and persists a developer that uses hibernate as mainTechnology

   // new EntityManager and new transaction
   Developer dev = em.find(Developer.class, id);
   boolean foundCoolStuff = false;
   for (String tech : new String[]{"HTML5", "Android", "Scala"}) {
      dev.setMainTechnology(tech);
      // othersAreUsingIt:
      // select count(*) from Developer where mainTechnology = ? and id != ?
      if (/*othersAreUsingIt(tech, dev) &&*/ dev.likesMainTechnology()) {
          foundCoolStuff = true; break;
      }
   }
   if (!foundCoolStuff) {
      // still use hibernate
      dev.setMainTechnology("hibernate");
                                                                                36
   }
Tuesday, November 22, 2011
Anti-Pattern #3
                                   Temporary Changes




Tuesday, November 22, 2011
Temporary Changes
   • Description
         –We change the persistent data of an object temporarily to
          test some features
         –In the meantime a database flush occurs triggered, for
          example, by a HQL touching the table
   • Consequences
         –Flushes can be performed during the transaction, not
          only at the commit time
         –Temporary changes persisted into the database
          unnecessarily
   • Solution
         –Plan your business model and processing to avoid
          temporary changes to your persistent data              38

Tuesday, November 22, 2011
Puzzle #4
                                 Plant a Tree




Tuesday, November 22, 2011
Plant a Tree

   @Entity
   public class Forest {
      @Id @GeneratedValue
      private Long id;
      @OneToMany
      Collection<Tree> trees = new HashSet<Tree>();

         public void plantTree(Tree tree) {
            trees.add(tree);
         }
   }

   // creates and persists a forest with 10.000 trees

   // new EntityManager and new transaction
   Tree tree = new Tree(“oak”);
   em.persist(tree);
   Forest forest = em.find(Forest.class, id);
   forest.plantTree(tree);




                                                        40

Tuesday, November 22, 2011
How Many Queries in 2nd Tx?

   @Entity                                              (a) 1 select, 2 inserts
   public class Forest {                                (b) 2 selects, 2 inserts
      @Id @GeneratedValue                               (c) 2 selects, 1 delete,
      private Long id;
      @OneToMany                                        10.000+2 inserts
      Collection<Tree> trees = new HashSet<Tree>();     (d) Even more ;-)
         public void plantTree(Tree tree) {
            trees.add(tree);
         }
   }

   // creates and persists a forest with 10.000 trees

   // new EntityManager and new transaction
   Tree tree = new Tree(“oak”);
   em.persist(tree);
   Forest forest = em.find(Forest.class, id);
   forest.plantTree(tree);




                                                                                   41

Tuesday, November 22, 2011
How Many Queries in 2nd Tx?
   (a) 1 select, 2 inserts
   (b) 2 selects, 2 inserts
   (c) 2 selects, 1 delete, 10.000+2 inserts
   (d) Even more ;-)




       The combination of OneToMany and Collection
       enables a bag semantic. That’s why the collection
       is re-created.                                 42

Tuesday, November 22, 2011
Plant a Tree - Revisited

   @Entity
   public class Orchard {
      @Id @GeneratedValue
      private Long id;
      @OneToMany
      List<Tree> trees = new ArrayList<Tree>();

         public void plantTree(Tree tree) {
            trees.add(tree);
         }
   }

   // creates and persists a forest with 10.000 trees

   // new EntityManager and new transaction
   Tree tree = new Tree(“apple tree”);
   em.persist(tree);
   Orchard orchard = em.find(Orchard.class, id);
   orchard.plantTree(tree);




                                                        43

Tuesday, November 22, 2011
Plant a Tree - Revisited

   @Entity
   public class Orchard {                               STILL BAG SEMANTIC!
      @Id @GeneratedValue
      private Long id;
      @OneToMany
      List<Tree> trees = new ArrayList<Tree>();

         public void plantTree(Tree tree) {
            trees.add(tree);
         }
   }

   // creates and persists a forest with 10.000 trees

   // new EntityManager and new transaction
   Tree tree = new Tree(“apple tree”);
   em.persist(tree);
   Orchard orchard = em.find(Orchard.class, id);
   orchard.plantTree(tree);




                                                                          43

Tuesday, November 22, 2011
Plant a Tree - Revisited

   @Entity
   public class Orchard {                               STILL BAG SEMANTIC!
      @Id @GeneratedValue
      private Long id;                                   Use OrderColumn or
      @OneToMany
      List<Tree> trees = new ArrayList<Tree>();          IndexColumn for list
                                                              semantic.
         public void plantTree(Tree tree) {
            trees.add(tree);
         }
   }

   // creates and persists a forest with 10.000 trees

   // new EntityManager and new transaction
   Tree tree = new Tree(“apple tree”);
   em.persist(tree);
   Orchard orchard = em.find(Orchard.class, id);
   orchard.plantTree(tree);




                                                                                43

Tuesday, November 22, 2011
OneToMany Mapping

                         Seman&c                    Java	
  Type               Annota&on

                                                     java.u3l.Collec3on
                    bag	
  seman3c                       java.u3l.List
                                                                             @ElementCollec3on	
  ||
                                                                          @OneToMany	
  ||	
  @ManyToMany




                     set	
  seman3c                      java.u3l.Set
                                                                             @ElementCollec3on	
  ||
                                                                          @OneToMany	
  ||	
  @ManyToMany


                                                                             (@ElementCollec3on	
  ||
                                                                          @OneToMany	
  ||	
  @ManyToMany)	
  
                     list	
  seman3c                     java.u3l.List                    &&
                                                                                 (@OrderColumn	
  ||	
  
                                                                                  @IndexColumn)
                @OneToMany	
  (no	
  cascade	
  op3on)
                                                                                                                 44

Tuesday, November 22, 2011
OneToMany Mapping

                                            add	
                           remove	
                      update	
  
                                          element                           element                       element

                      bag	
                  re-­‐create:                      re-­‐create:
                                                                                                           1	
  update
                    seman3c           1	
  delete	
  +	
  N	
  inserts 1	
  delete	
  +	
  N	
  inserts


                      set	
                    1	
  insert                       1	
  delete               1	
  update
                    seman3c

                      list	
               1	
  insert	
  +	
  M	
           1	
  delete	
  +	
  M	
  
                                                                                                           1	
  update
                    seman3c                     updates                          updates*


                @OneToMany	
  (no	
  cascade	
  op3on)
                                                                                                                         45

Tuesday, November 22, 2011
OneToMany Mapping

                                            add	
                           remove	
                      update	
  
                                          element                           element                       element

                      bag	
                  re-­‐create:                      re-­‐create:
                                                                                                           1	
  update
                    seman3c           1	
  delete	
  +	
  N	
  inserts 1	
  delete	
  +	
  N	
  inserts


                      set	
                    1	
  insert                       1	
  delete               1	
  update
                    seman3c

                      list	
               1	
  insert	
  +	
  M	
           1	
  delete	
  +	
  M	
  
                                                                                                           1	
  update
                    seman3c                     updates                          updates*


                @OneToMany	
  (no	
  cascade	
  op3on)
                                                                                                                         46

Tuesday, November 22, 2011
OneToMany Mapping

                                            add	
                           remove	
                      update	
  
                                          element                           element                       element
                                             Oops, we have a problem.
                      bag	
         (list: removal of nth element, n < size-2)
                                             re-­‐create:     re-­‐create:
                    seman3c           1	
  delete	
  +	
  N	
  inserts 1	
  delete	
  +	
  N	
  inserts
                                                                                                           1	
  update



                      set	
                    1	
  insert                       1	
  delete               1	
  update
                    seman3c

                      list	
               1	
  insert	
  +	
  M	
           1	
  delete	
  +	
  M	
  
                                                                                                           1	
  update
                    seman3c                     updates                          updates*


                @OneToMany	
  (no	
  cascade	
  op3on)
                                                                                                                         47

Tuesday, November 22, 2011
Anti-Pattern #4
                             Inadequate Collection Type (Owning Side)




Tuesday, November 22, 2011
Inadequate Collection Mapping (Owning Side)



   • Description
         –Chosen an inadequate collection mapping on the
          owning side
   • Consequences
         –Additional queries executed
   • Solution
         –Consider your use cases and usage patterns and
          choose a mapping with the least performance overhead

                                                            49

Tuesday, November 22, 2011
Plant a Tree

   @Entity
   public class Forest {
      @Id @GeneratedValue
      private Long id;
      @OneToMany
      Set<Tree> trees = new HashSet<Tree>();

         public void plantTree(Tree tree) {
            trees.add(tree);
         }
   }

   // creates and persists a forest with 10.000 trees

   // new EntityManager and new transaction
   Tree oak = new Tree(“oak”);
   em.persist(oak);
   Forest forest = em.find(Forest.class, id);
   forest.plantTree(oak);




                                                        50

Tuesday, November 22, 2011
Anti-Pattern #5
                                OneToMany as Owning Side




Tuesday, November 22, 2011
OneToMany as Owning Side
   • Description
         –OneToMany used as the owning side of a relationship
   • Consequences
         –Collection elements loaded into memory
         –Possibly unnecessary queries
         –Transaction and locking schema problems: version,
          optimistic locking
   • Solution
         –Use ManyToOne as the owning side and OneToMany
          as the inverse side
         –Or at least exclude the collection from locking
               • @OptimisticLock(excluded=true)
                                              .                 52

Tuesday, November 22, 2011
Plant a Tree
   @Entity
   public class Forest {
      @Id @GeneratedValue
      private Long id;
      @OneToMany (mappedBy = “forest”)
      Set<Tree> trees = new HashSet<Tree>();

         public void plantTree(Tree tree) {
            trees.add(tree);
         }
   }

   @Entity
   public class Tree {
      @Id @GeneratedValue
      private Long id;
      private String name;
      @ManyToOne
      Forest forest;

         public void setForest(Forest forest) {
            this.forest = forest;
            this.forest.plantTree(this);
         }
   }
                                                  53

Tuesday, November 22, 2011
Plant a Tree
   @Entity
   public class Forest {
      @Id @GeneratedValue
      private Long id;
      @OneToMany (mappedBy = “forest”)
      Set<Tree> trees = new HashSet<Tree>();

         public void plantTree(Tree tree) {
            trees.add(tree);
         }
   }

   @Entity
   public class Tree {
      @Id @GeneratedValue
      private Long id;
      private String name;
      @ManyToOne
      Forest forest;

         public void setForest(Forest forest) {
            this.forest = forest;
            this.forest.plantTree(this);
         }
   }
                                                  54

Tuesday, November 22, 2011
Anti-Pattern #6
                             Inadequate Collection Type (Inverse Side)




Tuesday, November 22, 2011
Inadequate Collection Type (Inverse Side)


   • Description
         –Set used as a collection type on the inverse side of a
          relationship and, to keep the model consistent, the
          owning side updates the inverse side
   • Consequences
         –Due to a set semantic, all elements must be loaded
          when we add a new element
   • Solution
         –Use Collection or List instead

                                                                   56

Tuesday, November 22, 2011
Plant a Tree
   @Entity
   public class Forest {
      @Id @GeneratedValue
      private Long id;
      @OneToMany (mappedBy = “forest”)
      Collection<Tree> trees = new HashSet<Tree>();

         public void plantTree(Tree tree) {
            trees.add(tree);
         }
   }

   @Entity
   public class Tree {
      @Id @GeneratedValue
      private Long id;
      private String name;
      @ManyToOne
      Forest forest;

         public void setForest(Forest forest) {
            this.forest = forest;
            this.forest.plantTree(this);
         }
   }
                                                      57

Tuesday, November 22, 2011
Plant a Tree
   @Entity
   public class Forest {
      @Id @GeneratedValue
      private Long id;
      @OneToMany (mappedBy = “forest”)
      Collection<Tree> trees = new HashSet<Tree>();

         public void plantTree(Tree tree) {
            trees.add(tree);
         }
   }

   @Entity
   public class Tree {
      @Id @GeneratedValue
      private Long id;
      private String name;
      @ManyToOne
      Forest forest;

         // ...
   }
   // creates and persists a forest with 10.000 trees

   // new EntityManager and new transaction
   em.remove(forest);                                   58

Tuesday, November 22, 2011
Plant a Tree
   @Entity
   public class Forest {
      @Id @GeneratedValue
      private Long id;
      @OneToMany (mappedBy = “forest”)
      Collection<Tree> trees = new HashSet<Tree>();

         public void plantTree(Tree tree) {
            trees.add(tree);
         }
   }

   @Entity
   public class Tree {
      @Id @GeneratedValue
      private Long id;
      private String name;
      @ManyToOne
      Forest forest;

         // ...
   }
   // creates and persists a forest with 10.000 trees

   // new EntityManager and new transaction
   em.remove(forest);                                   58

Tuesday, November 22, 2011
Plant a Tree
   @Entity
   public class Forest {
      @Id @GeneratedValue
      private Long id;
      @OneToMany (mappedBy = “forest”)
      Collection<Tree> trees = new HashSet<Tree>();

         // ...
   }

   @Entity
   public class Tree {
      @Id @GeneratedValue
      private Long id;
      private String name;
      @ManyToOne
      Forest forest;

         // ...
   }
   // creates and persists a forest with 10.000 trees

   // new EntityManager and new transaction
   for (Tree tree : forest.getTrees()) {
      tree.setForest(null);
   }
                                                        59
   em.remove(forest);
Tuesday, November 22, 2011
Plant a Tree
   @Entity
   public class Forest {
      @Id @GeneratedValue
      private Long id;
      @OneToMany (mappedBy = “forest”)
      Collection<Tree> trees = new HashSet<Tree>();

         // ...
   }

   @Entity
   public class Tree {
      @Id @GeneratedValue
      private Long id;                                  10.000 UPDATES
      private String name;
      @ManyToOne
                                                           1 DELETE
      Forest forest;

         // ...
   }
   // creates and persists a forest with 10.000 trees

   // new EntityManager and new transaction
   for (Tree tree : forest.getTrees()) {
      tree.setForest(null);
   }
                                                                         59
   em.remove(forest);
Tuesday, November 22, 2011
Anti-Pattern #7
                                  One by One Processing




Tuesday, November 22, 2011
Inadequate Collection Type (Inverse Side)


   • Description
         –Sequential processing of a persistent collection/objects
   • Consequences
         –Each database operation performed separately for
          each element
   • Solution
         –Bulk queries
         –That’s why CaveatEmptor was implemented like this
          (aggregate function on a database level)

                                                                 61

Tuesday, November 22, 2011
Conclusions

   • Big data cause big problems
         –Standard mappings don’t handle large datasets well
         –Smart model, bulk processing, projections
   • RTFM
         –Most of information can be found in the hibernate docs
         –Understand what you read
         –Think about consequences
         –And hopefully you’ll be fine :)
   • Hibernate
         –Smarter policies and data structures
                                                               62

Tuesday, November 22, 2011
Contact




   • email: patrycja@yonita.com
   • twitter: @yonlabs
   • www: http://www.yonita.com




                                  63

Tuesday, November 22, 2011

More Related Content

What's hot

Introduction to the Data Grid
Introduction to the Data GridIntroduction to the Data Grid
Introduction to the Data GridOutSystems
 
MySQL Indexing - Best practices for MySQL 5.6
MySQL Indexing - Best practices for MySQL 5.6MySQL Indexing - Best practices for MySQL 5.6
MySQL Indexing - Best practices for MySQL 5.6MYXPLAIN
 
Mysql Explain Explained
Mysql Explain ExplainedMysql Explain Explained
Mysql Explain ExplainedJeremy Coates
 
MySQL Performance Schema in Action: the Complete Tutorial
MySQL Performance Schema in Action: the Complete TutorialMySQL Performance Schema in Action: the Complete Tutorial
MySQL Performance Schema in Action: the Complete TutorialSveta Smirnova
 
Altinity Quickstart for ClickHouse-2202-09-15.pdf
Altinity Quickstart for ClickHouse-2202-09-15.pdfAltinity Quickstart for ClickHouse-2202-09-15.pdf
Altinity Quickstart for ClickHouse-2202-09-15.pdfAltinity Ltd
 
PostgreSQL 15 and its Major Features -(Aakash M - Mydbops) - Mydbops Opensour...
PostgreSQL 15 and its Major Features -(Aakash M - Mydbops) - Mydbops Opensour...PostgreSQL 15 and its Major Features -(Aakash M - Mydbops) - Mydbops Opensour...
PostgreSQL 15 and its Major Features -(Aakash M - Mydbops) - Mydbops Opensour...Mydbops
 
Boost Performance With My S Q L 51 Partitions
Boost Performance With  My S Q L 51 PartitionsBoost Performance With  My S Q L 51 Partitions
Boost Performance With My S Q L 51 PartitionsPerconaPerformance
 
Developing for Node.JS with MySQL and NoSQL
Developing for Node.JS with MySQL and NoSQLDeveloping for Node.JS with MySQL and NoSQL
Developing for Node.JS with MySQL and NoSQLJohn David Duncan
 
PostgreSQL Security. How Do We Think?
PostgreSQL Security. How Do We Think?PostgreSQL Security. How Do We Think?
PostgreSQL Security. How Do We Think?Ohyama Masanori
 
[29DCF] PostgreSQL에서 DB Lock을 줄이는 5가지 팁
[29DCF] PostgreSQL에서 DB Lock을 줄이는 5가지 팁[29DCF] PostgreSQL에서 DB Lock을 줄이는 5가지 팁
[29DCF] PostgreSQL에서 DB Lock을 줄이는 5가지 팁jiminlee81
 
Mastering PostgreSQL Administration
Mastering PostgreSQL AdministrationMastering PostgreSQL Administration
Mastering PostgreSQL AdministrationCommand Prompt., Inc
 
The InnoDB Storage Engine for MySQL
The InnoDB Storage Engine for MySQLThe InnoDB Storage Engine for MySQL
The InnoDB Storage Engine for MySQLMorgan Tocker
 
ProxySQL & PXC(Query routing and Failover Test)
ProxySQL & PXC(Query routing and Failover Test)ProxySQL & PXC(Query routing and Failover Test)
ProxySQL & PXC(Query routing and Failover Test)YoungHeon (Roy) Kim
 
MySQL GTID 시작하기
MySQL GTID 시작하기MySQL GTID 시작하기
MySQL GTID 시작하기I Goo Lee
 
MySQL Shell/AdminAPI - MySQL Architectures Made Easy For All!
MySQL Shell/AdminAPI - MySQL Architectures Made Easy For All!MySQL Shell/AdminAPI - MySQL Architectures Made Easy For All!
MySQL Shell/AdminAPI - MySQL Architectures Made Easy For All!Miguel Araújo
 
MySQL Atchitecture and Concepts
MySQL Atchitecture and ConceptsMySQL Atchitecture and Concepts
MySQL Atchitecture and ConceptsTuyen Vuong
 
MySQL Performance Schema in 20 Minutes
 MySQL Performance Schema in 20 Minutes MySQL Performance Schema in 20 Minutes
MySQL Performance Schema in 20 MinutesSveta Smirnova
 
MySQL Multi-Source Replication for PL2016
MySQL Multi-Source Replication for PL2016MySQL Multi-Source Replication for PL2016
MySQL Multi-Source Replication for PL2016Wagner Bianchi
 
C++20 the small things - Timur Doumler
C++20 the small things - Timur DoumlerC++20 the small things - Timur Doumler
C++20 the small things - Timur Doumlercorehard_by
 
What is new in PostgreSQL 14?
What is new in PostgreSQL 14?What is new in PostgreSQL 14?
What is new in PostgreSQL 14?Mydbops
 

What's hot (20)

Introduction to the Data Grid
Introduction to the Data GridIntroduction to the Data Grid
Introduction to the Data Grid
 
MySQL Indexing - Best practices for MySQL 5.6
MySQL Indexing - Best practices for MySQL 5.6MySQL Indexing - Best practices for MySQL 5.6
MySQL Indexing - Best practices for MySQL 5.6
 
Mysql Explain Explained
Mysql Explain ExplainedMysql Explain Explained
Mysql Explain Explained
 
MySQL Performance Schema in Action: the Complete Tutorial
MySQL Performance Schema in Action: the Complete TutorialMySQL Performance Schema in Action: the Complete Tutorial
MySQL Performance Schema in Action: the Complete Tutorial
 
Altinity Quickstart for ClickHouse-2202-09-15.pdf
Altinity Quickstart for ClickHouse-2202-09-15.pdfAltinity Quickstart for ClickHouse-2202-09-15.pdf
Altinity Quickstart for ClickHouse-2202-09-15.pdf
 
PostgreSQL 15 and its Major Features -(Aakash M - Mydbops) - Mydbops Opensour...
PostgreSQL 15 and its Major Features -(Aakash M - Mydbops) - Mydbops Opensour...PostgreSQL 15 and its Major Features -(Aakash M - Mydbops) - Mydbops Opensour...
PostgreSQL 15 and its Major Features -(Aakash M - Mydbops) - Mydbops Opensour...
 
Boost Performance With My S Q L 51 Partitions
Boost Performance With  My S Q L 51 PartitionsBoost Performance With  My S Q L 51 Partitions
Boost Performance With My S Q L 51 Partitions
 
Developing for Node.JS with MySQL and NoSQL
Developing for Node.JS with MySQL and NoSQLDeveloping for Node.JS with MySQL and NoSQL
Developing for Node.JS with MySQL and NoSQL
 
PostgreSQL Security. How Do We Think?
PostgreSQL Security. How Do We Think?PostgreSQL Security. How Do We Think?
PostgreSQL Security. How Do We Think?
 
[29DCF] PostgreSQL에서 DB Lock을 줄이는 5가지 팁
[29DCF] PostgreSQL에서 DB Lock을 줄이는 5가지 팁[29DCF] PostgreSQL에서 DB Lock을 줄이는 5가지 팁
[29DCF] PostgreSQL에서 DB Lock을 줄이는 5가지 팁
 
Mastering PostgreSQL Administration
Mastering PostgreSQL AdministrationMastering PostgreSQL Administration
Mastering PostgreSQL Administration
 
The InnoDB Storage Engine for MySQL
The InnoDB Storage Engine for MySQLThe InnoDB Storage Engine for MySQL
The InnoDB Storage Engine for MySQL
 
ProxySQL & PXC(Query routing and Failover Test)
ProxySQL & PXC(Query routing and Failover Test)ProxySQL & PXC(Query routing and Failover Test)
ProxySQL & PXC(Query routing and Failover Test)
 
MySQL GTID 시작하기
MySQL GTID 시작하기MySQL GTID 시작하기
MySQL GTID 시작하기
 
MySQL Shell/AdminAPI - MySQL Architectures Made Easy For All!
MySQL Shell/AdminAPI - MySQL Architectures Made Easy For All!MySQL Shell/AdminAPI - MySQL Architectures Made Easy For All!
MySQL Shell/AdminAPI - MySQL Architectures Made Easy For All!
 
MySQL Atchitecture and Concepts
MySQL Atchitecture and ConceptsMySQL Atchitecture and Concepts
MySQL Atchitecture and Concepts
 
MySQL Performance Schema in 20 Minutes
 MySQL Performance Schema in 20 Minutes MySQL Performance Schema in 20 Minutes
MySQL Performance Schema in 20 Minutes
 
MySQL Multi-Source Replication for PL2016
MySQL Multi-Source Replication for PL2016MySQL Multi-Source Replication for PL2016
MySQL Multi-Source Replication for PL2016
 
C++20 the small things - Timur Doumler
C++20 the small things - Timur DoumlerC++20 the small things - Timur Doumler
C++20 the small things - Timur Doumler
 
What is new in PostgreSQL 14?
What is new in PostgreSQL 14?What is new in PostgreSQL 14?
What is new in PostgreSQL 14?
 

More from Codemotion

Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...Codemotion
 
Pompili - From hero to_zero: The FatalNoise neverending story
Pompili - From hero to_zero: The FatalNoise neverending storyPompili - From hero to_zero: The FatalNoise neverending story
Pompili - From hero to_zero: The FatalNoise neverending storyCodemotion
 
Pastore - Commodore 65 - La storia
Pastore - Commodore 65 - La storiaPastore - Commodore 65 - La storia
Pastore - Commodore 65 - La storiaCodemotion
 
Pennisi - Essere Richard Altwasser
Pennisi - Essere Richard AltwasserPennisi - Essere Richard Altwasser
Pennisi - Essere Richard AltwasserCodemotion
 
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...Codemotion
 
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019Codemotion
 
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019Codemotion
 
Francesco Baldassarri - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Francesco Baldassarri  - Deliver Data at Scale - Codemotion Amsterdam 2019 - Francesco Baldassarri  - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Francesco Baldassarri - Deliver Data at Scale - Codemotion Amsterdam 2019 - Codemotion
 
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...Codemotion
 
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...Codemotion
 
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...Codemotion
 
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...Codemotion
 
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019Codemotion
 
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019Codemotion
 
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019Codemotion
 
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...Codemotion
 
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...Codemotion
 
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019Codemotion
 
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019Codemotion
 
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019Codemotion
 

More from Codemotion (20)

Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
 
Pompili - From hero to_zero: The FatalNoise neverending story
Pompili - From hero to_zero: The FatalNoise neverending storyPompili - From hero to_zero: The FatalNoise neverending story
Pompili - From hero to_zero: The FatalNoise neverending story
 
Pastore - Commodore 65 - La storia
Pastore - Commodore 65 - La storiaPastore - Commodore 65 - La storia
Pastore - Commodore 65 - La storia
 
Pennisi - Essere Richard Altwasser
Pennisi - Essere Richard AltwasserPennisi - Essere Richard Altwasser
Pennisi - Essere Richard Altwasser
 
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
 
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
 
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
 
Francesco Baldassarri - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Francesco Baldassarri  - Deliver Data at Scale - Codemotion Amsterdam 2019 - Francesco Baldassarri  - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Francesco Baldassarri - Deliver Data at Scale - Codemotion Amsterdam 2019 -
 
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
 
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
 
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
 
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
 
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
 
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
 
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
 
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
 
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
 
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
 
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
 
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
 

Recently uploaded

How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxBkGupta21
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxLoriGlavin3
 
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
 
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
 
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
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
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
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESmohitsingh558521
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
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
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
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
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 

Recently uploaded (20)

How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptx
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
 
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
 
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
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
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
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
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
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
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?
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
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
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 

Performance Anti-Patterns in Hibernatee, by Patrycja Wegrzynowicz

  • 1. Performance Anti-Patterns in Hibernate Patrycja Wegrzynowicz CTO Yonita, Inc. Tuesday, November 22, 2011
  • 2. About Me • 10+ years of professional experience • PhD in Computer Science –Patterns and anti-patterns, static and dynamic code analysis, language semantics, compiler design • Active author and speaker –JavaOne, Devoxx, JavaZone, Jazoon, OOPSLA, ASE... • CTO of Yonita, Inc. –Bridge the gap between the industry and the academia –Automated defects detection and optimization –Performance, security, concurrency, databases • Twitter @yonlabs 2 Tuesday, November 22, 2011
  • 3. Agenda • 4 puzzles –Short program with curious behavior –Question to you (multiple choice) –Mystery revealed –Lessons learned • 7 performance anti-patterns –Description, consequences, solutions 3 Tuesday, November 22, 2011
  • 4. Disclaimer I do think Hibernate is a great tool! 4 Tuesday, November 22, 2011
  • 8. Puzzle #1 Less Is More Tuesday, November 22, 2011
  • 9. Who knows CaveatEmptor app? 7 Tuesday, November 22, 2011
  • 10. Who’s read Java Persistence with Hibernate? 8 Tuesday, November 22, 2011
  • 11. CaveatEmptor • Demo application from ‘Java Persistence with Hibernate’ • Simple auction system 9 Tuesday, November 22, 2011
  • 12. I’m Gonna Win This Auction! public class PlaceBidAction implements Action { // invoked in a new transaction public String execute(Map even) { // ... Bid currentMinBid = itemDAO.getMinBid(itemId); Bid currentMaxBid = itemDAO.getMaxBid(itemId); // uses load with Lock.UPGRADE Item item = itemDAO.findById(itemId, true); Bid newBid = item.placeBid(userDAO.findById(userId, false), newAmount, currentMaxBid, currentMinBid); // ... } } 10 Tuesday, November 22, 2011
  • 13. What’s the Problem? (a) None (code is correct) (b) Transaction/lock mgmt public class PlaceBidAction implements Action { (c) Exception thrown // invoked in a new transaction (d) None of the above public String execute(Map even) { // ... Bid currentMinBid = itemDAO.getMinBid(itemId); Bid currentMaxBid = itemDAO.getMaxBid(itemId); // uses load with Lock.UPGRADE Item item = itemDAO.findById(itemId, true); Bid newBid = item.placeBid(userDAO.findById(userId, false), newAmount, currentMaxBid, currentMinBid); // ... } } 11 Tuesday, November 22, 2011
  • 14. What’s the Problem? (a) None (the code is correct) (b) Transaction/Lock management (c) Exception thrown (d) None of the above The bids can change between calling getMaxBid and locking the item. 12 Tuesday, November 22, 2011
  • 15. Another Look public class PlaceBidAction implements Action { // invoked in a new transaction public String execute(Map even) { // ... Bid currentMinBid = itemDAO.getMinBid(itemId); Bid currentMaxBid = itemDAO.getMaxBid(itemId); // here, the bids can be modified by a different transaction // uses load with Lock.UPGRADE Item item = itemDAO.findById(itemId, true); Bid newBid = item.placeBid(userDAO.findById(userId, false), newAmount, currentMaxBid, currentMinBid); // ... } } 13 Tuesday, November 22, 2011
  • 16. 2 Users and Item with 2 Bids Thread A (new amount 100) Thread B (new amount 30) (1) // begin transaction // item with 2 bids: 10,20 Bid curMax = dao.getMaxBid(id); // curMax = 20 14 Tuesday, November 22, 2011
  • 17. 2 Users and Item with 2 Bids Thread A (new amount 100) Thread B (new amount 30) (1) (2) // begin transaction // begin transaction // item with 2 bids: 10,20 // item with 2 bids: 10,20 Bid curMax = dao.getMaxBid(id); Bid curMax = dao.getMaxBid(id); // curMax = 20 // curMax = 20 15 Tuesday, November 22, 2011
  • 18. 2 Users and Item with 2 Bids Thread A (new amount 100) Thread B (new amount 30) (1) (2) // begin transaction // begin transaction // item with 2 bids: 10,20 // item with 2 bids: 10,20 Bid curMax = dao.getMaxBid(id); Bid curMax = dao.getMaxBid(id); // curMax = 20 // curMax = 20 (3) // item with 2 bids: 10,20 // Lock.UPGRADE Item item = dao.findById(id,true); Bid newBid = item.placeBid(..., newAmount, curMax, ...); // commit transaction // item with 3 bids: 10,20,100 Successful bid: 100 16 Tuesday, November 22, 2011
  • 19. 2 Users and Item with 2 Bids Thread A (new amount 100) Thread B (new amount 30) (1) (2) // begin transaction // begin transaction // item with 2 bids: 10,20 // item with 2 bids: 10,20 Bid curMax = dao.getMaxBid(id); Bid curMax = dao.getMaxBid(id); // curMax = 20 // curMax = 20 (3) (4) // item with 2 bids: 10,20 // item with 3 bids: 10,20,100 // Lock.UPGRADE // Lock.UPGRADE Item item = dao.findById(id,true); Item item = dao.findById(id,true); Bid newBid = item.placeBid(..., Bid newBid = item.placeBid(..., newAmount, newAmount, curMax, ...); curMax, ...); // commit transaction // commit transaction // item with 3 bids: 10,20,100 // item with 4 bids: 10,20,100,30 Successful bid: 100 Successful bid: 30 17 Tuesday, November 22, 2011
  • 20. How To Fix It? public class PlaceBidAction implements Action { // invoked in a new transaction public String execute(Map even) { // ... Bid currentMinBid = itemDAO.getMinBid(itemId); Bid currentMaxBid = itemDAO.getMaxBid(itemId); // uses load with Lock.UPGRADE Item item = itemDAO.findById(itemId, true); Bid newBid = item.placeBid(userDAO.findById(userId, false), newAmount, currentMaxBid, currentMinBid); // ... } } 18 Tuesday, November 22, 2011
  • 21. How To Fix It? version and optimistic locking public class PlaceBidAction implements Action { // invoked in a new transaction public String execute(Map even) { // ... Bid currentMinBid = itemDAO.getMinBid(itemId); Bid currentMaxBid = itemDAO.getMaxBid(itemId); // uses load with Lock.UPGRADE Item item = itemDAO.findById(itemId, true); Bid newBid = item.placeBid(userDAO.findById(userId, false), newAmount, currentMaxBid, currentMinBid); // ... } } 18 Tuesday, November 22, 2011
  • 22. How To Fix It? version and NO optimistic locking public class PlaceBidAction implements Action { // invoked in a new transaction public String execute(Map even) { // ... Bid currentMinBid = itemDAO.getMinBid(itemId); Bid currentMaxBid = itemDAO.getMaxBid(itemId); // uses load with Lock.UPGRADE Item item = itemDAO.findById(itemId, true); Bid newBid = item.placeBid(userDAO.findById(userId, false), newAmount, currentMaxBid, currentMinBid); // ... } } 18 Tuesday, November 22, 2011
  • 23. How To Fix It? version and NO optimistic locking REPEATABLE public class PlaceBidAction implements Action { // invoked in a new transaction READS public String execute(Map even) { // ... Bid currentMinBid = itemDAO.getMinBid(itemId); Bid currentMaxBid = itemDAO.getMaxBid(itemId); // uses load with Lock.UPGRADE Item item = itemDAO.findById(itemId, true); Bid newBid = item.placeBid(userDAO.findById(userId, false), newAmount, currentMaxBid, currentMinBid); // ... } } 18 Tuesday, November 22, 2011
  • 24. How To Fix It? version and NO optimistic locking REPEATABLE public class PlaceBidAction implements Action { // invoked in a new transaction READS public String execute(Map even) { // ... SERIALIZABLE Bid currentMinBid = itemDAO.getMinBid(itemId); Bid currentMaxBid = itemDAO.getMaxBid(itemId); // uses load with Lock.UPGRADE Item item = itemDAO.findById(itemId, true); Bid newBid = item.placeBid(userDAO.findById(userId, false), newAmount, currentMaxBid, currentMinBid); // ... } } 18 Tuesday, November 22, 2011
  • 25. How To Fix It? version and NO optimistic locking REPEATABLE public class PlaceBidAction implements Action { NO // invoked in a new transaction READS public String execute(Map even) { // ... SERIALIZABLE Bid currentMinBid = itemDAO.getMinBid(itemId); Bid currentMaxBid = itemDAO.getMaxBid(itemId); // uses load with Lock.UPGRADE Item item = itemDAO.findById(itemId, true); Bid newBid = item.placeBid(userDAO.findById(userId, false), newAmount, currentMaxBid, currentMinBid); // ... } } 18 Tuesday, November 22, 2011
  • 26. How To Fix It? version and NO optimistic locking REPEATABLE public class PlaceBidAction implements Action { NO // invoked in a new transaction READS public String execute(Map even) { // ... SERIALIZABLE YES Bid currentMinBid = itemDAO.getMinBid(itemId); Bid currentMaxBid = itemDAO.getMaxBid(itemId); // uses load with Lock.UPGRADE Item item = itemDAO.findById(itemId, true); Bid newBid = item.placeBid(userDAO.findById(userId, false), newAmount, currentMaxBid, currentMinBid); // ... } } 18 Tuesday, November 22, 2011
  • 27. How To Fix It? version and NO optimistic locking REPEATABLE public class PlaceBidAction implements Action { NO // invoked in a new transaction READS public String execute(Map even) { // ... SERIALIZABLE YES Bid currentMinBid = itemDAO.getMinBid(itemId); Bid currentMaxBid = itemDAO.getMaxBid(itemId); move lock before // uses load with Lock.UPGRADE getMinBid/ Item item = itemDAO.findById(itemId, true); getMaxBid Bid newBid = item.placeBid(userDAO.findById(userId, false), newAmount, currentMaxBid, currentMinBid); // ... } } 18 Tuesday, November 22, 2011
  • 28. How To Fix It? version and NO optimistic locking REPEATABLE public class PlaceBidAction implements Action { NO // invoked in a new transaction READS public String execute(Map even) { // ... SERIALIZABLE YES Bid currentMinBid = itemDAO.getMinBid(itemId); Bid currentMaxBid = itemDAO.getMaxBid(itemId); move lock before // uses load with Lock.UPGRADE getMinBid/ YES Item item = itemDAO.findById(itemId, true); getMaxBid Bid newBid = item.placeBid(userDAO.findById(userId, false), newAmount, currentMaxBid, currentMinBid); // ... } } 18 Tuesday, November 22, 2011
  • 29. How To Fix It? version and NO optimistic locking REPEATABLE public class PlaceBidAction implements Action { NO // invoked in a new transaction READS public String execute(Map even) { // ... SERIALIZABLE YES Bid currentMinBid = itemDAO.getMinBid(itemId); Bid currentMaxBid = itemDAO.getMaxBid(itemId); move lock before // uses load with Lock.UPGRADE getMinBid/ YES Item item = itemDAO.findById(itemId, true); getMaxBid Bid newBid = item.placeBid(userDAO.findById(userId, false), newAmount, currentMaxBid, different currentMinBid); object model // ... } } 18 Tuesday, November 22, 2011
  • 30. How To Fix It? version and NO optimistic locking REPEATABLE public class PlaceBidAction implements Action { NO // invoked in a new transaction READS public String execute(Map even) { // ... SERIALIZABLE YES Bid currentMinBid = itemDAO.getMinBid(itemId); Bid currentMaxBid = itemDAO.getMaxBid(itemId); move lock before // uses load with Lock.UPGRADE getMinBid/ YES Item item = itemDAO.findById(itemId, true); getMaxBid Bid newBid = item.placeBid(userDAO.findById(userId, false), newAmount, currentMaxBid, different YES currentMinBid); object model // ... } } 18 Tuesday, November 22, 2011
  • 31. How To Fix It? version and NO optimistic locking REPEATABLE public class PlaceBidAction implements Action { NO // invoked in a new transaction READS public String execute(Map even) { // ... SERIALIZABLE YES Bid currentMinBid = itemDAO.getMinBid(itemId); Bid currentMaxBid = itemDAO.getMaxBid(itemId); move lock before // uses load with Lock.UPGRADE getMinBid/ YES Item item = itemDAO.findById(itemId, true); getMaxBid Bid newBid = item.placeBid(userDAO.findById(userId, false), newAmount, currentMaxBid, different YES currentMinBid); object model // ... } } Java synchronized 18 Tuesday, November 22, 2011
  • 32. How To Fix It? version and NO optimistic locking REPEATABLE public class PlaceBidAction implements Action { NO // invoked in a new transaction READS public String execute(Map even) { // ... SERIALIZABLE YES Bid currentMinBid = itemDAO.getMinBid(itemId); Bid currentMaxBid = itemDAO.getMaxBid(itemId); move lock before // uses load with Lock.UPGRADE getMinBid/ YES Item item = itemDAO.findById(itemId, true); getMaxBid Bid newBid = item.placeBid(userDAO.findById(userId, false), newAmount, currentMaxBid, different YES currentMinBid); object model // ... } Java } YES synchronized 18 Tuesday, November 22, 2011
  • 33. Lessons Learned • Nobody’s perfect ;-) • ACID is only a theory –Simple transaction interceptor/annotation often is not enough –Query order does matter –Learn more about locks and transaction isolation levels • Premature optimization is the root of all evil –Performance Anti-Pattern #1 19 Tuesday, November 22, 2011
  • 34. Performance Lessons • Object model • Usage patterns –Concurrent users –Data volume • Transaction and locking management 20 Tuesday, November 22, 2011
  • 35. Puzzle #2 Heads of Hydra Tuesday, November 22, 2011
  • 36. Heads of Hydra @Entity public class Hydra { private Long id; private List<Head> heads = new ArrayList<Head>(); @Id @GeneratedValue public Long getId() {...} protected void setId() {...} @OneToMany(cascade=CascadeType.ALL) public List<Head> getHeads() { return Collections.unmodifiableList(heads); } protected void setHeads(List<Head> heads) {...} } // creates and persists the hydra with 3 heads // new EntityManager and new transaction Hydra found = em.find(Hydra.class, hydra.getId()); 22 Tuesday, November 22, 2011
  • 37. How Many Queries in 2nd Tx? (a) 1 select (b) 2 selects @Entity (c) 1+3 selects public class Hydra { private Long id; (d) 2 selects, 1 delete, 3 private List<Head> heads = new ArrayList<Head>(); inserts (e) None of the above @Id @GeneratedValue public Long getId() {...} protected void setId() {...} @OneToMany(cascade=CascadeType.ALL) public List<Head> getHeads() { return Collections.unmodifiableList(heads); } protected void setHeads(List<Head> heads) {...} } // creates and persists the hydra with 3 heads // new EntityManager and new transaction Hydra found = em.find(Hydra.class, hydra.getId()); 23 Tuesday, November 22, 2011
  • 38. How Many Queries in 2nd Tx? (a) 1 select (b) 2 selects (c) 1+3 selects (d) 2 selects, 1 delete, 3 inserts (e) None of the above During commit hibernate checks whether the collection property is dirty (needs to be re- created) by comparing Java identities (object references). 24 Tuesday, November 22, 2011
  • 39. Another Look @Entity public class Hydra { private Long id; private List<Head> heads = new ArrayList<Head>(); @Id @GeneratedValue public Long getId() {...} protected void setId() {...} @OneToMany(cascade=CascadeType.ALL) public List<Head> getHeads() { return Collections.unmodifiableList(heads); } protected void setHeads(List<Head> heads) {...} } // creates and persists hydra with three heads // new EntityManager and new transaction // during find only 1 select (hydra) Hydra found = em.find(Hydra.class, hydra.getId()); // during commit 1 select (heads),1 delete (heads),3 inserts (heads) 25 Tuesday, November 22, 2011
  • 40. How To Fix It? @Entity public class Hydra { @Id @GeneratedValue private Long id; @OneToMany(cascade=CascadeType.ALL) private List<Head> heads = new ArrayList<Head>(); public Long getId() {...} protected void setId() {...} public List<Head> getHeads() { return Collections.unmodifiableList(heads); } protected void setHeads(List<Head> heads) {...} } // creates and persists hydra with three heads // new EntityManager and new transaction Hydra found = em.find(Hydra.class, hydra.getId()); 26 Tuesday, November 22, 2011
  • 41. Lessons Learned • Expect unexpected ;-) • Prefer field access mappings • And... 27 Tuesday, November 22, 2011
  • 42. Anti-Pattern #2 Lost Collection Proxy on Owning Side Tuesday, November 22, 2011
  • 43. Lost Collection Proxy • Description –On the owning side of an association, we assign a new collection object to a persistent field/property overriding a collection proxy returned by hibernate • Consequences –The entire collection is re-created: one delete to remove all elements and then many element inserts 29 Tuesday, November 22, 2011
  • 44. Lost Collection Proxy - Example @Entity public class Hydra { @Id @GeneratedValue private Long id; @OneToMany(cascade=CascadeType.ALL) private List<Head> heads = new ArrayList<Head>(); public Long getId() {...} protected void setId() {...} public List<Head> getHeads() { return heads; } public void setHeads(List<Head> heads) { this.heads = heads; } } 30 Tuesday, November 22, 2011
  • 45. Lost Collection Proxy - Solution • Operate on collection objects returned by hibernate –In most cases it’s a much more efficient solution • Unless you know what you’re doing –It might be performance-wise in some cases to re- create the entire collection (bulk delete) –However, it’s the place when hibernate could do better, having all required data available: • Original size, added and removed elements • Min(#added + #removed, 1 + #size - #removed + #added) 31 Tuesday, November 22, 2011
  • 46. Puzzle #3 Fashionable Developer Tuesday, November 22, 2011
  • 47. Fashionable Developer @Entity public class Developer { @Id @GeneratedValue private Long id; private String mainTechnology; public boolean likesMainTechnology() { return "hibernate".equalsIgnoreCase(mainTechnology); } } // creates and persists a developer that uses hibernate as mainTechnology // new EntityManager and new transaction Developer dev = em.find(Developer.class, id); boolean foundCoolStuff = false; for (String tech : new String[]{"HTML5", "Android", "Scala"}) { dev.setMainTechnology(tech); // othersAreUsingIt: // select count(*) from Developer where mainTechnology = ? and id != ? if (othersAreUsingIt(tech, dev) && dev.likesMainTechnology()) { foundCoolStuff = true; break; } } if (!foundCoolStuff) { // still use hibernate dev.setMainTechnology("hibernate"); 33 } Tuesday, November 22, 2011
  • 48. How Many Queries in 2nd Tx? @Entity public class Developer { (a) 2 select @Id @GeneratedValue (b) 4 selects private Long id; private String mainTechnology; (c) 4 selects, 1 update (d) 4 selects, 4 updates public boolean likesMainTechnology() { (e) None of the above return "hibernate".equalsIgnoreCase(mainTechnology); } } // creates and persists a developer that uses hibernate as mainTechnology // new EntityManager and new transaction Developer dev = em.find(Developer.class, id); boolean foundCoolStuff = false; for (String tech : new String[]{"HTML5", "Android", "Scala"}) { dev.setMainTechnology(tech); // othersAreUsingIt: // select count(*) from Developer where mainTechnology = ? and id != ? if (othersAreUsingIt(tech, dev) && dev.likesMainTechnology()) { foundCoolStuff = true; break; } } if (!foundCoolStuff) { // still use hibernate dev.setMainTechnology("hibernate"); 34 } Tuesday, November 22, 2011
  • 49. How Many Queries in 2nd Tx? (a) 2 selects (b) 4 selects (c) 4 selects, 1 update (d) 4 selects, 4 inserts (e) None of the above Hibernate must guarantee correctness of executed queries, therefore in certain situations it must perform flushes during a transaction. 35 Tuesday, November 22, 2011
  • 50. Fashionable Developer @Entity public class Developer { @Id @GeneratedValue private Long id; private String mainTechnology; NO UPDATES public boolean likesMainTechnology() { return "hibernate".equalsIgnoreCase(mainTechnology); } } // creates and persists a developer that uses hibernate as mainTechnology // new EntityManager and new transaction Developer dev = em.find(Developer.class, id); boolean foundCoolStuff = false; for (String tech : new String[]{"HTML5", "Android", "Scala"}) { dev.setMainTechnology(tech); // othersAreUsingIt: // select count(*) from Developer where mainTechnology = ? and id != ? if (/*othersAreUsingIt(tech, dev) &&*/ dev.likesMainTechnology()) { foundCoolStuff = true; break; } } if (!foundCoolStuff) { // still use hibernate dev.setMainTechnology("hibernate"); 36 } Tuesday, November 22, 2011
  • 51. Anti-Pattern #3 Temporary Changes Tuesday, November 22, 2011
  • 52. Temporary Changes • Description –We change the persistent data of an object temporarily to test some features –In the meantime a database flush occurs triggered, for example, by a HQL touching the table • Consequences –Flushes can be performed during the transaction, not only at the commit time –Temporary changes persisted into the database unnecessarily • Solution –Plan your business model and processing to avoid temporary changes to your persistent data 38 Tuesday, November 22, 2011
  • 53. Puzzle #4 Plant a Tree Tuesday, November 22, 2011
  • 54. Plant a Tree @Entity public class Forest { @Id @GeneratedValue private Long id; @OneToMany Collection<Tree> trees = new HashSet<Tree>(); public void plantTree(Tree tree) { trees.add(tree); } } // creates and persists a forest with 10.000 trees // new EntityManager and new transaction Tree tree = new Tree(“oak”); em.persist(tree); Forest forest = em.find(Forest.class, id); forest.plantTree(tree); 40 Tuesday, November 22, 2011
  • 55. How Many Queries in 2nd Tx? @Entity (a) 1 select, 2 inserts public class Forest { (b) 2 selects, 2 inserts @Id @GeneratedValue (c) 2 selects, 1 delete, private Long id; @OneToMany 10.000+2 inserts Collection<Tree> trees = new HashSet<Tree>(); (d) Even more ;-) public void plantTree(Tree tree) { trees.add(tree); } } // creates and persists a forest with 10.000 trees // new EntityManager and new transaction Tree tree = new Tree(“oak”); em.persist(tree); Forest forest = em.find(Forest.class, id); forest.plantTree(tree); 41 Tuesday, November 22, 2011
  • 56. How Many Queries in 2nd Tx? (a) 1 select, 2 inserts (b) 2 selects, 2 inserts (c) 2 selects, 1 delete, 10.000+2 inserts (d) Even more ;-) The combination of OneToMany and Collection enables a bag semantic. That’s why the collection is re-created. 42 Tuesday, November 22, 2011
  • 57. Plant a Tree - Revisited @Entity public class Orchard { @Id @GeneratedValue private Long id; @OneToMany List<Tree> trees = new ArrayList<Tree>(); public void plantTree(Tree tree) { trees.add(tree); } } // creates and persists a forest with 10.000 trees // new EntityManager and new transaction Tree tree = new Tree(“apple tree”); em.persist(tree); Orchard orchard = em.find(Orchard.class, id); orchard.plantTree(tree); 43 Tuesday, November 22, 2011
  • 58. Plant a Tree - Revisited @Entity public class Orchard { STILL BAG SEMANTIC! @Id @GeneratedValue private Long id; @OneToMany List<Tree> trees = new ArrayList<Tree>(); public void plantTree(Tree tree) { trees.add(tree); } } // creates and persists a forest with 10.000 trees // new EntityManager and new transaction Tree tree = new Tree(“apple tree”); em.persist(tree); Orchard orchard = em.find(Orchard.class, id); orchard.plantTree(tree); 43 Tuesday, November 22, 2011
  • 59. Plant a Tree - Revisited @Entity public class Orchard { STILL BAG SEMANTIC! @Id @GeneratedValue private Long id; Use OrderColumn or @OneToMany List<Tree> trees = new ArrayList<Tree>(); IndexColumn for list semantic. public void plantTree(Tree tree) { trees.add(tree); } } // creates and persists a forest with 10.000 trees // new EntityManager and new transaction Tree tree = new Tree(“apple tree”); em.persist(tree); Orchard orchard = em.find(Orchard.class, id); orchard.plantTree(tree); 43 Tuesday, November 22, 2011
  • 60. OneToMany Mapping Seman&c Java  Type Annota&on java.u3l.Collec3on bag  seman3c java.u3l.List @ElementCollec3on  || @OneToMany  ||  @ManyToMany set  seman3c java.u3l.Set @ElementCollec3on  || @OneToMany  ||  @ManyToMany (@ElementCollec3on  || @OneToMany  ||  @ManyToMany)   list  seman3c java.u3l.List && (@OrderColumn  ||   @IndexColumn) @OneToMany  (no  cascade  op3on) 44 Tuesday, November 22, 2011
  • 61. OneToMany Mapping add   remove   update   element element element bag   re-­‐create: re-­‐create: 1  update seman3c 1  delete  +  N  inserts 1  delete  +  N  inserts set   1  insert 1  delete 1  update seman3c list   1  insert  +  M   1  delete  +  M   1  update seman3c updates updates* @OneToMany  (no  cascade  op3on) 45 Tuesday, November 22, 2011
  • 62. OneToMany Mapping add   remove   update   element element element bag   re-­‐create: re-­‐create: 1  update seman3c 1  delete  +  N  inserts 1  delete  +  N  inserts set   1  insert 1  delete 1  update seman3c list   1  insert  +  M   1  delete  +  M   1  update seman3c updates updates* @OneToMany  (no  cascade  op3on) 46 Tuesday, November 22, 2011
  • 63. OneToMany Mapping add   remove   update   element element element Oops, we have a problem. bag   (list: removal of nth element, n < size-2) re-­‐create: re-­‐create: seman3c 1  delete  +  N  inserts 1  delete  +  N  inserts 1  update set   1  insert 1  delete 1  update seman3c list   1  insert  +  M   1  delete  +  M   1  update seman3c updates updates* @OneToMany  (no  cascade  op3on) 47 Tuesday, November 22, 2011
  • 64. Anti-Pattern #4 Inadequate Collection Type (Owning Side) Tuesday, November 22, 2011
  • 65. Inadequate Collection Mapping (Owning Side) • Description –Chosen an inadequate collection mapping on the owning side • Consequences –Additional queries executed • Solution –Consider your use cases and usage patterns and choose a mapping with the least performance overhead 49 Tuesday, November 22, 2011
  • 66. Plant a Tree @Entity public class Forest { @Id @GeneratedValue private Long id; @OneToMany Set<Tree> trees = new HashSet<Tree>(); public void plantTree(Tree tree) { trees.add(tree); } } // creates and persists a forest with 10.000 trees // new EntityManager and new transaction Tree oak = new Tree(“oak”); em.persist(oak); Forest forest = em.find(Forest.class, id); forest.plantTree(oak); 50 Tuesday, November 22, 2011
  • 67. Anti-Pattern #5 OneToMany as Owning Side Tuesday, November 22, 2011
  • 68. OneToMany as Owning Side • Description –OneToMany used as the owning side of a relationship • Consequences –Collection elements loaded into memory –Possibly unnecessary queries –Transaction and locking schema problems: version, optimistic locking • Solution –Use ManyToOne as the owning side and OneToMany as the inverse side –Or at least exclude the collection from locking • @OptimisticLock(excluded=true) . 52 Tuesday, November 22, 2011
  • 69. Plant a Tree @Entity public class Forest { @Id @GeneratedValue private Long id; @OneToMany (mappedBy = “forest”) Set<Tree> trees = new HashSet<Tree>(); public void plantTree(Tree tree) { trees.add(tree); } } @Entity public class Tree { @Id @GeneratedValue private Long id; private String name; @ManyToOne Forest forest; public void setForest(Forest forest) { this.forest = forest; this.forest.plantTree(this); } } 53 Tuesday, November 22, 2011
  • 70. Plant a Tree @Entity public class Forest { @Id @GeneratedValue private Long id; @OneToMany (mappedBy = “forest”) Set<Tree> trees = new HashSet<Tree>(); public void plantTree(Tree tree) { trees.add(tree); } } @Entity public class Tree { @Id @GeneratedValue private Long id; private String name; @ManyToOne Forest forest; public void setForest(Forest forest) { this.forest = forest; this.forest.plantTree(this); } } 54 Tuesday, November 22, 2011
  • 71. Anti-Pattern #6 Inadequate Collection Type (Inverse Side) Tuesday, November 22, 2011
  • 72. Inadequate Collection Type (Inverse Side) • Description –Set used as a collection type on the inverse side of a relationship and, to keep the model consistent, the owning side updates the inverse side • Consequences –Due to a set semantic, all elements must be loaded when we add a new element • Solution –Use Collection or List instead 56 Tuesday, November 22, 2011
  • 73. Plant a Tree @Entity public class Forest { @Id @GeneratedValue private Long id; @OneToMany (mappedBy = “forest”) Collection<Tree> trees = new HashSet<Tree>(); public void plantTree(Tree tree) { trees.add(tree); } } @Entity public class Tree { @Id @GeneratedValue private Long id; private String name; @ManyToOne Forest forest; public void setForest(Forest forest) { this.forest = forest; this.forest.plantTree(this); } } 57 Tuesday, November 22, 2011
  • 74. Plant a Tree @Entity public class Forest { @Id @GeneratedValue private Long id; @OneToMany (mappedBy = “forest”) Collection<Tree> trees = new HashSet<Tree>(); public void plantTree(Tree tree) { trees.add(tree); } } @Entity public class Tree { @Id @GeneratedValue private Long id; private String name; @ManyToOne Forest forest; // ... } // creates and persists a forest with 10.000 trees // new EntityManager and new transaction em.remove(forest); 58 Tuesday, November 22, 2011
  • 75. Plant a Tree @Entity public class Forest { @Id @GeneratedValue private Long id; @OneToMany (mappedBy = “forest”) Collection<Tree> trees = new HashSet<Tree>(); public void plantTree(Tree tree) { trees.add(tree); } } @Entity public class Tree { @Id @GeneratedValue private Long id; private String name; @ManyToOne Forest forest; // ... } // creates and persists a forest with 10.000 trees // new EntityManager and new transaction em.remove(forest); 58 Tuesday, November 22, 2011
  • 76. Plant a Tree @Entity public class Forest { @Id @GeneratedValue private Long id; @OneToMany (mappedBy = “forest”) Collection<Tree> trees = new HashSet<Tree>(); // ... } @Entity public class Tree { @Id @GeneratedValue private Long id; private String name; @ManyToOne Forest forest; // ... } // creates and persists a forest with 10.000 trees // new EntityManager and new transaction for (Tree tree : forest.getTrees()) { tree.setForest(null); } 59 em.remove(forest); Tuesday, November 22, 2011
  • 77. Plant a Tree @Entity public class Forest { @Id @GeneratedValue private Long id; @OneToMany (mappedBy = “forest”) Collection<Tree> trees = new HashSet<Tree>(); // ... } @Entity public class Tree { @Id @GeneratedValue private Long id; 10.000 UPDATES private String name; @ManyToOne 1 DELETE Forest forest; // ... } // creates and persists a forest with 10.000 trees // new EntityManager and new transaction for (Tree tree : forest.getTrees()) { tree.setForest(null); } 59 em.remove(forest); Tuesday, November 22, 2011
  • 78. Anti-Pattern #7 One by One Processing Tuesday, November 22, 2011
  • 79. Inadequate Collection Type (Inverse Side) • Description –Sequential processing of a persistent collection/objects • Consequences –Each database operation performed separately for each element • Solution –Bulk queries –That’s why CaveatEmptor was implemented like this (aggregate function on a database level) 61 Tuesday, November 22, 2011
  • 80. Conclusions • Big data cause big problems –Standard mappings don’t handle large datasets well –Smart model, bulk processing, projections • RTFM –Most of information can be found in the hibernate docs –Understand what you read –Think about consequences –And hopefully you’ll be fine :) • Hibernate –Smarter policies and data structures 62 Tuesday, November 22, 2011
  • 81. Contact • email: patrycja@yonita.com • twitter: @yonlabs • www: http://www.yonita.com 63 Tuesday, November 22, 2011