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

Percona Live 2012PPT: MySQL Query optimization
Percona Live 2012PPT: MySQL Query optimizationPercona Live 2012PPT: MySQL Query optimization
Percona Live 2012PPT: MySQL Query optimizationmysqlops
 
MariaDB Optimization
MariaDB OptimizationMariaDB Optimization
MariaDB OptimizationJongJin Lee
 
Top 10 Mistakes When Migrating From Oracle to PostgreSQL
Top 10 Mistakes When Migrating From Oracle to PostgreSQLTop 10 Mistakes When Migrating From Oracle to PostgreSQL
Top 10 Mistakes When Migrating From Oracle to PostgreSQLJim Mlodgenski
 
Percona XtraBackup - New Features and Improvements
Percona XtraBackup - New Features and ImprovementsPercona XtraBackup - New Features and Improvements
Percona XtraBackup - New Features and ImprovementsMarcelo Altmann
 
All About JSON and ClickHouse - Tips, Tricks and New Features-2022-07-26-FINA...
All About JSON and ClickHouse - Tips, Tricks and New Features-2022-07-26-FINA...All About JSON and ClickHouse - Tips, Tricks and New Features-2022-07-26-FINA...
All About JSON and ClickHouse - Tips, Tricks and New Features-2022-07-26-FINA...Altinity Ltd
 
Redis & Redis HA design with Keepalived
Redis & Redis HA design with KeepalivedRedis & Redis HA design with Keepalived
Redis & Redis HA design with KeepalivedToshiki Inami
 
SQL Tuning, takes 3 to tango
SQL Tuning, takes 3 to tangoSQL Tuning, takes 3 to tango
SQL Tuning, takes 3 to tangoMauro Pagano
 
Deployment Patterns of WSO2 Identity Server
Deployment Patterns of WSO2 Identity ServerDeployment Patterns of WSO2 Identity Server
Deployment Patterns of WSO2 Identity ServerMifrazMurthaja
 
MySQL 8.0.16 New Features Summary
MySQL 8.0.16 New Features SummaryMySQL 8.0.16 New Features Summary
MySQL 8.0.16 New Features SummaryOlivier DASINI
 
0x003 - Exploiting LOLDrivers - Physical Memory Mayhem
0x003 - Exploiting LOLDrivers - Physical Memory Mayhem0x003 - Exploiting LOLDrivers - Physical Memory Mayhem
0x003 - Exploiting LOLDrivers - Physical Memory MayhemRussell Sanford
 
[OpenInfra Days Korea 2018] (Track 1) Kubernetes 환경에서의 Volume 배포와 데이터 관리의 유연성...
[OpenInfra Days Korea 2018] (Track 1) Kubernetes 환경에서의 Volume 배포와 데이터 관리의 유연성...[OpenInfra Days Korea 2018] (Track 1) Kubernetes 환경에서의 Volume 배포와 데이터 관리의 유연성...
[OpenInfra Days Korea 2018] (Track 1) Kubernetes 환경에서의 Volume 배포와 데이터 관리의 유연성...OpenStack Korea Community
 
Walking the Bifrost: An Operator's Guide to Heimdal & Kerberos on macOS
Walking the Bifrost: An Operator's Guide to Heimdal & Kerberos on macOSWalking the Bifrost: An Operator's Guide to Heimdal & Kerberos on macOS
Walking the Bifrost: An Operator's Guide to Heimdal & Kerberos on macOSCody Thomas
 
Deep Dive into MySQL InnoDB Cluster Read Scale-out Capabilities.pdf
Deep Dive into MySQL InnoDB Cluster Read Scale-out Capabilities.pdfDeep Dive into MySQL InnoDB Cluster Read Scale-out Capabilities.pdf
Deep Dive into MySQL InnoDB Cluster Read Scale-out Capabilities.pdfMiguel Araújo
 
