$30 off During Our Annual Pro Sale. View Details »

JPA - Beyond Copy-Paste

JPA - Beyond Copy-Paste

Jakub Kubryński

May 19, 2017
Tweet

More Decks by Jakub Kubryński

Other Decks in Programming

Transcript

  1. @jkubrynski / kubrynski.com
    JPA - BEYOND COPY-PASTE
    JAKUB KUBRYNSKI
    [email protected] / @jkubrynski / http://kubrynski.com

    View Slide

  2. WHOAMI
    DEVSKILLER CO-FOUNDER
    BOTTEGA TRAINER
    DEVOXX.PL PROGRAM COMMITTEE
    SPRING CLOUD CONTRACT CO-AUTHOR

    View Slide

  3. View Slide

  4. ALL NON-TRIVIAL ABSTRACTIONS, TO SOME DEGREE, ARE LEAKY.
    JOEL SPOLSKY

    View Slide

  5. @Entity
    public class Product {
    @Id
    @GeneratedValue
    private Long id;
    @Column
    private String name;
    // ...
    }

    View Slide

  6. @Entity
    public class Product {
    @Id
    @GeneratedValue
    private Long id;
    @Column // it does exactly nothing
    private String name;
    // ...
    }

    View Slide

  7. @Transactional @Service
    public class ProductService {
    public void updatePrice(Long productId, Money newPrice) {
    Product product = productRepository.find(productId);
    product.setPrice(newPrice);
    productRepository.save(product);
    }
    }

    View Slide

  8. @Transactional @Service
    public class ProductService {
    public void updatePrice(Long productId, Money newPrice) {
    Product product = productRepository.find(productId);
    product.setPrice(newPrice);
    productRepository.save(product); // it does exactly nothing
    }
    }

    View Slide

  9. FIELDS VS GETTERS
    @Entity
    public class Product {
    private Long id;
    private String name;
    @Id
    public Long getId() {
    return id;
    }
    }

    View Slide

  10. MIXED ACCESS
    @Entity
    @Access(AccessType.FIELD)
    public class Product {
    private Long id;
    private String name;
    @Id
    @Access(AccessType.PROPERTY)
    public Long getId() {
    return id;
    }
    }

    View Slide

  11. @Entity
    public class Order {
    }

    View Slide

  12. @Entity(name = "orders")
    public class Order {
    }

    View Slide

  13. @Entity(name = "orders")
    public class Order {
    }
    insert into orders ...

    View Slide

  14. @Entity(name = "orders")
    public class Order {
    }
    em.createQuery("SELECT o FROM Order o")

    View Slide

  15. @Entity(name = "orders")
    public class Order {
    }
    em.createQuery("SELECT o FROM orders o")

    View Slide

  16. @Entity
    @Table(name = "orders")
    public class Order {
    }

    View Slide

  17. MAPPINGS

    View Slide

  18. ONE TO ONE
    @Entity
    public class Customer {
    @OneToOne
    private Address address;
    }
    @Entity
    public class Address {
    @OneToOne
    private Customer customer;
    }

    View Slide

  19. ONE TO ONE
    @Entity
    public class Customer {
    @OneToOne
    private Address address;
    }
    @Entity
    public class Address {
    @OneToOne(mappedBy = "address")
    private Customer customer;
    }

    View Slide

  20. ONE TO MANY
    @Entity
    public class Customer {
    @OneToMany
    private Set addresses;
    }

    View Slide

  21. ONE TO MANY
    @Entity
    public class Customer {
    @OneToMany
    @JoinColumn(name = "customer_id")
    private Set addresses;
    }

    View Slide

  22. MANY TO MANY
    @Entity
    public class Customer {
    @ManyToMany
    private Collection addresses;
    }
    @Entity
    public class Address {
    @ManyToMany
    private Collection customers;
    }

    View Slide

  23. LAZY LOADING
    element is loaded only when required
    proxy by subclassing, but not always
    needed

    View Slide

  24. LAZY LOADING
    Custom
    collections
    PersistentSet
    PersistentBag
    PersistentList

    View Slide

  25. SET, BAG OR LIST?
    @OneToMany
    Set products;

    View Slide

  26. SET, BAG OR LIST?
    @OneToMany
    List products;

    View Slide

  27. SET, BAG OR LIST?
    @OneToMany
    @OrderColumn
    List products;

    View Slide

  28. N+1
    @Entity
    public class User {
    @OneToMany
    private List addresses;
    }
    List users = em.createQuery("SELECT u FROM User u").getResultList();
    for (User user : users) {
    for (Address address : user.getAddresses()) {
    ...
    }
    }

    View Slide

  29. N+1
    @Entity
    public class User {
    @OneToMany
    @BatchSize(size = 10)
    private List addresses;
    }

    View Slide

  30. N+1
    SELECT DISTINCT u FROM User u
    JOIN FETCH u.addresses

    View Slide

  31. HOW TO SAVE
    EntityManager.persist()
    EntityManager.merge()

    View Slide

  32. OPTIMISTIC LOCKING
    @Entity
    public class User {
    @Version
    private int version;
    }

    View Slide

  33. OPTIMISTIC LOCKING IN REST
    NEVER HEARD OF IT

    View Slide

  34. IDENTITY
    EQUALS() AND HASHCODE()

    View Slide

  35. BASE CLASS
    @MappedSuperclass
    public abstract class BaseEntity implements Serializable {
    @Id @GeneratedValue
    private Long id;
    private String uuid = UUID.randomUUID().toString();
    public int hashCode() {
    return Objects.hash(uuid);
    }
    public boolean equals(Object that) {
    return this == that || that instanceof BaseEntity
    && Objects.equals(uuid, ((BaseEntity) that).uuid);
    }

    View Slide

  36. CACHING
    L1 - EntityManager cache / Session cache
    L2 - EntityManagerFactory cache / SessionFactory
    cache
    QueryCache

    View Slide

  37. FLUSH MODES
    MANUAL
    COMMIT
    AUTO
    ALWAYS

    View Slide

  38. LEVEL 1 CACHE PITFALLS
    FLUSH() AND CLEAR()

    View Slide

  39. LEVEL 2 CACHE PITFALLS
    DISTRIBUTED ENVIRONMENT

    View Slide

  40. HQL INJECTION
    String hqlQuery = "SELECT p FROM Product p where p.category = '" + cat + "'";
    List products = em.createQuery(hqlQuery, Product.class)
    .getResultList();

    View Slide

  41. MATERIALS
    Hibernate logs analysis
    Hibernate code debugging :-)
    https://leanpub.com/high-performance-java-
    persistence
    https://vladmihalcea.com
    http://www.jooq.org

    View Slide

  42. QUESTIONS?

    View Slide

  43. THANKS

    View Slide

  44. DYNAMIC UPDATES
    @Entity
    @DynamicUpdate
    public class MyEntity {
    // ...
    }

    View Slide

  45. DYNAMIC INSERTS
    @Entity
    @DynamicInsert
    public class MyEntity {
    // ...
    }

    View Slide