Hibernate-2

 count from....Hibernate-1

JPAH-JPA Hibernate

NH-Native Hibernate

4.Persistence Context & Persistence State

  Persistence State:Forms of entity which will navigate the hibernate.

1.Transient State
New records are stored as transient state

2.Detached State
If there is any content in the detached state it must be in the DB.
merge detached entity
step 1-create a clone from detached entity,but dont know the memory location of that entity.
step2-using select query check weather availability  of the record.
step 3-merge with the persistence context's entity. 

3.Managed State
If the entity is in persistence context will called as the manage state,In this state dirty checking feature activated in the entity object.If we want to update any thing in the db we want to put that in to the persistence context.All the content in the persistence context will flush(),after the commit 

session.contains(entity name-->Check whether entity is in the persistence context)

After fetched(get or find) an entity which is in the persistence context.If we request that entity to another operation before commit,that entity put to the first level cache give it   & it will course to the increase the Speed. 

All persistent objects are monitored by hibernate.It detects which objects have been modified and then calls update statements on all updated objects. the process of updating the changed object is called automatic dirty checking.

4.Removed State
Simply we can delete entity which is in the manage state, using delete() or remove() function.

But we can delete the entity in the detached state also using delete() method in NH,But cant use the remove() method in JPAH.If we use remove() statement it will show a  error.----------(x)

If we do not want (x) feature we cant disable that in JPAH but we can disable that in NH.

refresh()
Refresh all changes we did in manage state(get regards record in database);fetch that object from DB.
If we refresh detach state object,it will move to persistance contex. 

We can also refresh() the detached object but only the NH not for the JPAH.------------(y)
But,if we perform that in the JPAH it identify as Hibernate error.
 If we do not want (y) functionality we can  disable (y) functionality . add below configuration to the .properties file .After the disable that functionality we can see the exception in the console when use JPAH

hibernate.allow_refresh_detached_entity=false

Lazy fetching & Egger Fetching in Hibernate