Webinar - Key Reasons to Upgrade to MySQL 8.0 or MariaDB 10.11
Webinar - Key Reasons to Upgrade to MySQL 8.0 or MariaDB 10.11Webinar - Key Reasons to Upgrade to MySQL 8.0 or MariaDB 10.11
Webinar - Key Reasons to Upgrade to MySQL 8.0 or MariaDB 10.11Federico Razzoli
 
Random Thoughts on Paper Implementations [KAIST 2018]
Random Thoughts on Paper Implementations [KAIST 2018]Random Thoughts on Paper Implementations [KAIST 2018]
Random Thoughts on Paper Implementations [KAIST 2018]Taehoon Kim
 
[NDC 2018] 신입 개발자가 알아야 할 윈도우 메모리릭 디버깅
[NDC 2018] 신입 개발자가 알아야 할 윈도우 메모리릭 디버깅[NDC 2018] 신입 개발자가 알아야 할 윈도우 메모리릭 디버깅
[NDC 2018] 신입 개발자가 알아야 할 윈도우 메모리릭 디버깅DongMin Choi
 
Learn kubernetes in 90 minutes
Learn kubernetes in 90 minutesLearn kubernetes in 90 minutes
Learn kubernetes in 90 minutesLarry Cai
 
The consequences of sync_binlog != 1
The consequences of sync_binlog != 1The consequences of sync_binlog != 1
The consequences of sync_binlog != 1Jean-François Gagné
 
[TechPlayConf]Rekognition導入事例
[TechPlayConf]Rekognition導入事例[TechPlayConf]Rekognition導入事例
[TechPlayConf]Rekognition導入事例Shinji Miyazato
 
ProxySQL for MySQL
ProxySQL for MySQLProxySQL for MySQL
ProxySQL for MySQLMydbops
 

What's hot (20)

Percona Live 2012PPT: MySQL Query optimization
Percona Live 2012PPT: MySQL Query optimizationPercona Live 2012PPT: MySQL Query optimization
Percona Live 2012PPT: MySQL Query optimization
 
MariaDB Optimization
MariaDB OptimizationMariaDB Optimization
MariaDB Optimization
 
Top 10 Mistakes When Migrating From Oracle to PostgreSQL
Top 10 Mistakes When Migrating From Oracle to PostgreSQLTop 10 Mistakes When Migrating From Oracle to PostgreSQL
Top 10 Mistakes When Migrating From Oracle to PostgreSQL
 
Percona XtraBackup - New Features and Improvements
Percona XtraBackup - New Features and ImprovementsPercona XtraBackup - New Features and Improvements
Percona XtraBackup - New Features and Improvements
 
All About JSON and ClickHouse - Tips, Tricks and New Features-2022-07-26-FINA...
All About JSON and ClickHouse - Tips, Tricks and New Features-2022-07-26-FINA...All About JSON and ClickHouse - Tips, Tricks and New Features-2022-07-26-FINA...
All About JSON and ClickHouse - Tips, Tricks and New Features-2022-07-26-FINA...
 
Redis & Redis HA design with Keepalived
Redis & Redis HA design with KeepalivedRedis & Redis HA design with Keepalived
Redis & Redis HA design with Keepalived
 
SQL Tuning, takes 3 to tango
SQL Tuning, takes 3 to tangoSQL Tuning, takes 3 to tango
SQL Tuning, takes 3 to tango
 
Deployment Patterns of WSO2 Identity Server
Deployment Patterns of WSO2 Identity ServerDeployment Patterns of WSO2 Identity Server
Deployment Patterns of WSO2 Identity Server
 
MySQL 8.0.16 New Features Summary
MySQL 8.0.16 New Features SummaryMySQL 8.0.16 New Features Summary
MySQL 8.0.16 New Features Summary
 
0x003 - Exploiting LOLDrivers - Physical Memory Mayhem
0x003 - Exploiting LOLDrivers - Physical Memory Mayhem0x003 - Exploiting LOLDrivers - Physical Memory Mayhem
0x003 - Exploiting LOLDrivers - Physical Memory Mayhem
 
