Step 4- Mapping in Hibernate

Mapping meaning in hibernate-

Connection between java class to database tables

Types of mapping in hibernate-

1- Inheritance Mapping-

When java classes are having inheritance, their tables can be created using 3 ways-

1- Table per class hierarchy (Single Table Strategy)
-Only one table is created for all the classes.
-One Discriminator field is used.
xml element <subclass> is used.
-Gives maximum performance

[XML mapping file]-

<?xml version="1.0" encoding="UTF-8"?>
<hibernate-mapping>
  <class name="Person" table="PERSONS">
    <id name="id" column="PERSON_ID" type="long" />
    <discriminator column="PERSON_TYPE" type="string" />
    <property name="name" column="NAME" type="string" />
    <property name="address" column="ADDRESS" type="string" />
    <subclass name="Employee" discriminator-value="E">
      <property name="salary" column="SALARY" type="double" />
      <property name="title" column="TITLE" type="string" />
    </subclass>
    <subclass name="Student" discriminator-value="S">
      <property name="major" column="MAJOR" type="string" />
      <property name="gpa" column="GPA" type="double" />
    </subclass>
  </class>
</hibernate-mapping>

[Table in database ]-

PERSONS
+————-+————-+————+————————-+
| PERSON_ID | NAME | ADDRESS | PERSON_TYPE |
+————-+————-+————+————————-+
| 1 | John Doe | 123 Main St | E |
+————-+————-+————+————————-+
| 2 | Jane Doe | 456 Park Ave | S |
+————-+————-+————+————————-+


2–Table per sub-class hierarchy (Joined Strategy)
-One table for each class is created.
-Foreign key is maintained between the tables.
-xml element <joined- subclass> is used.

[XML mapping file]-

<?xml version="1.0" encoding="UTF-8"?>
<hibernate-mapping>
  <class name="Person" table="PERSONS">
    <id name="id" column="PERSON_ID" type="long" />
    <property name="name" column="NAME" type="string" />
    <property name="address" column="ADDRESS" type="string" />
    <joined-subclass name="Employee" table="EMPLOYEES">
      <key column="PERSON_ID" />
      <property name="salary" column="SALARY" type="double" />
      <property name="title" column="TITLE" type="string" />
    </joined-subclass>
    <joined-subclass name="Student" table="STUDENTS">
      <key column="PERSON_ID" />
      <property name="major" column="MAJOR" type="string" />
      <property name="gpa" column="GPA" type="double" />
    </joined-subclass>
  </class>
</hibernate-mapping>

[Tables in database]-

PERSONS
+————-+————-+—————-+
| PERSON_ID | NAME | ADDRESS |
+————-+————-+—————-+
| 1 | John Doe | 123 Main St |
+————-+————-+—————-+
| 2 | Jane Doe | 456 Park Ave |
+————-+————-+—————–+

EMPLOYEES
+————-+————-+————+
| PERSON_ID | SALARY | TITLE |
+————-+————-+————+
| 1 | 50000 | Manager |
+————-+————-+————+

STUDENTS
+————-+————-+————+
| PERSON_ID | MAJOR | GPA |
+————-+————-+————+
| 2 | CS | 3.5 |
+————-+————-+————+



3-Table per concrete class hierarchy-
-One table for each concrete class (subclass) is created but not of super classes.
-Foreign key is not maintained.
-xml element<union-subclass> is used.

[XML mapping file]-

<?xml version="1.0" encoding="UTF-8"?>
<hibernate-mapping>
  <class name="Person" abstract="true">
    <id name="id" column="PERSON_ID" type="long" />
    <property name="name" column="NAME" type="string" />
    <property name="address" column="ADDRESS" type="string" />
  </class>
  <class name="Employee" table="EMPLOYEES">
    <id name="id" column="EMPLOYEE_ID" type="long" />
    <property name="salary" column="SALARY" type="double" />
    <property name="title" column="TITLE" type="string" />
    <property name="person_id" column="PERSON_ID" type="long" insert="false" update="false" />
  </class>
  <class name="Student" table="STUDENTS">
    <id name="id" column="STUDENT_ID" type="long" />
    <property name="major" column="MAJOR" type="string" />
    <property name="gpa" column="GPA" type="double" />
    <property name="person_id" column="PERSON_ID" type="long" insert="false" update="false" />
  </class>
</hibernate-mapping>

[Tables in database]-

