patterns and practices in hibernate
play

Patterns and Practices in Hibernate Patrycja Wegrzynowicz Yon - PowerPoint PPT Presentation

Patterns and Practices in Hibernate Patrycja Wegrzynowicz Yon Labs, Yon Consulting 100 Agenda > Introduction Usage Aspect of Hibernate CaveatEmptor Example > Object-Oriented Principles > Transactional Issues >


  1. Patterns and Practices in Hibernate Patrycja Wegrzynowicz Yon Labs, Yon Consulting 100

  2. Agenda > Introduction – Usage Aspect of Hibernate – CaveatEmptor Example > Object-Oriented Principles > Transactional Issues > Inheritance Strategies > Summary – Key Points to Remember 2

  3. Usage Aspects of Hibernate Architecture Object-Oriented Relational Database Design Design Programming 3

  4. CaveatEmptor Example > Java Persistence with Hibernate – Christian Bauer, Gavin King > CaveatEmptor – A demo application with the book – A simple auction system What is good and what is bad about CaveatEmptor? 4

  5. Object-Oriented Principles 5

  6. What is OO about? > Data Abstraction > SOLID – Data and Behaviour – Single Responsibility Principle > Encapsulation – Open/closed Principle > Inheritance – Liskov Substitution Principle > Polymorphism – Interface Segregation Principle – Dependency Inversion Principle 6

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

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

  9. Rich OO Model CaveatEmptor Auction Model […] […] […] […] 9

  10. CaveatEmptor Auction Model – A Closer Look Bid-related members of Item class private List<Bid> bids = new ArrayList<Bid>(); private Bid successfulBid; private Map<Long,Bid> bidsByIdentifier = new HashMap<Long,Bid>(); public List<Bid> getBids() public void addBid(Bid bid) public Bid getSuccessfulBid() public void setSuccessfulBid(Bid successfulBid) public Map<Long, Bid> getBidsByIdentifier() public void setBidsByIdentifier(Map<Long, Bid> bidsByIdentifier) public Bid placeBid(User bidder, MonetaryAmount bidAmount, Bid currentMaxBid, Bid currentMinBid) throws BusinessException 10

  11. We Need Encapsulation! We can add to this mutable list whatever we like public List<Bid> getBids() { return bids; } public void addBid(Bid bid) { if (bid == null ) throw new IllegalArgumentException("Can't add a null Bid."); this. getBids().add(bid); // Don't have to set the "other" side, a Bid can only be instantiated with a given item } We can add a bid with a different Item instance (Item constructor is public) 11

  12. Without Encapsulation Business Methods Are Only Lipstick on a Pig 12

  13. Exposed Structure Results in BAD Things > Inconsistent state of objects – The winning bid for an item which is not maximal – Buyer different that the bidder of the winning bid – 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 13

  14. Practices to Design for Encapsulation > Business Logic First – Business methods first – No matter whether a legacy or a new database, don’t do hibernate mappings in the early stage > Lazy Programming of Getters and Setters – Lean approach – No waste – No getters and setters by default, add them when there is a real need 14

  15. 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 Thank god hibernate is flexible! 15

  16. Practices to Code for Encapsulation Consistent Management of Internal State 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 16

  17. 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<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 17

  18. 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 18

  19. Practices to Code for Encapsulation Immutable Collection Puzzler public class Item { // … public getBids() { return Collections.unmodifiableList(bids); } public setBids(List<Bid> bids) { this. bids.clear(); if (bids != null ) this. bids.addAll(bids); } // … } item.setBids(item.getBids()); ? 19

  20. Transactional Issues 20

  21. CaveatEmptor – PlaceBidAction 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); 21

  22. CaveatEmptor – Concurrency Scenario Two bids in the database: 100, 124 Thread A – new bid 9999 Thread B – new bid 1000 22

  23. CaveatEmptor – Concurrency Scenario Two bids in the database: 100, 124 Thread A – new bid 9999 Thread B – new bid 1000 1 // two bids in db: 100, 124 Bid curMinBid = itemDAO.getMinBid(itemId); Bid curMaxBid = itemDAO.getMaxBid(itemId); // curMax = 124 23

  24. CaveatEmptor – Concurrency Scenario Two bids in the database: 100, 124 Thread A – new bid 9999 Thread B – new bid 1000 1 2 // two bids in db: 100, 124 // two bids in db: 100, 124 Bid curMinBid = itemDAO.getMinBid(itemId); Bid curMinBid = itemDAO.getMinBid(itemId); Bid curMaxBid = itemDAO.getMaxBid(itemId); Bid curMaxBid = itemDAO.getMaxBid(itemId); // curMax = 124 // curMax = 124 24

  25. CaveatEmptor – Concurrency Scenario Two bids in the database: 100, 124 Thread A – new bid 9999 Thread B – new bid 1000 1 2 // two bids in db: 100, 124 // two bids in db: 100, 124 Bid curMinBid = itemDAO.getMinBid(itemId); Bid curMinBid = itemDAO.getMinBid(itemId); Bid curMaxBid = itemDAO.getMaxBid(itemId); Bid curMaxBid = itemDAO.getMaxBid(itemId); // curMax = 124 // curMax = 124 3 // item with two bids: 100, 124 // curMax = 124 Item item = itemDAO.findById(itemId, true ); Bid newBid = item.placeBid(…, newAmount, curMaxBid, curMinBid); successful bid: 9999 25

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

  27. CaveatEmptor – Concurrency Scenario Two bids in the database: 100, 124 Thread A – new bid 9999 Thread B – new bid 1000 1 2 // two bids in db: 100, 124 // two bids in db: 100, 124 Bid curMinBid = itemDAO.getMinBid(itemId); Bid curMinBid = itemDAO.getMinBid(itemId); Bid curMaxBid = itemDAO.getMaxBid(itemId); Bid curMaxBid = itemDAO.getMaxBid(itemId); // curMax = 124 // curMax = 124 3 4 // item with two bids: 100, 124 // item with three bids: 100, 124, 9999 // curMax = 124 // but curMax = 124 Item item = itemDAO.findById(itemId, true ); Item item = itemDAO.findById(itemId, true ); Bid newBid = item.placeBid(…, newAmount, Bid newBid = item.placeBid(…, newAmount, currentMaxBid, currentMinBid); currentMaxBid, currentMinBid); successful bid: 9999 successful bid: 1000 27

  28. Even Worse – Depending on Isolation Level… 4 // item with three bids: 100, 124, 9999 // but curMax = 124 Item item = itemDAO.findById(itemId, true ); Bid newBid = item.placeBid(…, newAmount, currentMaxBid, currentMinBid); successful bid: 1000 READ_COMMITED REPEATABLE_READS BID1 (amount 100, bid_position 0) BID1 (amount 100, bid_position 0) BID2 (amount 124, bid_position 1) BID2 (amount 124, bid_position 1) BID3 (amount 9999, bid_position 2) BID3 (amount 9999, bid_position 2 ) BID4 (amount 1000, bid_position 3) BID4 (amount 1000, bid_position 2 ) next time hibernate will load only 3 bids for item 28

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend