Hibernate Bootcamp
Agenda
- Understanding Hibernate
- Setup
- Hibernate xml configurations
- hbm2ddl options
- @Id and @Entity annotations
- CRUD
- Transient, Persistent and Detached states
- Name Annotations
- Generating Primary Key
- Embedded types
- Saving Collections
- Configuring Collections and Adding Keys
Agenda (Cont.)
- One to One Mapping
- One to Many Mapping
- Many to Many Mapping
- Cascading
- Inheritance
What is Hibernate?
- An ORM tool
- Used in the data layer of applications
- Implements JPA
The Problem solved by hibernate
User Class |
---|
Id |
Name |
Address |
Phone |
Date of Birth |
Id | Name | Address | Phone | Date of Birth |
---|---|---|---|---|
The Problem solved by hibernate (Cont.)
- Mapping member variables to column
- Mapping relationships
- Handling data types
- Managing changes to object state
Set up with gradle
apply plugin: 'java'
repositories {
mavenCentral()
}
dependencies {
compile('org.hibernate:hibernate-core:5.2.6.Final')
compile ('mysql:mysql-connector-java:5.1.6')
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!--Database connection settings -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/poc</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password"/>
<!--JDBC connection pool-->
<property name="connection.pool_size">10</property>
<!-- SQL Dialect-->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!--echo all executed SQL-->
<property name="show_sql">true</property>
<!--drop or re-create database schema at startup-->
<property name="hbm2ddl.auto">create</property>
<!--Annotated entity class-->
<mapping class="com.hibernate.demo.Person"/>
</session-factory>
</hibernate-configuration>
hibernate.cfg.xml
hbm2ddl configurations
- update: update the schema.
- create: creates the schema, destroying previous data.
- create-drop: drop the schema when the SessionFactory is closed explicitly, typically when the application is stopped.
- none: Do not do anything.
Special note about update for hbm2ddl auto
-
update won't modify existing table column definitions.
-
update will add a db column that doesn't already exist.
-
update will not delete a db column that is removed/no longer in your entity.
-
update will not modify a db column that has already been created.
@Id and @Entity
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class Person {
@Id
Integer id;
String name;
Integer age;
}
- @Entity : Marks the class as entity.
- @Id : Specifies primary key for the entity.
CRUD (Create)
- Create a session factory
- Create a session from session factory
- Use the session to save model objects
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class Application {
public static void main(String[] args) {
Person person=new Person();
person.setName("Hibernate");
person.setAge(27);
person.setId(2);
SessionFactory sessionFactory=new Configuration().configure().buildSessionFactory();
Session session=sessionFactory.openSession();
session.beginTransaction();
session.save(person);
session.getTransaction().commit();
}
}
CRUD (Read)
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class Application {
public static void main(String[] args) {
SessionFactory sessionFactory=new Configuration().configure().buildSessionFactory();
Session session=sessionFactory.openSession();
session.beginTransaction();
Person person=session.get(Person.class,1);
session.getTransaction().commit();
session.close();
System.out.println(person);
}
}
CRUD (Update)
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class Application {
public static void main(String[] args) {
SessionFactory sessionFactory=new Configuration().configure().buildSessionFactory();
Session session=sessionFactory.openSession();
session.beginTransaction();
Person person=session.get(Person.class,1);
person.setName("Updated Name");
session.update(person);
session.getTransaction().commit();
session.close();
System.out.println(person);
}
}
CRUD (Delete)
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class Application {
public static void main(String[] args) {
SessionFactory sessionFactory=new Configuration().configure().buildSessionFactory();
Session session=sessionFactory.openSession();
session.beginTransaction();
Person person=session.get(Person.class,1);
session.delete(person);
session.getTransaction().commit();
session.close();
System.out.println(person);
}
}
Transient, Persistent and Detached states
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class Application {
public static void main(String[] args) {
Person person=new Person();
//Transient state
person.setName("Hibernate");
person.setAge(23);
SessionFactory sessionFactory=new Configuration().configure().buildSessionFactory();
Session session=sessionFactory.openSession();
session.beginTransaction();
//Persistent state
session.save(person);
person.setName("Updated");
session.getTransaction().commit();
session.close();
sessionFactory.close();
//Detached state
person.setName("Updated in detached");
}
}
Name Annotations
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity(name = "Employee")
public class Person {
@Id
Integer id;
@Column(name = "First_Name")
String name;
Integer age;
}
- Name property can be used with @Entity and @Column annotation to specify the name of table and column.
- @Id and @Column annotations can be used with getters also.
More Annotations
import javax.persistence.*;
import java.util.Date;
@Entity
@Table(name = "Employee")
public class Person {
@Id
Integer id;
@Column(name = "First_Name")
String name;
@Transient
Integer age;
@Temporal(TemporalType.DATE)
Date dob;
}
- @Table annotation is used to store specify the name of the table for entity.
- @Transient is used to ignore the field of an entity while persisting it into a database.
- @Temporal annotation is used with Date types to specify what should be saved i.e DATE, TIME or TIMESTAMP
Automatically generate primary key value
@Entity
@Table(name = "Employee")
public class Person {
@Id @GeneratedValue(strategy =GenerationType.SEQUENCE )
Integer id;
String name;
Integer age;
@Temporal(TemporalType.DATE)
Date dob;
}
- @GenerateValue annotation can be used to generate id for objects while persistence.
- AUTO (default): Tells Doctrine to pick the strategy that is preferred by the used database platform. The preferred strategies are IDENTITY for MySQL, SQLite and MsSQL and SEQUENCE for Oracle and PostgreSQL. This strategy provides full portability.
- SEQUENCE: Tells Doctrine to use a database sequence for ID generation. This strategy does currently not provide full portability. Sequences are supported by Oracle and PostgreSql.
-
IDENTITY: Tells Doctrine to use special identity columns in the database that generate a value on insertion of a row. This strategy does currently not provide full portability and is supported by the following platforms:
MySQL/SQLite => AUTO_INCREMENT
MSSQL => IDENTITY
PostgreSQL => SERIAL
Id Generation Stratergies
- TABLE: Tells Doctrine to use a separate table for ID generation. This strategy provides full portability.
Id Generation Stratergies (cont.)
Embedded Type
import javax.persistence.*;
@Entity
public class Person{
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
Integer id;
String name;
Integer age;
@Embedded
Address address;
}
For embedded object we can use @Embedded annotation for the Reference type instance variable
import javax.persistence.Embeddable;
@Embeddable
public class Address {
String city;
String country;
}
Optionally we can also place @Embeddable on the class of the reference type instance variable
Embedded type (Cont.)
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class Application {
public static void main(String[] args) {
Person person=new Person();
person.setName("Hibernate");
person.setAge(23);
Address address=new Address();
address.setCity("Delhi");
address.setCountry("India");
person.setAddress(address);
SessionFactory sessionFactory=new Configuration().configure().buildSessionFactory();
Session session=sessionFactory.openSession();
session.beginTransaction();
session.save(person);
session.getTransaction().commit();
session.close();
}
}
Saving Collections
import javax.persistence.*;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
@Entity
@Table(name = "Employee")
public class Person {
@Id @GeneratedValue(strategy =GenerationType.SEQUENCE )
Integer id;
String name;
Integer age;
@Temporal(TemporalType.DATE)
Date dob;
@ElementCollection
Set<String> hobbies=new HashSet<String>();
}
- @ElementCollection annotation is used to persist collections in Hibernate entities
One to One mapping
import javax.persistence.*;
@Entity
@Table(name = "Employee")
public class Person {
@Id @GeneratedValue(strategy =GenerationType.SEQUENCE )
Integer id;
String name;
Integer age;
@OneToOne
@JoinColumn(name = "Vehicle_join_column")
Vehicle vehicle;
}
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Vehicle {
@Id @GeneratedValue(strategy = GenerationType.AUTO)
Integer vehicleId;
String vehicleName;
}
One to One mapping (Cont.)
Person person=new Person();
person.setName("Hibernate");
person.setAge(27);
person.setId(1);
Vehicle vehicle=new Vehicle();
vehicle.setVehicleName("Car");
person.setVehicle(vehicle);
SessionFactory sessionFactory=new Configuration().configure().buildSessionFactory();
Session session=sessionFactory.openSession();
session.beginTransaction();
session.save(person);
session.save(vehicle);
session.getTransaction().commit();
session.close();
One to Many (Unidirectional)
import javax.persistence.*;
import java.util.Collection;
import java.util.HashSet;
@Entity
@Table(name = "Employee")
public class Person {
@Id @GeneratedValue(strategy =GenerationType.SEQUENCE )
Integer id;
String name;
Integer age;
@OneToMany
@JoinTable(joinColumns = @JoinColumn(name="USER_ID")
,inverseJoinColumns = @JoinColumn(name = "VEHICAL_ID"))
Collection<Vehicle> vehicle= new HashSet<Vehicle>();
}
import javax.persistence.*;
@Entity
public class Vehicle {
@Id @GeneratedValue(strategy = GenerationType.AUTO)
Integer vehicleId;
String vehicleName;
}
One to Many (Unidirectional) Cont.
Person person=new Person();
person.setName("Hibernate");
person.setAge(27);
person.setId(1);
Vehicle vehicle=new Vehicle();
vehicle.setVehicleName("Car");
Vehicle vehicle2=new Vehicle();
vehicle2.setVehicleName("Bike");
person.getVehicle().add(vehicle);
person.getVehicle().add(vehicle2);
SessionFactory sessionFactory=new Configuration().configure().buildSessionFactory();
Session session=sessionFactory.openSession();
session.beginTransaction();
session.save(person);
session.save(vehicle);
session.save(vehicle2);
session.getTransaction().commit();
session.close();
One to Many (Bidirectional)
import javax.persistence.*;
import java.util.Collection;
import java.util.HashSet;
@Entity
@Table(name = "Employee")
public class Person {
@Id @GeneratedValue(strategy =GenerationType.SEQUENCE )
Integer id;
String name;
Integer age;
@OneToMany
@JoinTable(joinColumns = @JoinColumn(name="USER_ID")
,inverseJoinColumns = @JoinColumn(name = "VEHICAL_ID"))
Collection<Vehicle> vehicle= new HashSet<Vehicle>();
}
import javax.persistence.*;
@Entity
public class Vehicle {
@Id @GeneratedValue(strategy = GenerationType.AUTO)
Integer vehicleId;
String vehicleName;
@ManyToOne
Person person;
}
Person person=new Person();
person.setName("Hibernate");
person.setAge(27);
person.setId(1);
Vehicle vehicle=new Vehicle();
vehicle.setVehicleName("Car");
vehicle.setPerson(person);
Vehicle vehicle2=new Vehicle();
vehicle2.setPerson(person);
vehicle2.setVehicleName("Bike");
person.getVehicle().add(vehicle);
person.getVehicle().add(vehicle2);
SessionFactory sessionFactory=new Configuration().configure().buildSessionFactory();
Session session=sessionFactory.openSession();
session.beginTransaction();
session.save(person);
session.save(vehicle);
session.save(vehicle2);
session.getTransaction().commit();
session.close();
One to Many (Bidirectional) Cont.
One to Many without additional table
import javax.persistence.*;
import java.util.Collection;
import java.util.HashSet;
@Entity
@Table(name = "Employee")
public class Person {
@Id @GeneratedValue(strategy =GenerationType.SEQUENCE )
Integer id;
String name;
Integer age;
@OneToMany(mappedBy = "person")
Collection<Vehicle> vehicle= new HashSet<Vehicle>();
}
import javax.persistence.*;
@Entity
public class Vehicle {
@Id @GeneratedValue(strategy = GenerationType.AUTO)
Integer vehicleId;
String vehicleName;
@ManyToOne
Person person;
}
Many to Many
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Entity
@Table(name = "Employee")
public class Person {
@Id @GeneratedValue(strategy =GenerationType.SEQUENCE )
Integer id;
String name;
Integer age;
@ManyToMany
List<Vehicle> vehicle= new ArrayList<Vehicle>();
}
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Entity
public class Vehicle {
@Id @GeneratedValue(strategy = GenerationType.AUTO)
Integer vehicleId;
String vehicleName;
@ManyToMany(mappedBy = "vehicle")
List<Person> personList = new ArrayList<Person>();
}
Cascade Type
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Entity
public class Person{
@Id @GeneratedValue(strategy = GenerationType.TABLE)
Integer id;
String name;
Integer age;
@OneToMany(cascade = CascadeType.PERSIST)
List<Vehicle> listOfVehicles=new ArrayList<Vehicle>();
}
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Vehicle {
@Id @GeneratedValue(strategy = GenerationType.TABLE)
Integer vehicleId;
String vehicleName;
}
Cascade Type (Cont.)
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class Application {
public static void main(String[] args) {
Person person=new Person();
person.setName("Hibernate");
person.setAge(23);
Vehicle vehicle=new Vehicle();
vehicle.setVehicleName("Car");
person.getListOfVehicles().add(vehicle);
SessionFactory sessionFactory=new Configuration().configure().buildSessionFactory();
Session session=sessionFactory.openSession();
session.beginTransaction();
session.persist(person);
session.getTransaction().commit();
session.close();
sessionFactory.close();
}
}
Inheritance
Hibernate provides several strategies to leverage this object-oriented trait onto domain model entities.
MappedSuperclass
When using MappedSuperclass, the inheritance is visible in the domain model only and each database table contains both the base class and the subclass properties.
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
@MappedSuperclass
public class Account {
@Id
private Integer id;
private String owner;
private Integer balance;
private Integer interestRate;
//getters and setters
}
import javax.persistence.Entity;
@Entity
public class DebitAccount extends Account{
private Integer overdraftFee;
//getter and setter
}
DebitAccount debitAccount=new DebitAccount();
debitAccount.setOwner("Peter");
debitAccount.setBalance(23000);
debitAccount.setInterestRate(23);
debitAccount.setId(2);
debitAccount.setOverdraftFee(2300);
session.save(debitAccount);
Single Table
The single table inheritance strategy maps all subclasses to only one database table. Each subclass declares its own persistent properties.
import javax.persistence.*;
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class Account {
@Id
private Integer id;
private String owner;
private Integer balance;
private Integer interestRate;
}
import javax.persistence.Entity;
@Entity
public class DebitAccount extends Account{
private Integer overdraftFee;
// getter and setter
}
Joined Table
Each subclass can also be mapped to its own table. This is also called table-per-subclass mapping strategy. An inherited state is retrieved by joining with the table of the superclass.
import javax.persistence.*;
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Account {
@Id
private Integer id;
private String owner;
private Integer balance;
private Integer interestRate;
}
import javax.persistence.Entity;
@Entity
public class DebitAccount extends Account{
private Integer overdraftFee;
// getter and setter
}
Table per class
This is called the table-per-concrete-class strategy. Each table defines all persistent states of the class, including the inherited state.
import javax.persistence.*;
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Account {
@Id
private Integer id;
private String owner;
private Integer balance;
private Integer interestRate;
}
import javax.persistence.Entity;
@Entity
public class DebitAccount extends Account{
private Integer overdraftFee;
// getter and setter
}
Hibernate Bootcamp
By Pulkit Pushkarna
Hibernate Bootcamp
- 1,766