PERSONS
+————-+————-+—————-+
| PERSON_ID | NAME | ADDRESS |
+————-+————-+—————-+
| 1 | John Doe | 123 Main St |
+————-+————-+—————-+
| 2 | Jane Doe | 456 Park Ave |
+————-+————-+—————-+

EMPLOYEES
+————-+————-+————+
| EMPLOYEE_ID | SALARY | TITLE | PERSON_ID|
+————-+————-+————+————+
| 1 | 50000 | Manager |1 |
+————-+————-+————+————+

STUDENTS
+————-+————-+————+
| STUDENT_ID | MAJOR | GPA | PERSON_ID |
+————-+————-+————+————+
| 2 | CS | 3.5 |2 |
+————-+————-+————+————+

2- Collection Mapping-

When java class is having collection object, they can be stored according to their type of collection –

collectiondescriptionxml based mappingannotation based mapping
ListA list of entities mapped to a single table.<list name=”employees” table=”employees_list”><key column=”employee_id”/><index column=”employee_index”/><one-to-many class=”Employee”/></list>@ElementCollection
@CollectionTable(name=”employees_list”, joinColumns=@JoinColumn(name=”employee_id”))
@Column(name=”employee_index”)
private List<Employee> employees;
SetA set of entities mapped to a single table.<set name=”employees” table=”employees_set”><key column=”employee_id”/><one-to-many class=”Employee”/></set>@ElementCollection
@CollectionTable(name=”employees_set”, joinColumns=@JoinColumn(name=”employee_id”))
private Set<Employee> employees;
MapA map of entities mapped to a single table, where the keys and values are both entities.<map name=”employees” table=”employees_map”><key column=”employee_id”/><map-key column=”employee_key”/><one-to-many class=”Employee”/>
</map>
@ElementCollection
@CollectionTable(name=”employees_map”, joinColumns=@JoinColumn(name=”employee_id”))
@MapKeyColumn(name=”employee_key”)
private Map<String, Employee> employees;

1-list mapping

[XML Based Mapping]-

<class name="Department">
  <id name="id" column="department_id" type="long"/>
  <property name="name" column="department_name" type="string"/>
  <list name="employeeNames" table="employee_names_list">
    <key column="department_id"/>
    <index column="employee_index"/>
    <element column="employee_name" type="string"/>
  </list>
</class>

[Annotation Based Mapping]-

@Entity
@Table(name = "Department")
public class Department {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "department_id")
  private Long id;

  @Column(name = "department_name")
  private String name;

  @ElementCollection
  @CollectionTable(name = "employee_names_list", joinColumns = @JoinColumn(name = "department_id"))
  @Column(name = "employee_name")
  @OrderColumn(name = "employee_index")
  private List<String> employeeNames;

  //getters and setters
}

[CRUD Example (Create, Read, Update, Delete)]-

// Saving a new Department with a list of employee names
Session session = sessionFactory.openSession();
session.beginTransaction();

List<String> employeeNames = new ArrayList<>();
employeeNames.add("John Doe");
employeeNames.add("Jane Smith");

Department department = new Department("Marketing", employeeNames);
session.save(department);

session.getTransaction().commit();
session.close();

// Retrieving a Department by id
Session session = sessionFactory.openSession();
Department department = session.get(Department.class, 1L);
List<String> employeeNames = department.getEmployeeNames();

// Updating a Department's list of employee names
Session session = sessionFactory.openSession();
session.beginTransaction();

Department department = session.get(Department.class, 1L);
department.getEmployeeNames().add("Bob Johnson");
session.update(department);

session.getTransaction().commit();
session.close();

// Deleting a Department
Session session = sessionFactory.openSession();
session.beginTransaction();

Department department = session.get(Department.class, 1L);
session.delete(department);

session.getTransaction().commit();
session.close();


2-set mapping

[XML Based Mapping]

<class name="Department">
  <id name="id" column="department_id" type="long"/>
  <property name="name" column="department_name" type="string"/>
  <set name="employeeNames" table="employee_names_set">
    <key column="department_id"/>
    <element column="employee_name" type="string"/>
  </set>
</class>

[Annotation Based Mapping]

@Entity
@Table(name = "Department")
public class Department {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "department_id")
  private Long id;

  @Column(name = "department_name")
  private String name;

  @ElementCollection
  @CollectionTable(name = "employee_names_set", joinColumns = @JoinColumn(name = "department_id"))
  @Column(name = "employee_name")
  private Set<String> employeeNames;

  //getters and setters
}