[OpenInfra Days Korea 2018] (Track 1) Kubernetes 환경에서의 Volume 배포와 데이터 관리의 유연성...
[OpenInfra Days Korea 2018] (Track 1) Kubernetes 환경에서의 Volume 배포와 데이터 관리의 유연성...[OpenInfra Days Korea 2018] (Track 1) Kubernetes 환경에서의 Volume 배포와 데이터 관리의 유연성...
[OpenInfra Days Korea 2018] (Track 1) Kubernetes 환경에서의 Volume 배포와 데이터 관리의 유연성...
 
Walking the Bifrost: An Operator's Guide to Heimdal & Kerberos on macOS
Walking the Bifrost: An Operator's Guide to Heimdal & Kerberos on macOSWalking the Bifrost: An Operator's Guide to Heimdal & Kerberos on macOS
Walking the Bifrost: An Operator's Guide to Heimdal & Kerberos on macOS
 
Deep Dive into MySQL InnoDB Cluster Read Scale-out Capabilities.pdf
Deep Dive into MySQL InnoDB Cluster Read Scale-out Capabilities.pdfDeep Dive into MySQL InnoDB Cluster Read Scale-out Capabilities.pdf
Deep Dive into MySQL InnoDB Cluster Read Scale-out Capabilities.pdf
 
Webinar - Key Reasons to Upgrade to MySQL 8.0 or MariaDB 10.11
Webinar - Key Reasons to Upgrade to MySQL 8.0 or MariaDB 10.11Webinar - Key Reasons to Upgrade to MySQL 8.0 or MariaDB 10.11
Webinar - Key Reasons to Upgrade to MySQL 8.0 or MariaDB 10.11
 
Random Thoughts on Paper Implementations [KAIST 2018]
Random Thoughts on Paper Implementations [KAIST 2018]Random Thoughts on Paper Implementations [KAIST 2018]
Random Thoughts on Paper Implementations [KAIST 2018]
 
[NDC 2018] 신입 개발자가 알아야 할 윈도우 메모리릭 디버깅
[NDC 2018] 신입 개발자가 알아야 할 윈도우 메모리릭 디버깅[NDC 2018] 신입 개발자가 알아야 할 윈도우 메모리릭 디버깅
[NDC 2018] 신입 개발자가 알아야 할 윈도우 메모리릭 디버깅
 
Learn kubernetes in 90 minutes
Learn kubernetes in 90 minutesLearn kubernetes in 90 minutes
Learn kubernetes in 90 minutes
 
The consequences of sync_binlog != 1
The consequences of sync_binlog != 1The consequences of sync_binlog != 1
The consequences of sync_binlog != 1
 
[TechPlayConf]Rekognition導入事例
[TechPlayConf]Rekognition導入事例[TechPlayConf]Rekognition導入事例
[TechPlayConf]Rekognition導入事例
 
ProxySQL for MySQL
ProxySQL for MySQLProxySQL for MySQL
ProxySQL for MySQL
 

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

Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfRankYa
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piececharlottematthew16
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr LapshynFwdays
 
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
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
The Future of Software Development - Devin AI Innovative Approach.pdf
The Future of Software Development - Devin AI Innovative Approach.pdfThe Future of Software Development - Devin AI Innovative Approach.pdf
The Future of Software Development - Devin AI Innovative Approach.pdfSeasiaInfotech2
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embeddingZilliz
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Wonjun Hwang
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostLeverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostZilliz
 
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
 

Recently uploaded (20)

Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdf
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piece
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
 
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
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
The Future of Software Development - Devin AI Innovative Approach.pdf
The Future of Software Development - Devin AI Innovative Approach.pdfThe Future of Software Development - Devin AI Innovative Approach.pdf
The Future of Software Development - Devin AI Innovative Approach.pdf
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embedding
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostLeverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
 
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
 

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