1 / 66

Patterns and Anti-Patterns in Hibernate

Patterns and Anti-Patterns in Hibernate. Patrycja Wegrzynowicz CTO, Yonita, Inc. CTO, Yon Labs and Yon Consulting, LLC. About me. Past 10+ years of practical experience as software developer, architect, and head of software R&D PhD in Computer Science (automated code analysis)

gizela
Download Presentation

Patterns and Anti-Patterns in Hibernate

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Patterns and Anti-Patterns in Hibernate Patrycja Wegrzynowicz CTO, Yonita, Inc. CTO, Yon Labs and Yon Consulting, LLC

  2. About me • Past • 10+ years of practical experience as software developer, architect, and head of software R&D • PhD in Computer Science (automated code analysis) • Speaker at JavaOne, JavaZone, Devoxx, Jazoon, OOPSLA, and others • Present • Founder and CTO of Yonita Inc. and Yon Consulting • Bridge the gap between the industry and the academia • Future • Who cares? Seize the day!

  3. Agenda • Transactional issues • Break  • Object-oriented issues • Break  • Performance issues • Break  • Automated detection

  4. Usage Aspectsof Hibernate Architecture Object-Oriented Design Relational DB Design Programming

  5. CaveatEmptor Demo • Java Persistence with Hibernate • Christian Bauer • Gavin King • CaveatEmptor • Demo in the book • Simple auction system

  6. Transactional Issues

  7. First and Foremost, Correctness • Warranty of correctness • A piece of code always produces an expected result • Scenarios • Various inputs • Concurrency • Time line

  8. Is CaveatEmptor Correct? transaction

  9. CaveatEmptor – ConcurrentScenario Two bids in the database: 100, 124 • Thread A – new bid 9999 • // begin transaction • // two bids in the db: 100, 124 • Bid curMinBid = itemDAO.getMinBid(itemId); • Bid curMaxBid = itemDAO.getMaxBid(itemId); • // curMaxBid = 124 • // get locked item • // item with two bids: 100, 124 • // curMaxBid = 124 • Item item = itemDAO.findById(itemId, true); • Bid newBid = item.placeBid(…, newAmount, • curMaxBid, curMinBid); • // commit transaction • Thread B – new bid 1000 • // begin transaction • // two bids in db: 100, 124 • Bid curMinBid = itemDAO.getMinBid(itemId); • Bid curMaxBid = itemDAO.getMaxBid(itemId); • // curMaxBid = 124 • // get locked item • // item with three bids: 100, 124, 9999 • // but curMaxBid = 124 • Item item = itemDAO.findById(itemId, true); • Bid newBid = item.placeBid(…, newAmount, • curMaxBid, curMinBid); • // commit transaction 1 2 3 4 successful bid: 1000 successful bid: 9999

  10. How to Fix It? REPEATABLE_READS NO HIBERNATE VERSIONING NO SERIALIZABLE YES YES

  11. CaveatEmptor – Hibernate Versioning Two bids in the database: 100, 124 • Thread A – new bid 9999 • // begin transaction • // two bids in the db: 100, 124 • Bid curMinBid = itemDAO.getMinBid(itemId); • Bid curMaxBid = itemDAO.getMaxBid(itemId); • // curMaxBid = 124 • // get item (version 1) • // item with two bids: 100, 124 • // curMaxBid = 124 • Item item = itemDAO.findById(itemId, true); • Bid newBid = item.placeBid(…, newAmount, • curMaxBid, curMinBid); • // commit transaction (version 2) • Thread B – new bid 1000 • // begin transaction • // two bids in db: 100, 124 • Bid curMinBid = itemDAO.getMinBid(itemId); • Bid curMaxBid = itemDAO.getMaxBid(itemId); • // curMaxBid = 124 • // get item (version 2) • // item with three bids: 100, 124, 9999 • // but curMaxBid = 124 • Item item = itemDAO.findById(itemId, true); • Bid newBid = item.placeBid(…, newAmount, • curMaxBid, curMinBid); • // commit transaction (version 3) 1 2 3 4 successful bid: 1000 successful bid: 9999

  12. CaveatEmptor – Repeatable Reads Two bids in the database: 100, 124 • Thread A – new bid 9999 • // begin transaction • // two bids in the db: 100, 124 • Bid curMinBid = itemDAO.getMinBid(itemId); • Bid curMaxBid = itemDAO.getMaxBid(itemId); • // curMaxBid = 124 • // get item (version 1) • // item with two bids: 100, 124 • // curMaxBid = 124 • Item item = itemDAO.findById(itemId, true); • Bid newBid = item.placeBid(…, newAmount, • curMaxBid, curMinBid); • // commit transaction (version 2) • Thread B – new bid 1000 • // begin transaction • // two bids in db: 100, 124 • Bid curMinBid = itemDAO.getMinBid(itemId); • Bid curMaxBid = itemDAO.getMaxBid(itemId); • // curMaxBid = 124 • // get item (version 2) • // item with two bids loaded: 100, 124 • // but curMaxBid = 124 • Item item = itemDAO.findById(itemId, true); • Bid newBid = item.placeBid(…, newAmount, • curMaxBid, curMinBid); • // commit transaction (version 3) 1 2 3 4 successful bid: 1000 successful bid: 9999

  13. CaveatEmptor - Repeatable Reads • Even worse • MySQL takes a snapshot of the database at the moment of the first query

  14. CaveatEmptor - Serializable • SERIALIZABLE works fine • Alltransactions occur in a completely isolated fashion; i.e., as if all transactions in the system had executed serially, one after the other • Snapshot isolation or lock-based concurrency control (read/write locks released at the end of a transaction, range-locks) • What about performance? • Can you imagine eBay working this way?

  15. CaveatEmptor - Re-Ordering

  16. CaveatEmptor - Re-Ordering • Item class • Represents item and auction; has the list of bids • Why to inject min and max bids (internal state) to an item? • Back to OO Principles • Objects should contain their internal state

  17. Alternative Approaches • Calculate maximum in Java • Safe, but requires loading of all the bids • Keep track of the winning bid • Manual tracking, but with encapsulation • Db denormalized, but fast • Utilize custom mappings with custom queries, laziness, order or where clauses • Db normalized, as fast as the present code

  18. Alternative AproachesInverse Mappings with Embedded Queries <set name=„maxBids" inverse="true" lazy=„true"> <key not-null="true"> <column name="ITEM_ID"/> </key> <one-to-many class="Bid"/> <loader query-ref="getMaxBid"/> </set> • Automated object state • Encapsulation • Inverse • Makes use of present relations • Normalized form • Lazy • Loaded on the first access • Custom queries • SQL  • Use order-by and where if they are enough

  19. Puzzle #1 getItemMaxBid select b from Bid b where b.amount.value = (select max(b.amount.value) from Bid b where b.item.id = :itemid)

  20. Puzzle #1 getItemMaxBid – Hint • Item #1 • Bid $100 • Bid $125 • Bid $150 • Item #2 • Bid $20 • Bid $125 select b from Bid b where b.amount.value = (select max(b.amount.value) from Bid b where b.item.id = :itemid)

  21. Puzzle #1 getItemMaxBid – Answer • Item #1 • Bid $100 • Bid $125 • Bid $150 • Item #2 • Bid $20 • Bid $125 • getItemMaxBid(Item#2) • Item #1 Bid $125 • Item #2 Bid $125 select b from Bid b where b.amount.value = (select max(b.amount.value) from Bid b where b.item.id = :itemid)

  22. Puzzle #1 getItemMaxBid – Fixed • Item #1 • Bid $100 • Bid $125 • Bid $150 • Item #2 • Bid $20 • Bid $125 • getItemMaxBid(Item#2) • Item #2 Bid $125 • select b • from Bid b • where b.amount.value = • (select max(b.amount.value) • from Bid b • where b.item.id = :itemid) • and b.item.id = :itemid

  23. Puzzle #2 placeBid

  24. Puzzle #2 placeBid – Hint

  25. Puzzle #2 placeBid – Fixed >=

  26. Object-Oriented Issues

  27. What is OO about? • Basic Principles • Data abstraction = data + behavior • Encapsulation, inheritance, polimorphism • Advanced Principles (SOLID) • Single Responsibility Principle • Open/Closed Principle • Liskov Substitution Principle • Interface Segregation Principle • Dependency Inversion Principle

  28. Is This a Good OO Model? […] […] […] […]

  29. Is This a Good OO Model? […] […] Anemic Domain Model! […] […]

  30. Rich OO Model – CaveatEmptor […] […] […] […]

  31. CaveatEmptor – A Closer Look

  32. We Need Encapsulation! We can add to the mutable list whatever we like. We can add a bid to the item with a different item reference.

  33. Without Encapsulation, Business Methods Are Only Lipstick on a Pig

  34. Exposed Structure Results in Bad Things • Inconsistent state of objects • The winning bid for an item which is not maximal • The winning bid added after the auction ended • Basically, we cannot trust our data! • Various Bugs • Null pointer exceptions • Nasty bugs (unexpected nulls, consider embedded objects!) • Too much code • Duplicated code, defensive code, spaghetti code

  35. Practices to Code for EncapsulationRestrive Access Modifiers • private, package, protected • fields, getters, setters • used by hibernate or to manage referential integrity • hibernate is able to deal with any access modifiers (even private!) of the members of a class

  36. Practices to Code for EncapsulationConsistent Management of Internal State // custom example! public Item(MonetaryAmount initialPrice) { // beware of polymorphic calls in constructors // it’s better to use a private _setInitialPrice from both the setter and ctr setInitialPrice(initialPrice); } public void setInitialPrice(MonetaryAmount initialPrice) { if (initialPrice == null) throw new IllegalArgumentException(„initial price cant be null”); this.initialPrice = initialPrice; } All roads lead to Rome

  37. Practices to Code for EncapsulationDo Not Expose Mutable Internal State • Problems mainly in the case of Date and Collection hierarchies • return date; // Date • return bids; // List<Bid> • Uncontrolled changes to the internal state of an object • Defensive copying • return new Date(created.getTime()); • return new ArrayList(bids); • Inefficient for collections – we force the retrieval of the bids from the database • Immutable • return Collections.unmodifiableList(bids); • Inefficient for persistent collections mapped by property as dirty checking compares collections by identity

  38. Practices to Code for EncapsulationImmutable Collection Returned • Dirty checking compares identity of collections • Additional statements issued • Embedded objects – recreation of the collection • List of entities – all entities updated • Practices • Internally, do not create new collections, reuse the one retrieved • Use field mapping, or • Use different accessors for public access and hibernate access

  39. Practices to Code for Encapsulation • Business first • First business methods, than accessors • Restrictive access modifiers • Hibernate can deal with private/package/protected • Don't expose mutable internal state • Problems mainly in the case of Date and Collections • return date; // Date • return bids; // List<Bid> • Uncontrolled changes to the internal state of an object

  40. Puzzle #3 Immutable List

  41. Puzzle #3 Immutable List - Hint item.setBids(item.getBids())?

  42. Puzzle #3 Immutable List - Answer item.setBids(item.getBids())? The answer: bids = empty list

  43. Performance Issues

  44. This is Java.

  45. Is Java Slow? • On most Intels Java is as fast or faster than C • The Gaia Satellie and Data Processing • William O’Mullane from ESAC • Jazoon 2010

  46. Is HibernateSlow? • Sometimes… • Depending on usage scenarios

  47. Puzzle #4 Standard Collection Mapping

  48. Puzzle #4 Standard Collection Mapping

  49. Puzzle #4 Standard Collection Mapping

  50. Puzzle #5Immutable Collections

More Related