[CRUD Example (Create, Read, Update, Delete)]-

//creating new department
Department department = new Department();
department.setName("IT Department");
department.setEmployeeNames(new HashSet<>(Arrays.asList("John Doe", "Jane Doe")));

//saving the department to the database
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(department);
em.getTransaction().commit();
em.close();

//retrieving a department
EntityManager em = emf.createEntityManager();
Department department = em.find(Department.class, 1L);

//updating a department
department.getEmployeeNames().add("Bob Smith");
em.getTransaction().begin();
em.merge(department);
em.getTransaction().commit();
em.close();

//deleting a department
EntityManager em = emf.createEntityManager();
Department department = em.find(Department.class, 1L);
em.getTransaction().begin();
em.remove(department);
em.getTransaction().commit();
em.close();


3-map mapping

[XML Based Mapping]

<class name="Department">
  <id name="id" column="department_id" type="long"/>
  <property name="name" column="department_name" type="string"/>
  <map name="employeeNames" table="employee_names_map">
    <key column="department_id"/>
    <map-key column="employee_id" type="long"/>
    <element column="employee_name" type="string"/>
  </map>
</class>

[Annotation Based Mapping]

@Entity
@Table(name = "Department")
public class Department {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "department_id")
  private Long id;

  @Column(name = "department_name")
  private String name;

  @ElementCollection
  @CollectionTable(name = "employee_names_map", joinColumns = @JoinColumn(name = "department_id"))
  @MapKeyColumn(name = "employee_id")
  @Column(name = "employee_name")
  private Map<Long, String> employeeNames;
  
  //getters and setters
}

[CRUD Example (Create, Read, Update, Delete)]-

//creating new department
Department department = new Department();
department.setName("IT Department");
Map<Long, String> employeeNames = new HashMap<>();
employeeNames.put(1L, "John Doe");
employeeNames.put(2L, "Jane Doe");
department.setEmployeeNames(employeeNames);

//saving the department to the database
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(department);
em.getTransaction().commit();
em.close();

//retrieving the department from the database
em = emf.createEntityManager();
Department departmentFromDb = em.find(Department.class, department.getId());
System.out.println(departmentFromDb);
em.close();

//updating the department
em = emf.createEntityManager();
em.getTransaction().begin();
departmentFromDb.getEmployeeNames().put(3L, "Bob Smith");
em.merge(departmentFromDb);
em.getTransaction().commit();
em.close();

//deleting the department
em = emf.createEntityManager();
em.getTransaction().begin();
Department departmentToDelete = em.find(Department.class, department.getId());
em.remove(departmentToDelete);
em.getTransaction().commit();
em.close();

3- Association mapping-

When java class is having reference of another java class, their tables can be created using 3 ways-

1-One to one –

[XML Based Mapping]

<hibernate-mapping>
  <class name="Person" table="person">
    <id name="id" column="id" type="long" unsaved-value="null">
      <generator class="native"/>
    </id>
    <property name="name" column="name" type="string"/>
    <one-to-one name="address" class="Address" cascade="all"/>
  </class>
</hibernate-mapping>

[Annotation Based Mapping]

@Entity
public class Person {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    @OneToOne(cascade = CascadeType.ALL)
    private Address address;
    // getters and setters
}

[CRUD Example (Create, Read, Update, Delete)]-

SessionFactory factory = new Configuration().configure().buildSessionFactory();
Session session = factory.openSession();

// Create
session.beginTransaction();
Person person = new Person();
person.setName("John Doe");
session.save(person);
session.getTransaction().commit();

// Read
Person person = (Person) session.get(Person.class, 1L);

// Update
session.beginTransaction();
person.setName("Jane Doe");
session.update(person);
session.getTransaction().commit();

// Delete
session.beginTransaction();
session.delete(person);
session.getTransaction().commit();

2-Many to One

[XML Based Mapping]

<hibernate-mapping>
    <class name="Employee" table="employee">
        <id name="id" column="id" type="int"/>
        <property name="name" column="name" type="string"/>
        <many-to-one name="department" column="dept_id" class="Department"/>
    </class>
</hibernate-mapping>

[Annotation Based Mapping]

@Entity
public class Employee {
    @Id
    private int id;
    private String name;
    @ManyToOne
    @JoinColumn(name="dept_id")
    private Department department;
    //getters and setters
}

