Skip to content

Instantly share code, notes, and snippets.

@jamesdh
Forked from jahe/jpa-cheatsheet.java
Created August 27, 2021 04:32

Revisions

  1. @jahe jahe revised this gist Jun 24, 2018. 1 changed file with 20 additions and 1 deletion.
    21 changes: 20 additions & 1 deletion jpa-cheatsheet.java
    Original file line number Diff line number Diff line change
    @@ -387,4 +387,23 @@ public class Passport {
    public void createPerson() {
    em.persist(person1); // here the person gets its ID from the DB sequence, but the INSERT statement fires at the end of the transactional method
    person1.setName("Hans");
    } // here does the INSERT happen and after that the transaction COMMIT
    } // here does the INSERT happen and after that the transaction COMMIT

    // On a 1:n relationship the relating entity reference has to be set on both sides
    // But to add e.g. two new childs to a parent entity we only have to set the reference on both sides
    // and then call persist() only on the childs
    public void addReviewsForCourse() {
    Course course = em.find(Course.class, 1);

    Review goodReview = new Review("Super!");
    Review badReview = new Review("Bad!");

    course.addReview(goodReview);
    goodReview.setCourse(course);

    course.addReview(badReview);
    badReview.setCourse(course);

    em.persist(goodReview);
    em.persist(badReview);
    }
  2. @jahe jahe revised this gist Jun 12, 2018. 1 changed file with 12 additions and 1 deletion.
    13 changes: 12 additions & 1 deletion jpa-cheatsheet.java
    Original file line number Diff line number Diff line change
    @@ -106,6 +106,9 @@ public class Match {
    * Native Query - Plain SQL statements

    // Initialize DB schema in a Spring Boot App
    resources/schema.sql

    // Populate DB with data in a Spring Boot App
    resources/data.sql

    // Generic Rowmapper that maps all the columns to a Java Pojo
    @@ -376,4 +379,12 @@ public class Passport {
    @OneToOne(fetch=FetchType.LAZY, mappedBy="passport")
    private Student student;

    }
    }

    // Hibernate tries to make the SQL statements as late as possible
    // In this case 1 x INSERT statement is being fired
    @Transactional
    public void createPerson() {
    em.persist(person1); // here the person gets its ID from the DB sequence, but the INSERT statement fires at the end of the transactional method
    person1.setName("Hans");
    } // here does the INSERT happen and after that the transaction COMMIT
  3. @jahe jahe revised this gist Jun 3, 2018. 1 changed file with 43 additions and 1 deletion.
    44 changes: 43 additions & 1 deletion jpa-cheatsheet.java
    Original file line number Diff line number Diff line change
    @@ -334,4 +334,46 @@ public void foo() {

    // Use NativeQuery for mass updates
    Query nativeQuery = em.createNativeQuery("UPDATE person set last_updated_date=sysdate()");
    int rowsAffected = nativeQuery.executeUpdate();
    int rowsAffected = nativeQuery.executeUpdate();

    // Simple OneToOne relationship with one entity owning the relationship
    //
    // Fetch type of a @OneToOne relationship is "Eager" by default
    // This means that the passwort table will be joined in the select statement to find the student
    @Entity
    public class Student {

    @OneToOne
    private Passport passport;

    }
    // -> SELECT * FROM student ... LEFT OUTER JOIN passport ON ...

    // Set Fetch type to lazy so that the passport is only selected when it is needed
    @Entity
    public class Student {

    @OneToOne(fetch=FetchType.LAZY)
    private Passport passport;

    }

    Student student = em.find(Student.class, 1234); // -> SELECT * FROM student WHERE id=1234
    String passportNumber = student.getPassport().getNumber(); // -> SELECT * FROM passport WHERE id=5678

    // As soon as you introduce @Transactional a PersistenceContext will be created
    // The PersistenceContext is a place where every Entity is being stored
    // We interact with the PersistenceContext via an EntityManager (It is the interface to the PersistenceContext)
    // The PersistenceContext is created in the start of a transaction and killed when the transaction is ended
    // When there is no transaction, each method call to the EntityManager acts as an own transaction -> This is often the cause for a LazyInitializationException

    Hibernate "Session" == Persistence Context

    // Add mappedBy to the non-owning side of the relationship to get a biderectional navigation
    @Entity
    public class Passport {

    @OneToOne(fetch=FetchType.LAZY, mappedBy="passport")
    private Student student;

    }
  4. @jahe jahe revised this gist May 29, 2018. 1 changed file with 5 additions and 1 deletion.
    6 changes: 5 additions & 1 deletion jpa-cheatsheet.java
    Original file line number Diff line number Diff line change
    @@ -311,10 +311,14 @@ public void foo() {
    private LocalDateTime lastUpdatedDate;

    // Use NativeQuery to write plain SQL that is being executed directly
    //
    // Usecases for NativeQueries:
    // * Performance tuning
    // * DBMC specific features
    // * Mass updates (JPA can only select a row and then update that row)
    //
    // NativeQueries doesn't use the PersistenceContext
    // When you have some of the Entities that are being updated by a NativeQuery in your PersistenceContext you have to make sure to refresh() them.
    Query nativeQuery = em.createNativeQuery("SELECT * FROM person", Person.class);
    List<Person> persons = nativeQuery.getResultList();

    @@ -330,4 +334,4 @@ public void foo() {

    // Use NativeQuery for mass updates
    Query nativeQuery = em.createNativeQuery("UPDATE person set last_updated_date=sysdate()");
    int rowsAffected = nativeQuery.executeUpdate();
    int rowsAffected = nativeQuery.executeUpdate();
  5. @jahe jahe revised this gist May 29, 2018. 1 changed file with 27 additions and 5 deletions.
    32 changes: 27 additions & 5 deletions jpa-cheatsheet.java
    Original file line number Diff line number Diff line change
    @@ -149,6 +149,10 @@ public Person findById(int id) {
    // Pretty print the SQL printed on the console
    spring.jpa.properties.hibernate.format_sql=true

    // Show SQL statistics of JPA / Hibernate (e.g. how long did a query take)
    spring.jpa.properties.hibernate.generate_statistics=true
    logging.level.org.hibernate.stat=debug

    // Find a JPA entity with EntityManager
    Person person = entityManager.find(Person.class, id)

    @@ -184,10 +188,6 @@ public class Person {
    TypedQuery<Person> typedQuery = entityManager.createQuery("select p from Person p", Person.class);
    List<Person> persons = typedQuery.getResultList();

    // Show SQL statistics of JPA / Hibernate (e.g. how long did a query take)
    spring.jpa.properties.hibernate.generate_statistics=true
    logging.level.org.hibernate.stat=debug

    // Reset In-Memory DB after a test method that changes the state of the DB
    @Test
    @DirtiesContext
    @@ -308,4 +308,26 @@ public void foo() {

    // Automatically insert a timestamp when an entity was updated (Hibernate specific)
    @UpdateTimestamp
    private LocalDateTime lastUpdatedDate;
    private LocalDateTime lastUpdatedDate;

    // Use NativeQuery to write plain SQL that is being executed directly
    // Usecases for NativeQueries:
    // * Performance tuning
    // * DBMC specific features
    // * Mass updates (JPA can only select a row and then update that row)
    Query nativeQuery = em.createNativeQuery("SELECT * FROM person", Person.class);
    List<Person> persons = nativeQuery.getResultList();

    // Use NativeQuery with positional parameters
    Query nativeQuery = em.createNativeQuery("SELECT * FROM person WHERE id = ?", Person.class);
    nativeQuery.setParameter(1, 1234);
    List<Person> persons = nativeQuery.getResultList();

    // Use NativeQuery with named parameters
    Query nativeQuery = em.createNativeQuery("SELECT * FROM person WHERE id = :id", Person.class);
    nativeQuery.setParameter("id", 1234);
    List<Person> persons = nativeQuery.getResultList();

    // Use NativeQuery for mass updates
    Query nativeQuery = em.createNativeQuery("UPDATE person set last_updated_date=sysdate()");
    int rowsAffected = nativeQuery.executeUpdate();
  6. @jahe jahe revised this gist May 29, 2018. 1 changed file with 36 additions and 1 deletion.
    37 changes: 36 additions & 1 deletion jpa-cheatsheet.java
    Original file line number Diff line number Diff line change
    @@ -168,6 +168,22 @@ public class Person {
    ...
    }

    // Define multiple named queries on an entity
    @Entity
    @NamedQueries(
    value={
    @NamedQuery(name="find_all_persons", query="select p from Person p"),
    @NamedQuery(name="find_all_persons_with_a", query="select p from Person p where name like 'a%'")
    }
    )
    public class Person {
    ...
    }

    // Query the DB with a JPQL query
    TypedQuery<Person> typedQuery = entityManager.createQuery("select p from Person p", Person.class);
    List<Person> persons = typedQuery.getResultList();

    // Show SQL statistics of JPA / Hibernate (e.g. how long did a query take)
    spring.jpa.properties.hibernate.generate_statistics=true
    logging.level.org.hibernate.stat=debug
    @@ -273,4 +289,23 @@ public void foo() {

    em.refresh(person);
    em.flush();
    }
    }

    // Specify column properties
    @Column(
    name="fullname", // Name of the table column - default: fieldname
    nullable=false, // Is the column nullable - default: true
    unique=true, // Is the value of this column unique across the table - default: false
    insertable=false, // Should this field be included in an INSERT command - default: true
    updateable=false, // Should this field be included in an UPDATE command - default: true
    length=20 // Maximum number of chars (only relevant to string fields) - default: 255
    )
    private String name;

    // Automatically insert a timestamp when an entity was created (Hibernate specific)
    @CreationTimestamp
    private LocalDateTime createdDate;

    // Automatically insert a timestamp when an entity was updated (Hibernate specific)
    @UpdateTimestamp
    private LocalDateTime lastUpdatedDate;
  7. @jahe jahe revised this gist May 28, 2018. No changes.
  8. @jahe jahe revised this gist May 26, 2018. 1 changed file with 104 additions and 1 deletion.
    105 changes: 104 additions & 1 deletion jpa-cheatsheet.java
    Original file line number Diff line number Diff line change
    @@ -170,4 +170,107 @@ public class Person {

    // Show SQL statistics of JPA / Hibernate (e.g. how long did a query take)
    spring.jpa.properties.hibernate.generate_statistics=true
    logging.level.org.hibernate.stat=debug
    logging.level.org.hibernate.stat=debug

    // Reset In-Memory DB after a test method that changes the state of the DB
    @Test
    @DirtiesContext
    public void deleteByIdBasic() {
    repository.deleteById(12);
    assertNull(repository.findById(12));
    }

    // Save an Entity with JPA
    public Person save(Person person) {
    if (person.getId() == null) {
    // insert
    em.persist(person);
    } else {
    // update
    em.merge(person);
    }

    return person;
    }

    // In a @Transactional method every set-method results in an update of the row regardless of calling em.merge() on it
    // The EntityManager keeps track of all the changes that are being made to an Entity
    // In this case 1 x INSERT and 1 x UPDATE statement are being fired
    @Transactional
    public void foo() {
    Person person = new Person("Hansen");
    em.persist(person);
    person.setName("Meier");
    }

    // Send out changes to the DB within a Transaction
    // In this case 1 x INSERT and 2 x UPDATE statements are being fired
    @Transactional
    public void foo() {
    Person person = new Person("Hansen");
    em.persist(person);
    em.flush();

    person.setName("Meier");
    em.flush();

    person.setName("Raab");
    em.flush();
    }

    // Prevent changes made to an Entity from going into the DB within an Transaction
    // With em.detach(entity) the changes to this entity are no longer being tracked by the EntityManager
    // In this case 1 x INSERT and 1 x Update statements are being fired
    @Transactional
    public void foo() {
    Person person = new Person("Hansen");
    em.persist(person);
    em.flush();

    person.setName("Meier");
    em.flush();

    em.detach(person);

    person.setName("Raab");
    }

    // Prevent changes made to all Entites from going into the DB within a Transaction
    // With em.clear() the changes to all entites are no longer being tracked by the EntityManager
    // In this case 2 x INSERT and no other statements are being fired
    @Transactional
    public void foo() {
    Person person = new Person("Hansen");
    em.persist(person);

    Person person2 = new Person("Meier");
    em.persist(person2);

    em.flush();
    em.clear();

    person.setName("Paulsen");
    em.flush();

    person2.setName("Raab");
    em.flush();
    }

    // Get a fresh copy of an Entity from the DB within a Transaction
    // All changes that are not being flushed are now lost
    @Transactional
    public void foo() {
    Person person = new Person("Hansen");
    em.persist(person);

    Person person2 = new Person("Meier");
    em.persist(person2);

    em.flush();

    person.setName("Paulsen");
    person2.setName("Raab");

    em.refresh(person);
    em.flush();
    }
  9. @jahe jahe revised this gist May 26, 2018. 1 changed file with 33 additions and 1 deletion.
    34 changes: 33 additions & 1 deletion jpa-cheatsheet.java
    Original file line number Diff line number Diff line change
    @@ -138,4 +138,36 @@ public Person findById(int id) {
    }

    // Activate H2 Web-Console
    spring.h2.console.enabled=true
    spring.h2.console.enabled=true

    // Show SQL Statements made with JPA / Hibernate
    spring.jpa.show-sql=true

    // Show the parameters of the statements
    logging.level.org.hibernate.type=trace

    // Pretty print the SQL printed on the console
    spring.jpa.properties.hibernate.format_sql=true

    // Find a JPA entity with EntityManager
    Person person = entityManager.find(Person.class, id)

    // Insert or Update a JPA entity with EntityManager
    Person newPerson = entityManager.merge(person);

    // Delete a JPA entity with EntityManager
    entityManager.remove(person);

    // Find all entities with EntityManager (using JPQL -> It uses entites in its query, not table names)
    TypedQuery<Person> namedQuery = entityManager.createNamedQuery("find_all_persons", Person.class);
    List<Person> persons = namedQuery.getResultList();

    @Entity
    @NamedQuery(name="find_all_persons", query="select p from Person p")
    public class Person {
    ...
    }

    // Show SQL statistics of JPA / Hibernate (e.g. how long did a query take)
    spring.jpa.properties.hibernate.generate_statistics=true
    logging.level.org.hibernate.stat=debug
  10. @jahe jahe revised this gist May 26, 2018. No changes.
  11. @jahe jahe revised this gist May 26, 2018. 1 changed file with 30 additions and 1 deletion.
    31 changes: 30 additions & 1 deletion jpa-cheatsheet.java
    Original file line number Diff line number Diff line change
    @@ -109,4 +109,33 @@ public class Match {
    resources/data.sql

    // Generic Rowmapper that maps all the columns to a Java Pojo
    List<Person> persons = jdbcTemplate.query("select * from person", new BeanPropertyRowMapper<Person>(Person.class))
    List<Person> persons = jdbcTemplate.query("select * from person", new BeanPropertyRowMapper<Person>(Person.class));

    // Select a single object with JdbcTemplate
    Person person = jdbcTemplate.queryForObject("select * from person where id=?", new Object[] { 12 }, new BeanPropertyRowMapper<Person>(Person.class));

    // Delete a single object with JdbcTemplate
    int rowsAffected = jdbcTemplate.update("delete * from person where id=?", new Object[] { 12 });

    // Insert a single object with JdbcTemplate (java.sql.Timestamp)
    int rowsAffected = jdbcTemplate.update("insert into person (id, name, birth_date) values (?, ?)", new Object[] { 12, "Meier", new Timestamp(new Date().getTime()) });

    // Update a single object with JdbcTemplate
    int rowsAffected = jdbcTemplate.update("update person set name=? where id=?", new Object[] { "Petersen", 12 });

    EntityManger = Interface to the PersistenceContext

    // Enable Transaction Management on each method
    @Transactional // javax.persistence.Transactional
    public class PersonJpaRepository {

    @PersistenceContext
    EntityManager entitiyManager;

    public Person findById(int id) {
    return entityManager.find(Person.class, id);
    }
    }

    // Activate H2 Web-Console
    spring.h2.console.enabled=true
  12. @jahe jahe revised this gist May 25, 2018. 1 changed file with 13 additions and 1 deletion.
    14 changes: 13 additions & 1 deletion jpa-cheatsheet.java
    Original file line number Diff line number Diff line change
    @@ -97,4 +97,16 @@ public class Match {
    // Several ways to delete records in the db
    // http://www.objectdb.com/java/jpa/persistence/delete#Orphan_Removal

    TODO: how to implemwnt equals and hashcode: https://vladmihalcea.com/2016/10/20/the-best-way-to-implement-equals-hashcode-and-tostring-with-jpa-and-hibernate/
    TODO: how to implemwnt equals and hashcode: https://vladmihalcea.com/2016/10/20/the-best-way-to-implement-equals-hashcode-and-tostring-with-jpa-and-hibernate/

    Query Data
    * JDBC - Plain SQL statements
    * JPQL - Query language based on Enitity names (not on table names)
    * Criteria Query - Build a query with a Java based API
    * Native Query - Plain SQL statements

    // Initialize DB schema in a Spring Boot App
    resources/data.sql

    // Generic Rowmapper that maps all the columns to a Java Pojo
    List<Person> persons = jdbcTemplate.query("select * from person", new BeanPropertyRowMapper<Person>(Person.class))
  13. @jahe jahe revised this gist Jun 24, 2017. 1 changed file with 3 additions and 1 deletion.
    4 changes: 3 additions & 1 deletion jpa-cheatsheet.java
    Original file line number Diff line number Diff line change
    @@ -95,4 +95,6 @@ public class Match {
    // CascadeType.ALL contains PERSIST, REMOVE, REFRESH, MERGE, DETACH

    // Several ways to delete records in the db
    // http://www.objectdb.com/java/jpa/persistence/delete#Orphan_Removal
    // http://www.objectdb.com/java/jpa/persistence/delete#Orphan_Removal

    TODO: how to implemwnt equals and hashcode: https://vladmihalcea.com/2016/10/20/the-best-way-to-implement-equals-hashcode-and-tostring-with-jpa-and-hibernate/
  14. @jahe jahe revised this gist Jun 23, 2017. 1 changed file with 3 additions and 1 deletion.
    4 changes: 3 additions & 1 deletion jpa-cheatsheet.java
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,4 @@
    /*
    JPA (Java Persistence API)
    Transaction Management with an Entity-Mananger:
    @@ -44,6 +45,7 @@
    Lazy Loading funktioniert
    Detached - Lazy Loading muss nicht zwangsweise funktionieren
    */

    // Use a database sequence on id field
    @Entity
    @@ -93,4 +95,4 @@ public class Match {
    // CascadeType.ALL contains PERSIST, REMOVE, REFRESH, MERGE, DETACH

    // Several ways to delete records in the db
    http://www.objectdb.com/java/jpa/persistence/delete#Orphan_Removal
    // http://www.objectdb.com/java/jpa/persistence/delete#Orphan_Removal
  15. @jahe jahe revised this gist Jun 23, 2017. 1 changed file with 41 additions and 12 deletions.
    53 changes: 41 additions & 12 deletions jpa-cheatsheet.java
    Original file line number Diff line number Diff line change
    @@ -49,19 +49,48 @@
    @Entity
    @Table(name = "ADDRESS")
    public class Address {
    @Id
    @SequenceGenerator(
    name = "address_seq",
    sequenceName = "address_seq",
    allocationSize = 1
    )
    @GeneratedValue(
    strategy = GenerationType.SEQUENCE,
    generator = "address_seq"
    )
    private long id;
    @Id
    @SequenceGenerator(
    name = "address_seq",
    sequenceName = "address_seq",
    allocationSize = 1
    )
    @GeneratedValue(
    strategy = GenerationType.SEQUENCE,
    generator = "address_seq"
    )
    private long id;
    }

    // Delete dependent children, when the parent is going to be deleted (child-entites are orphans (=Waisen) then)
    @OneToMany(mappedBy="foo", orphanRemoval=true)
    private List<Bikes> bikes;
    private List<Bikes> bikes;

    // Model a m:n relationship where the corresponding relationship record would be deleted when a entity record is deleted
    @Entity
    public class Team {
    @ManyToMany(cascade = { CascadeType.MERGE, CascadeType.PERSIST }, mappedBy="teams")
    private List<Match> matches;
    }

    @Entity
    public class Match {
    @ManyToMany(cascade = { CascadeType.MERGE, CascadeType.PERSIST })
    @JoinTable(
    name="MATCH_TEAM",
    joinColumns={@JoinColumn(name="MATCH_ID", referencedColumnName="ID")},
    inverseJoinColumns={@JoinColumn(name="TEAM_ID", referencedColumnName="ID")}
    )
    private List<Team> teams;
    }

    // Remove Child Records, when the child record is set to null in the parents collection of children
    // by setting "orphanRemoval = true"
    @OneToOne(cascade = CascadeType.ALL, fetch=FetchType.LAZY, orphanRemoval = true)
    private AvatarImage avatarImage;

    // Mark children elements as "CascadeType.ALL" to refresh/delete/... them if the parent refreshes/deletes/...
    // CascadeType.ALL contains PERSIST, REMOVE, REFRESH, MERGE, DETACH

    // Several ways to delete records in the db
    http://www.objectdb.com/java/jpa/persistence/delete#Orphan_Removal
  16. @jahe jahe revised this gist Jun 23, 2017. 1 changed file with 5 additions and 1 deletion.
    6 changes: 5 additions & 1 deletion jpa-cheatsheet.java
    Original file line number Diff line number Diff line change
    @@ -60,4 +60,8 @@ public class Address {
    generator = "address_seq"
    )
    private long id;
    }
    }

    // Delete dependent children, when the parent is going to be deleted (child-entites are orphans (=Waisen) then)
    @OneToMany(mappedBy="foo", orphanRemoval=true)
    private List<Bikes> bikes;
  17. @jahe jahe renamed this gist May 24, 2017. 1 changed file with 18 additions and 1 deletion.
    19 changes: 18 additions & 1 deletion jpa-notes.txt → jpa-cheatsheet.java
    Original file line number Diff line number Diff line change
    @@ -43,4 +43,21 @@
    Beim nächsten Transaktions-Commit werden nur die Änderungen in die DB geschrieben.

    Lazy Loading funktioniert
    Detached - Lazy Loading muss nicht zwangsweise funktionieren
    Detached - Lazy Loading muss nicht zwangsweise funktionieren

    // Use a database sequence on id field
    @Entity
    @Table(name = "ADDRESS")
    public class Address {
    @Id
    @SequenceGenerator(
    name = "address_seq",
    sequenceName = "address_seq",
    allocationSize = 1
    )
    @GeneratedValue(
    strategy = GenerationType.SEQUENCE,
    generator = "address_seq"
    )
    private long id;
    }
  18. @jahe jahe created this gist May 12, 2017.
    46 changes: 46 additions & 0 deletions jpa-notes.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,46 @@
    JPA (Java Persistence API)

    Transaction Management with an Entity-Mananger:
    ---
    entityManager.getTransaction().begin();
    entityManager.persist(<some-entity>);
    entityManager.getTransaction().commit();
    entityManager.clear();

    SomeEntity entity = entityManager.find(SomeEntity.class, 1);
    ---

    @OneToOne's fetch type is EAGER by default
    Lists + Sets fetch type is LAZY by default

    Two types of Lazy Loading implementations
    1. Proxying the object (default in Hibernate) by creating a Subclass of that object at runtime and overwrite the get methods.
    This is done by the JavaAssist lib.
    2. ByteCode Enhancement (default in EclipseLink): Add special logic to the get methods inside the Java Bytecode

    LazyInitializationExcepiton:

    Entity Lifecycle

    New ---> em.persist ---> Managed
    New ---> em.merge ---> Managed

    Managed ---> em.remove ---> Removed

    Managed ---> em.find ---> Managed
    Managed ---> query.getResultList ---> Managed
    Managed ---> query.getSingleResult ---> Managed

    Managed ---> em.detach ---> Detached
    Managed ---> em.close ---> Detached
    Managed ---> em.clear ---> Detached

    Detached ---> em.merge ---> Managed

    Ein neu angelegtes Entity Object ist im Zustand "New".
    Managed - Es gibt einen Entity-Manager, der für dieses Objekt verantwortlich ist:
    Vorteile: - Es werden automatisch Änderungen getrackt.
    Beim nächsten Transaktions-Commit werden nur die Änderungen in die DB geschrieben.

    Lazy Loading funktioniert
    Detached - Lazy Loading muss nicht zwangsweise funktionieren