Presentation is loading. Please wait.

Presentation is loading. Please wait.

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

Similar presentations


Presentation on theme: "Patterns and Anti-Patterns in Hibernate Patrycja Wegrzynowicz CTO, Yonita, Inc. CTO, Yon Labs and Yon Consulting, LLC."— 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 Aspects of 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 – Concurrent Scenario 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 Two bids in the database: 100, 124 12 34 successful bid: 9999 successful bid: 1000

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

11 CaveatEmptor – Hibernate Versioning 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) Two bids in the database: 100, 124 12 34 successful bid: 9999 successful bid: 1000

12 CaveatEmptor – Repeatable Reads 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) Two bids in the database: 100, 124 12 34 successful bid: 9999 successful bid: 1000

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 All transactions 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 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 18 Alternative Aproaches Inverse Mappings with Embedded Queries <set name=„maxBids" inverse="true" lazy=„true"> > 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 […] Anemic Domain Model! Is This a Good OO 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 Encapsulation Restrive 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 Encapsulation Consistent Management of Internal State All roads lead to Rome // 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; }

37 Practices to Code for Encapsulation Do Not Expose Mutable Internal State Problems mainly in the case of Date and Collection hierarchies return date; // Date return bids; // List 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 38 Practices to Code for Encapsulation Immutable 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 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 Hibernate Slow? Sometimes… Depending on usage scenarios

47 Puzzle #4 Standard Collection Mapping

48

49

50 Puzzle #5 Immutable Collections

51 Puzzle #5 Immutable Collections – Hint

52 Puzzle #5 Immutable Collection

53 Inheritance Strategies > Table per class hierarchy –One table > Table per subclass –Four tables > Table per concrete class –Two tables A > B > C D

54 Inheritance Strategies in Hibernate ConstraintsDirect AccessPolymorphism Table per Class Hierarchy Sometimes impossible to add db constrains (e.g. not null) Fast Polymorphic search Polymorphic relations Table per Subclass Constraints possibleSlower (joins) Polymorphic search Polymorphic relations Table per Concrete Class Constraints possibleFast Polymorphic search with unions or N queries + ++ ++ + ! ! ÷

55 AUTOMATED DETECTION OF HIBERNATE ISSUES

56 Code Level

57 Code Level Analysis

58

59 Automated Detection of Code Issues + Automated code analysis Definions of transactional, security, performance anti- patterns

60 Semantic Code Query System Code query systems Explore relationships among program elements Structural and call-related predicates CodeQuest, JQuery Semantic code query systems Focus on behavior (in-depth data flow analysis) Behavioral predicates in addition to structural ones D-CUBED – my PhD thesis (focus on design patterns) Yonita – rewrite + queries

61 Yonita Automated code analysis Semantic code query system Focus on behavior, not only structure Metamodel of a program: instances, structure, behaviour (calls, input/output values, execution paths) Definitions of various issues/anti-patterns Catalog of issues Transactions, object-oriented design, security, performance, multithreading

62 How does Yonita work? Analyses Parser Store Query Bytecode Sources asm, Recoder analyses: structural, call flow, data flow transitive closures relational (MySQL) or deductive (XSB) database SQL or Prolog (anti-)patterns bugs vulnerabilities...

63 Metamodel Structural elements Very similar to CodeQuest and Jquery Statements Instances Symbolic instances Behavioral predicates supporting call and data flows Output and input values Assignments

64 Instances Null New This Parameter Exception Multiple Return Instance Param Instance This Instance New Instance Null Instance Except. Instance … … …

65 Summary Proper usage of hibernate is tricky Transactional issues and correctness of code under various scenarios Maintanability and basic object-oriented principles Efficiency of code and mappings Automatization can help

66 Contact Patrycja patrycja@YonLabs.com twitter.com/YonLabs Yonita http://www.Yonita.com http://www.YonLabs.com http://www.YonConsulting.com


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

Similar presentations


Ads by Google