@Entity
public class Department {
    @Id
    private int id;
    private String name;
    //getters and setters
}

[CRUD Example (Create, Read, Update, Delete)]-

//Create
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
Department department = new Department();
department.setName("IT");
session.save(department);
session.getTransaction().commit();
session.close();

//Read
Session session = HibernateUtil.getSessionFactory().openSession();
Department department = session.get(Department.class, 1);
System.out.println(department.getName());
session.close();

//Update
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
Department department = session.get(Department.class, 1);
department.setName("Finance");
session.update(department);
session.getTransaction().commit();
session.close();

//Delete
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
Department department = session.get(Department.class, 1);
session.delete(department);
session.getTransaction().commit();
session.close();

3- One to Many-

[XML Based Mapping]

<hibernate-mapping>
    <class name="Department" table="department">
        <id name="id" column="id" type="int"/>
        <property name="name" column="name" type="string"/>
        <one-to-many name="employee" class="Employee" column="dept_id"/>
    </class>
    <class name="Employee" table="employee">
        <id name="id" column="id" type="int"/>
        <property name="name" column="name" type="string"/>
    </class>
</hibernate-mapping>

[Annotation Based Mapping]

@Entity
public class Department {
    @Id
    private int id;
    private String name;
    @OneToMany
    @JoinColumn(name="dept_id")
    private Employee employee;
    //getters and setters
}

@Entity
public class Employee {
    @Id
    private int id;
    private String name;
    //getters and setters
}

[CRUD Example (Create, Read, Update, Delete)]-

    // Create
    Session session = HibernateUtil.getSessionFactory().openSession();
    session.beginTransaction();

    Employee employee = new Employee();
    employee.setName("John Doe");

    Department department = new Department();
    department.setName("IT");
    department.setEmployee(employee);

    session.save(employee);
    session.save(department);

    session.getTransaction().commit();
    session.close();

    // Read
    session = HibernateUtil.getSessionFactory().openSession();
    department = (Department) session.get(Department.class, 1);
    System.out.println("Department name: " + department.getName());
    System.out.println("Employee name: " + department.getEmployee().getName());
    session.close();

    // Update
    session = HibernateUtil.getSessionFactory().openSession();
    session.beginTransaction();
    department = (Department) session.get(Department.class, 1);
    department.setName("Marketing");
    session.update(department);
    session.getTransaction().commit();
    session.close();

    // Delete
    session = HibernateUtil.getSessionFactory().openSession();
    session.beginTransaction();
    department = (Department) session.get(Department.class, 1);
    session.delete(department);
    session.getTransaction().commit();
    session.close();

4-Many to many

[XML Based Mapping]

<hibernate-mapping>
    <class name="Student" table="student">
        <id name="id" column="id" type="int">
            <generator class="increment"/>
        </id>
        <property name="name" column="name" type="string"/>
        <set name="courses" table="student_course" cascade="all">
            <key column="student_id"/>
            <many-to-many column="course_id" class="Course"/>
        </set>
    </class>
    <class name="Course" table="course">
        <id name="id" column="id" type="int">
            <generator class="increment"/>
        </id>
        <property name="name" column="name" type="string"/>
        <set name="students" inverse="true">
            <key column="student_id"/>
            <many-to-many column="course_id" class="Student"/>
        </set>
    </class>
</hibernate-mapping>

[Annotation Based Mapping]

@Entity
public class Student {
    @Id
    private int id;
    private String name;
    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "student_course", joinColumns = { @JoinColumn(name = "student_id") }, inverseJoinColumns = { @JoinColumn(name = "course_id") })
    private Set<Course> courses;
    // getters and setters
}

@Entity
public class Course {
    @Id
    private int id;
    private String name;
    @ManyToMany(mappedBy = "courses")
    private Set<Student> students;
    // getters and setters
}

[CRUD Example (Create, Read, Update, Delete)]-

SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();

// Create
Student student = new Student();
student.setName("John Doe");
Set<Course> courses = new HashSet<Course>();
courses.add(new Course("Math"));
courses.add(new Course("Physics"));
student.setCourses(courses);
session.save(student);

// Read
Student s = (Student) session.get(Student.class, student.getId());
System.out.println(s.getName() + " takes " + s.getCourses().size() + " courses");

// Update
s.getCourses().add(new Course("Chemistry"));
session.update(s);

// Delete
session.delete(s);
session.getTransaction().commit();
session.close();