Lazy fetching:(Must request for the data,without requesting can't get he data):   load(NH),get reference(JPAH) 

Eager fetching:(Quickly give the data) get(NH),find(JPAH)

When request data using id(Primary key) in lazy fetching,it returns the fake record called proxy(But it represent the real record).
But if we request the value from the proxy,then it returns the real value.But if there is no any such record regards to the proxy hibernate gives the exception which indicate bug in hibernate.

Update vs SaveOrUpdate
There is no alternative to update & save or update in JPAH. 
Update
Reatch the detached object.
Eg:-
//this object is already in the DB-----a
new Employee(1, "Jhone", "Washington DC", new BigDecimal(4500), Date.valueOf("2020-05-09"));

//there is a colomn id=1 recored in the db(a),then new id=1 will be detached 
Employee mike= new Employee(1, "Mike", "Texas", new BigDecimal(1500), Date.valueOf("2020-08-14"));

//new object will be mike object,which save in the db will be mike
session.update(mike);

if there is object in the persistance context as same as the detached object(@id equal,other feild can be deffer),It will be exception.
Eg:-
(t-1)execution
//there object is @Id1 already in the DB
session.save(new Employee(1, "Jhone", "Washington DC", new BigDecimal(4500), Date.valueOf("2020-05-09")));

(t)execution
//there is a column id=1 record in the db,then new id=1 will be detached
Employee mike= new Employee(1, "Mike", "Texas", new BigDecimal(1500), Date.valueOf ("2020-08-14"));

//now @id 1 object in the persistence context.
session.get(Employee.class,1);

//exception:there is already @id1(Jhone) in the Persistence context,but try to update another @Id1
//A different object with the same identifier value was already associated with the session
session.update(mike);

Whether update will happen or not update query will execute in this scenario. 
In the NH if we add the object to Manage state it will automatically update to the database,But If we want to update that forcefully we can use,update()

merge vs update?
Deference between update & merge?
(t-1)
There is a record called x with  primery key=1.

(t)
If there is object called y in the detached state same primary key(1).
session.get(ClassName.class,1)//get that x object to the manage state.

(t+1) case 1
session.merge(y)
//succeed replace object y

(t+1) case 2
session.update(y)
//fail exception

saveOrUpdate

If there is a object in the transient satate,saveOrUpdate keyword  work as save keyword(persist/merge).
If there is a object in the detached state  ,saveOrUpadate keyword work as NH update keyword. 

Process:-First execute SELECT statement to cheack wether record will exist or not,if record exist perform as the update() keyword,else perform as the transient keyword.

defferance between update() & savOrUpdate()
update()-without considering chnges will happen or not update statement will execute.
saveOrUpdate-Only update query execute changes happen in object

5.Object Relational Mapping with DB Relationships

There are 3 methods of mapping relationship between entity.
    1. Selection of one entity to exchange pk to fk or DBMS  rules
    2.Using @JoinTable
    3.Decomposing  

(5.1)Uni-Directional Relationship
If we can get inverse end data using owner end will be called as uni-directional relationship
(A) 1-1 Relationship
1. Selection of one entity to exchange pk to fk or DBMS  rules


Employee.java
package lk.myorg.hibernate.entity;

import lombok.*;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import java.math.BigDecimal;

@ToString
@AllArgsConstructor
@Getter
@Setter
@NoArgsConstructor
@Entity
public class Employee {
    @Id
    @Column(name="emp_id")//column name
    private int id;//atrtibute id
    private  String name;
    private String address;
    private BigDecimal salary;
}

Spouse.java
package lk.myorg.hibernate.entity;

import lombok.*;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;

@ToString
@AllArgsConstructor
@Getter
@Setter
@NoArgsConstructor
@Entity
public class Spouse {
    @Id
    private int id;
    private  String name;
    @OneToOne
//cant store nul values in total participation.But can be stor null values in prticial participations(If 1-1 partial,can store null values )
    @JoinColumn(name="employee_id",referencedColumnName ="emp_id",nullable = false)
    private  Employee employeeId;
}

2.Using @JoinTable
Employee2.java
Employee2
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Entity
public class Employee2 {
    @Id
    private int id;
    private String name;
    @Enumerated(EnumType.STRING)
    private Gender gender;
}

Phone.java
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString
@Entity
public class Phone {
    @Id
    private int id;
    private String number;
    private String model;

    @OneToOne
//    @JoinTable(name = "EmployeePhone",
//    joinColumns = @JoinColumn(name="phone_id",referencedColumnName = "id"),
//    inverseJoinColumns = @JoinColumn(name="employee_id",referencedColumnName = "id"),
//    uniqueConstraints = @UniqueConstraint(columnNames = "employee_id"))

    @JoinTable(name = "EmployeePhone",
            joinColumns = @JoinColumn(name="phone_id",referencedColumnName = "id"),
            inverseJoinColumns = @JoinColumn(name="employee_id",referencedColumnName = "id", unique = true))
    private Employee2 employee;

    public Phone(int id, String number, String model){
        this.id = id;
        this.number = number;
        this.model = model;
    }
}

3.Decomposing  

Employee3.java
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString
@Entity
public class Employee3 {
    @Id
    private int id;
    private String name;
}

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString
@Entity
public class Car {
    @Id
    private int id;
    private String name;
}

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString
@Embeddable
public class EmployeeCarPK implements Serializable {
    @Column(name = "emp_id", unique = true)
    private int empId;
    @Column(name = "car_id",unique = true)
    private int carId;
}

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString
@Entity
public class EmployeeCar {
    @EmbeddedId
    private EmployeeCarPK employeeCarPK;
    private Date date;
    @OneToOne
    @JoinColumn(name = "emp_id", referencedColumnName = "id", insertable = false, updatable = false)
    private Employee3 employee3;
    @OneToOne
    @JoinColumn(name = "car_id", referencedColumnName = "id", insertable = false, updatable = false)
    private Car car;

    public EmployeeCar(EmployeeCarPK employeeCarPK, Date date) {
        this.employeeCarPK = employeeCarPK;
        this.date = date;
    }

    public EmployeeCar(int empId, int carId, Date date) {
        this.employeeCarPK = new EmployeeCarPK(empId, carId);
        this.date = date;
    }
}

    3.Decomposing 
 
Customer3.java
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Getter
@Setter
@Entity
public class Customer3 {
    @Id
    private int id;
    private String name;
}

Order3
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Getter
@Setter
@Entity
public class Order3 {
    @Id
    private int id;
    private Date date;
}

CustomerOrderPK.java
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Getter
@Setter
public class CustomerOrderPK implements Serializable {
    private int customerId;
    private int orderId;
}

CustomerOrder.java
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Getter
@Setter
@Entity
@IdClass(CustomerOrderPK.class)
public class CustomerOrder {
    @Id
    @Column(name = "customer_id")
    private int customerId;
    @Id
    @Column(name = "order_id", unique = true)
    private int orderId;
    @ManyToOne
    @JoinColumn(name = "customer_id", referencedColumnName = "id", insertable = false, updatable = false)
    private Customer3 customer;
    @OneToOne
    @JoinColumn(name = "order_id", referencedColumnName = "id", insertable = false, updatable = false)
    private Order3 order;

    public CustomerOrder(int customerId, int orderId) {
        this.customerId = customerId;
        this.orderId = orderId;
    }

    public CustomerOrder(CustomerOrderPK customerOrderPK) {
        this.customerId = customerOrderPK.getCustomerId();
        this.orderId = customerOrderPK.getOrderId();
    }

    public CustomerOrderPK getCustomerOrderPK() {
        return new CustomerOrderPK(customerId, orderId);
    }

    public void setCustomerOrderPK(CustomerOrderPK customerOrderPK) {
        this.customerId = customerOrderPK.getCustomerId();
        this.orderId = customerOrderPK.getOrderId();
    }

}


(B)1-M Relationship
1. Selection of one entity to exchange pk to fk or DBMS  rules


Customer.java
package lk.myorg.hibernate.entity;


import lombok.AllArgsConstructor;
import lombok.Data;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;

@AllArgsConstructor
@Data
@Entity
public class Customer {
    @Id
    private int id;
    private String name;
    private String Contact;
}


Order.java
package lk.myorg.hibernate.entity;

import lombok.AllArgsConstructor;
import lombok.Data;

import javax.persistence.*;
import java.sql.Date;

@AllArgsConstructor
@Data
@Entity
@Table(name="`Order`")

public class Order {
    @Id
    private int id;
    private Date date;
    @ManyToOne
    @JoinColumn(name ="customer_id",referencedColumnName ="id",nullable =false)
    private Customer customerId;

}

   2.Using @JoinTable
Customer2
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString
@Entity
public class Customer2 {
    @Id
    private int id;
    private String name;
    @OneToMany
    @JoinTable(name="CustomerOrder",
    joinColumns = @JoinColumn(name="customer_id",referencedColumnName = "id"),
    inverseJoinColumns = @JoinColumn(name="order_id", referencedColumnName = "id"))
    private List<Order2> ordersList;

    public Customer2(int id, String name) {
        this.id = id;
        this.name = name;
    }
}

Order2
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString
@Entity
public class Order2 {
    @Id
    private int id;
    private Date date;
}



(C) M-M Relationship
2.Using @JoinTable
(Many-Many single only with primary keys)

Gender.java
package lk.myorg.hibernate.entity;

public enum Gender {
    MALE,FEMALE
}

Actor.java
package lk.myorg.hibernate.entity;

import lombok.AllArgsConstructor;
import lombok.Data;

import javax.persistence.*;

@AllArgsConstructor
@Data
@Entity
public class Actor {
    @Id
    private int id;
    private String name;
    @Enumerated(EnumType.STRING)
    private Gender gender;

}

Movie.java
package lk.myorg.hibernate.entity;

import lombok.AllArgsConstructor;
import lombok.Data;

import javax.persistence.*;
import java.util.List;

@AllArgsConstructor
@Data
@Entity
public class Movie {
    @Id
    private int id;
    private String name;
    private int duration;
    @ManyToMany
    @JoinTable(name="Movie_Actor",
            joinColumns =@JoinColumn(name="movie_id",referencedColumnName = "id"),
            inverseJoinColumns =@JoinColumn(name="actor_id",referencedColumnName = "id") )
    private List<Actor> actorList;

    public Movie(int id, String name, int duration) {
        this.id = id;
        this.name = name;
        this.duration = duration;
    }
}
    3.Decomposing  
(Many-Many with extra column)
M:M decompose to 1:M+M:1



Gender.java
package lk.myorg.hibernate.entity;

public enum Gender {
    MALE,FEMALE
}

Actor2.java
package lk.myorg.hibernate.entity;

import lombok.AllArgsConstructor;
import lombok.Data;

import javax.persistence.*;

@AllArgsConstructor
@Data
@Entity
public class Actor2 {
    @Id
    private int id;
    private String name;
    @Enumerated(EnumType.STRING)
    private Gender gender;

}

Movie2.java
package lk.myorg.hibernate.entity;

import lombok.AllArgsConstructor;
import lombok.Data;

import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
@Data
@AllArgsConstructor

public class Movie2 {
    @Id
    private int id;
    private String name;
    private int duration;
}

ActorMoviePK.java
package lk.myorg.hibernate.entity;
import lombok.AllArgsConstructor;
import lombok.Data;

import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.persistence.Entity;
import java.io.Serializable;

@Embeddable
@Entity
@Data
@AllArgsConstructor

public class ActorMoviePK implements Serializable{
    @Column(name = "actor_ID")
    private int actorID;
    @Column(name = "movie_ID")
    private int movieID;
}

ActorMovie.java

package lk.myorg.hibernate.entity;
import lombok.AllArgsConstructor;
import lombok.Data;

import javax.persistence.*;
import java.sql.Date;

@Entity
@Data
@AllArgsConstructor
@Table(name = "Actor_Movie")
public class ActorMovie {

    @EmbeddedId//link @Embeddable from  ActorMoviePK.java
    private ActorMoviePK actorMoviePK;

    @Column(name = "joined_Date")
    private Date joinedDate;

    @ManyToOne
    @JoinColumn(name = "actor_ID" , referencedColumnName = "id",insertable = false,updatable = false)//only read
    private Actor2 actorID;

    @ManyToOne
    @JoinColumn(name = "movie_ID" , referencedColumnName = "id",insertable = false,updatable = false)//only read
    private Movie2 movieID;

    public ActorMovie(int actorID,int movieID, Date date) {
        this.actorMoviePK = new ActorMoviePK(actorID,movieID);
        this.joinedDate = date;
    }

}

AppInizialiser.java
package lk.myorh.hibernate.main;

import lk.myorg.hibernate.entity.*;
import lk.myorg.hibernate.util.HibernateUtil;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;

import java.io.Serializable;
import java.math.BigDecimal;
import java.sql.Date;

public class AppInizialiser {
    public static void main(String[] args) {
        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
        Session session = sessionFactory.openSession();
        Transaction tx = null;
        try {
            tx = session.beginTransaction();
            Actor2 rock = new Actor2(1, "Rock", Gender.MALE);
            Actor2 dep = new Actor2(2, "Jonny dep", Gender.MALE);
            Movie2 ironman = new Movie2(1, "Iron Man", 140);
            ActorMovie actorMovie1 = new ActorMovie(rock.getId(), ironman.getId(), Date.valueOf("2015-08-06"));
            ActorMovie actorMovie2 = new ActorMovie(dep.getId(), ironman.getId(), Date.valueOf("2016-06-06"));

            session.persist(rock);
            session.persist(dep);
            session.persist(ironman);
            session.persist(actorMovie1);
            session.persist(actorMovie2);

            tx.commit();
          } catch (Throwable t) {
            tx.rollback();
            t.printStackTrace();
        }finally {
            session.close();
            sessionFactory.close();
        }
        session.close();
        sessionFactory.close();
    }
}

Tip:-
Primary key cant change using the hibernate.If relay want to change the Pk ,there are 2 method for that.But if you change the primary key It will return runtime time exception.
1.Use native SQL query
2.Delete the row from persistence context & create new record  

**If we cant also to change the part of the partial primary key in manage state.There are 2 cases in changing partial key
    1.changing memory location(Result to runtime time exceptional case)
    2.changing only part of partial key by accessing object.(nothing change but,not an exception)









Comments

Popular posts from this blog

Serialization Using java

Avoid Round-off error in large & Small numbers using BigDecimal Class in Java