Jpa (Java Persistence Api) Cheat Sheet: Transaction Management With Entitymanager
Jpa (Java Persistence Api) Cheat Sheet: Transaction Management With Entitymanager
entityManager.getTransaction().begin();
Person p = new Person();
p.setLastName("Kondayil");
p.setFirstName("Vinod");
entityManager.persist(p);
entityManager.getTransaction().commit();
Eager vs Lazy
@OneToOne and @ManyToOne fetch type is EAGER by default @OneToMany and
ManyToMany fetch type is LAZY by deafult
1. New: When an entity object is initially created its state is New. In this state the
object is not yet associated with an EntityManager and has no representation
in the database.
2. Managed: An entity object becomes Managed when it is persisted to the
database via an EntityManager’s persist method. Entity objects retrieved from
the database by an EntityManager are also in the Managed state.
3. Removed: A managed entity object can also be retrieved from the database
and marked for deletion, using the EntityManager’s remove() method within
an active transaction. The entity object changes its state from Managed to
Removed, and is physically deleted from the database during commit.
4. Detached: represents entity objects that have been disconnected from the
EntityManager.
Mappings
Delete dependent children, when the parent is deleted Note: Add mappedBy to the
non-owning side of the relationship to get a biderectional navigation
@OneToMany(mappedBy="blogpost", orphanRemoval=true)
private List<Comment> comments;
Setting fetch time to lazy so that the passport is only selected when it is needed
@Entity
public class Student {
@OneToOne(fetch=FetchType.LAZY)
private Passport passport;
}
Initialize DB
Initialize schema in a Spring Boot App src/main/resources/schema.sql
2. JPQL
@Entity
@NamedQuery(name="find_all_courses", query="select c from Course c")
public class Course {
...
}
Defining multiple named queries
@Entity
@NamedQueries(
value={
@NamedQuery(name="find_all_courses", query="select c from Course c"),
@NamedQuery(name="find_all_courses_starting_with_a", query="select c from
Course c where name like 'a%'")
}
)
public class Course {
...
}
@Transactional
public void addCourse() {
Course course = new Course("JPA Hibernate");
em.persist(course);
course.setName("JPA and Hibernate");
}//here at this point the INSERT happens to the DB and after that the transaction
commits
Using flush() you can send out changes to the DB within a Transaction
@Transactional
public void foo() {
Course course = new Course("JPA Hibernate");
em.persist(course);
em.flush();
@Transactional
public void foo() {
Course course = new Course("JPA Hibernate");
em.persist(course);
em.flush();
em.detach(course); //changes to the course entity will not be tracked from here
@Transactional
public void foo() {
Course course = new Course("JPA");
em.persist(course);
em.flush();
em.clear(); //from this point onwards no changes to the course and course2 will
be reflected
course.setName("JPA Hibernate");
em.flush();
@Transactional
public void foo() {
Course course = new Course("JPA");
em.persist(course);
em.flush();
course.setName("Hibernate");
Embedded Objects
We can declare an embedded component inside an entity. Using embedded objects
student table will be populated with the columns of the address also.
@Embeddable
public class Address {
String line1;
String line2;
String city;
String district;
String state;
String pincode;
}
@Entity
public class Student{
...
@Embedded
private Address address
}
@Column attributes
@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
)
@CreationTimestamp
private LocalDateTime createdDate;
Automatically insert a timestamp when an entity was updated (Hibernate specific)
@UpdateTimestamp
private LocalDateTime lastUpdatedDate;
1. SINGLE_TABLE : we will get a single table for all the above three entities with
a DTYPE column (distinguisher type). Problem with this strategy is that data
integrity is not good. Because columns would have to be nullable.
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
public abstract class Employee{
...
}
----------------------------------------------------
DTYPE | ID | NAME | HOURLY_WAGE | SALARY
----------------------------------------------------
FullTimeEmployee | 1 | ABC | NULL | 1000
----------------------------------------------------
PartTimeEmployee | 2 | XYZ | 25 | NULL
----------------------------------------------------
To change the DTYPE
@DiscriminatorColumn(name="EmployeeType")
FullTimeEmployee
----------------------
ID | NAME | SALARY
----------------------
1 | ABC | 1000
----------------------
PartTimeEmployee
-------------------------
ID | NAME | HOURLY_WAGE
-------------------------
1 | XYZ | 25
-------------------------
3. JOINED: Fields specific to a subclass are mapped to a separate table. The
common fields of the employee class will be in another table. To retrieve full
employees we need to do the join of three tables. This is the recommended
structure. Demerit: Joining the table to retrieve the data.
Employee
------------
ID | NAME
------------
1 | ABC
------------
2 | XYZ
------------
FullTimeEmployee
--------------------
ID | SALARY
--------------------
1 | 1000
--------------------
PartTimeEmployee
--------------------
ID | HOURLY_WAGE
--------------------
2 | 25
--------------------
@MappedSuperClass
public abstract class Employee{
...
}
FullTimeEmployee
----------------------
ID | NAME | SALARY
----------------------
1 | ABC | 1000
----------------------
PartTimeEmployee
-------------------------
ID | NAME | HOURLY_WAGE
-------------------------
1 | XYZ | 25
-------------------------