Reverse Engineering of JPA Entities with JBoss Tools Eclipse Plugin.

The tutorial below details how to do reverse engineering of Hibernate/JPA POJO entities from database tables.

The database tables\entities which are used for this tutorial are Course, Department and Student. The way these 3 tables are related are Courses have a many-to-many relationship with Students and Students have a many-to-many relationship with Departments. This means we have 5 tables in all Student, Course, Department, Department_Student and Student_Course. The DDL for these 5 tables is given below…please take note of the foreign key relationships between tables as these will be interpreted as relationships in the reverse generated POJO entities…

Scripts for tables - Student, Department & Course
 CREATE TABLE `student` (
  `STUDENT_ID` INT(11) NOT NULL,
  `FIRST_NAME` VARCHAR(255) DEFAULT NULL,
  `LAST_NAME` VARCHAR(255) DEFAULT NULL,
  `AGE` INT(11) DEFAULT NULL,
  `ADDRESS` VARCHAR(255) DEFAULT NULL,
  PRIMARY KEY (`STUDENT_ID`)
 )
 CREATE TABLE `department` (
  `DEPT_ID` INT(11) NOT NULL,
  `DEPT_NAME` VARCHAR(255) DEFAULT NULL,
  PRIMARY KEY (`DEPT_ID`)
 )
 CREATE TABLE `course` (
  `COURSE_ID` INT(11) NOT NULL,
  `COURSE_NAME` VARCHAR(255) NOT NULL,
  `COURSE_FROM` TIME DEFAULT NULL,
  `COURSE_TO` TIME DEFAULT NULL,
  PRIMARY KEY (`COURSE_ID`)
 )
 CREATE TABLE `department_student` (
  `Student_id` INT(11) NOT NULL,
  `department_id` INT(11) NOT NULL,
  PRIMARY KEY (`Student_id`,`department_id`),
  KEY `FK_department` (`department_id`),
  CONSTRAINT `FK_department` FOREIGN KEY (`department_id`) REFERENCES `department` (`DEPT_ID`),
  CONSTRAINT `FK_student` FOREIGN KEY (`Student_id`) REFERENCES `student` (`STUDENT_ID`)
 )
 CREATE TABLE `student_course` (
  `Student_id` INT(11) NOT NULL,
  `Course_id` INT(11) NOT NULL,
  PRIMARY KEY (`Student_id`,`Course_id`),
  KEY `FK_course` (`Course_id`),
  CONSTRAINT `FK_student_for_student_course` FOREIGN KEY (`Student_id`) REFERENCES `student` (`STUDENT_ID`),
  CONSTRAINT `FK_course` FOREIGN KEY (`Course_id`) REFERENCES `course` (`COURSE_ID`)
 )

Note: The above DDL script is for MySQL database but should work fine for all relational databases. Also, I am using MySQL as the default database for all my tutorials.

Note 2: There are certain pre-requisites for reverse code generation. These are –

Lets start off with the reverse code generation then…

Step 1: Open your JPA Project in Eclipse with the MySQL Data Connection. My JPA project is named ‘StudentDeptCourseProject’ after my three main entities. The contents in your eclipse window should resemble the snapshot below

Reverse Code Generation of Hibernate/JPA POJO Entities Step 01
Reverse Code Generation of Hibernate/JPA POJO Entities Step 01

Step 2:Double click on the persistence.xml for StudentDeptCourseProject and view its contents…

Reverse Code Generation of Hibernate/JPA POJO Entities Step 02
Reverse Code Generation of Hibernate/JPA POJO Entities Step 02

Step 3:For the next step we need to work in the “Hibernate” perspective. Go to Window>Open Perspective>Other… Select “Hibernate” and say “OK”…

Reverse Code Generation of Hibernate/JPA POJO Entities Step 03
Reverse Code Generation of Hibernate/JPA POJO Entities Step 03

Step 4: The below window gets displayed…

Reverse Code Generation of Hibernate/JPA POJO Entities Step 04
Reverse Code Generation of Hibernate/JPA POJO Entities Step 04

Then click on the “Hibernate Code Generation” icon in the top toolbar ( Arrow A in snapshot below) and then click on the menu item “Hibernate Code Generation Configurations…” (Arrow B)…

Reverse Code Generation of Hibernate/JPA POJO Entities Step 04 a
Reverse Code Generation of Hibernate/JPA POJO Entities Step 04 a

Step 5: The below dialog box for “Hibernate Code Generation Configurations” gets displayed…

Reverse Code Generation of Hibernate/JPA POJO Entities Step 04 b
Reverse Code Generation of Hibernate/JPA POJO Entities Step 05

Step 6: In the above displayed dialog box click on “setup” next to reveng.xml and then click on “Create New” button…

Reverse Code Generation of Hibernate/JPA POJO Entities Step 06
Reverse Code Generation of Hibernate/JPA POJO Entities Step 06

Step 7: Click on the project name StudentDeptCourse project and click “Next”…

Reverse Code Generation of Hibernate/JPA POJO Entities Step 07
Reverse Code Generation of Hibernate/JPA POJO Entities Step 07

Step 8: In the below window click refresh to show the list of tables in the ‘jb’ database(‘jb’ is the name of my database in MySQL)…

Reverse Code Generation of Hibernate/JPA POJO Entities Step 08
Reverse Code Generation of Hibernate/JPA POJO Entities Step 08

Step 9: Select all the tables and click on “Include”…

Reverse Code Generation of Hibernate/JPA POJO Entities Step 09
Reverse Code Generation of Hibernate/JPA POJO Entities Step 09

Step 10: Click “Finish” to finish generating “hibernate.reveng.xml”…

Reverse Code Generation of Hibernate/JPA POJO Entities Step 10
Reverse Code Generation of Hibernate/JPA POJO Entities Step 10

Step 11: This is how the Hibernate Code Generation Configurations window will appear with the entry for reveng.xml in place…

Reverse Code Generation of Hibernate/JPA POJO Entities Step 11
Reverse Code Generation of Hibernate/JPA POJO Entities Step 11

Step 12:Click on the “Exporters” tab to see how it appears…

Reverse Code Generation of Hibernate/JPA POJO Entities Step 12
Reverse Code Generation of Hibernate/JPA POJO Entities Step 12

Step 13:The reverse generated JPA POJO entities are present in the package com.javabrahman.reversegen. To view these go to the “Package Explorer” and expand the StudentDeptCourse project…

Reverse Code Generation of Hibernate/JPA POJO Entities Step 13
Reverse Code Generation of Hibernate/JPA POJO Entities Step 13

Note that the two many-to-many mapping classes do not have equivalent java entities. This is because these many-to-many entities have been specified as relationship tables in the student entity itself…

Let’s now have a look at the reverse generated Java code…

POJO for Course generated by hbm2java
package com.javabrahman.reversegen;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.*;
 /**
 * POJO for Course generated by hbm2java
 */
 @Entity
 @Table(name = "course", catalog = "jb")
 public class Course implements java.io.Serializable {
  private int courseId;
  private String courseName;
  private Date courseFrom;
  private Date courseTo;
  private Set students = new HashSet(0);public Course() {
 }
 public Course(int courseId, String courseName) {
  this.courseId = courseId;
  this.courseName = courseName;
 }
 public Course(int courseId, String courseName, Date courseFrom,
Date courseTo, Set students) {
  this.courseId = courseId;
  this.courseName = courseName;
  this.courseFrom = courseFrom;
  this.courseTo = courseTo;
  this.students = students;
 }
 @Id
 @Column(name = "COURSE_ID", unique = true, nullable = false)
  public int getCourseId() {
  return this.courseId;
 }
 public void setCourseId(int courseId) {
  this.courseId = courseId;
 }
 @Column(name = "COURSE_NAME", nullable = false)
 public String getCourseName() {
  return this.courseName;
 }
 public void setCourseName(String courseName) {
  this.courseName = courseName;
 }
 @Temporal(TemporalType.TIME)
 @Column(name = "COURSE_FROM", length = 8)
 public Date getCourseFrom() {
  return this.courseFrom;
 }
 public void setCourseFrom(Date courseFrom) {
  this.courseFrom = courseFrom;
 }
 @Temporal(TemporalType.TIME)
 @Column(name = "COURSE_TO", length = 8)
 public Date getCourseTo() {
  return this.courseTo;
 }
 public void setCourseTo(Date courseTo) {
  this.courseTo = courseTo;
 }
 @ManyToMany(fetch = FetchType.LAZY, mappedBy = "courses")
 public Set getStudents() {
  return this.students;
 }
 public void setStudents(Set students) {
  this.students = students;
 }
}
POJO for Student generated by hbm2java
package com.javabrahman.reversegen;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.*;
 /**
 * POJO for Student generated by hbm2java
 */
 @Entity
 @Table(name = "student", catalog = "jb")
 public class Student implements java.io.Serializable {
  private int studentId;
  private String firstName;
  private String lastName;
  private Integer age;
  private String address;
  private Set courses = new HashSet(0);
  private Set departments = new HashSet(0);
  
  public Student() {
  }
  public Student(int studentId) {
   this.studentId = studentId;
  }
  public Student(int studentId, String firstName, String lastName,
Integer age, String address, Set courses,
Set departments) {
   this.studentId = studentId;
   this.firstName = firstName;
   this.lastName = lastName;
   this.age = age;
   this.address = address;
   this.courses = courses;
   this.departments = departments;
  }
  @Id
  @Column(name = "STUDENT_ID", unique = true, nullable = false)
  public int getStudentId() {
   return this.studentId;
  }
  public void setStudentId(int studentId) {
   this.studentId = studentId;
 }
 @Column(name = "FIRST_NAME")
 public String getFirstName() {
  return this.firstName;
 }
 public void setFirstName(String firstName) {
  this.firstName = firstName;
 }
 @Column(name = "LAST_NAME")
 public String getLastName() {
  return this.lastName;
 }
 public void setLastName(String lastName) {
  this.lastName = lastName;
 }
 @Column(name = "AGE")
 public Integer getAge() {
  return this.age;
 }
 public void setAge(Integer age) {
  this.age = age;
 }
 @Column(name = "ADDRESS")
 public String getAddress() {
  return this.address;
 }
 public void setAddress(String address) {
  this.address = address;
 }
 @ManyToMany(fetch = FetchType.LAZY)
 @JoinTable(name = "student_course", catalog = "jb", joinColumns = { @JoinColumn(name = "Student_id", nullable = false, updatable = false) }, inverseJoinColumns = { @JoinColumn(name = "Course_id", nullable = false, updatable = false) })
 public Set getCourses() {
  return this.courses;
 }
 public void setCourses(Set courses) {
  this.courses = courses;
 }
 @ManyToMany(fetch = FetchType.LAZY)
 @JoinTable(name = "department_student", catalog = "jb", joinColumns = { @JoinColumn(name = "Student_id", nullable = false, updatable = false) }, inverseJoinColumns = { @JoinColumn(name = "department_id", nullable = false, updatable = false) })
 public Set getDepartments() {
  return this.departments;
 }
 public void setDepartments(Set departments) {
  this.departments = departments;
 }
}
POJO for Department generated by hbm2java
package com.javabrahman.reversegen;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.*;
 /**
 * POJO for Department generated by hbm2java
 */
 @Entity
 @Table(name = "department", catalog = "jb")
 public class Department implements java.io.Serializable {
  private int deptId;
  private String deptName;
  private Set students = new HashSet(0);public Department() {
 }
 public Department(int deptId) {
  this.deptId = deptId;
 }
 public Department(int deptId, String deptName, Set students) {
 this.deptId = deptId;
 this.deptName = deptName;
 this.students = students;
 }
 @Id
 @Column(name = "DEPT_ID", unique = true, nullable = false)
 public int getDeptId() {
  return this.deptId;
 }
 public void setDeptId(int deptId) {
  this.deptId = deptId;
 }
 @Column(name = "DEPT_NAME")
 public String getDeptName() {
  return this.deptName;
 }
 public void setDeptName(String deptName) {
  this.deptName = deptName;
 }
 @ManyToMany(fetch = FetchType.LAZY, mappedBy = "departments")
 public Set getStudents() {
  return this.students;
 }
 public void setStudents(Set students) {
  this.students = students;
 }
}

 

Digiprove sealCopyright © 2014-2022 JavaBrahman.com, all rights reserved.

14 thoughts on “Reverse Engineering of JPA Entities with JBoss Tools Eclipse Plugin.”

    1. Hi Isaac,
      Thanks for liking the guide :).
      I went through the stackoverflow query & the linked query as well. I kind of agree with the answer you got there i.e. its kind of redundant to keep both id and entity in your POJO.
      However, considering that you want to simplify your generalized methods which will use these values(andor having a small memory footprint) then I would suggest an approach in which you have the Address POJO as JPA warrants (without the addressId as a separate field) in your User POJO & lazy load your non-id fields in the Address POJO. This way your memory issue will be resolved to some extent & the redundancy can be avoided.

      1. Thanks for your quick response! My point in that post is that the memory used by this redundant pattern is quite trivial, and is not a problem for us. We would prefer to trade the efficiency of having strict relationships (without foreign keys) for the better maintainability of having the foreign keys be present directly on the objects. The pattern of having foreign keys present allows us to write a single method which serializes all our objects, for example. This saves us from a nightmare of writing a huge number of custom serializers which navigate the parent/child relationships.

        Even if you don’t think it is the best solution, do you know how one would go about including both the foreign key and relationship on the pojo?

        1. Hey Isaac,

          I am not aware of JPA providing such a feature for mapping both the foreign key & relationship.

          However, it does make sense to write generalized methods as you described. In case JPA doesn’t help with the id fields, then I think you can treat the foreign-key id fields as normal fields in your table, maybe make them not-null, and then join generically using JPQL. You may already be zeroing in on this approach.

        2. Really appreciate you offering this solution. I’m hesitant to remove the foreign keys from the database itself. I think that will cause its own problems. I’m considering altering the source code of hibernate tools directly (if that is possible).

    1. Hi Isaac,
      Thanks for liking the guide :).
      I went through the stackoverflow query & the linked query as well. I kind of agree with the answer you got there i.e. its kind of redundant to keep both id and entity in your POJO.
      However, considering that you want to simplify your generalized methods which will use these values(andor having a small memory footprint) then I would suggest an approach in which you have the Address POJO as JPA warrants (without the addressId as a separate field) in your User POJO & lazy load your non-id fields in the Address POJO. This way your memory issue will be resolved to some extent & the redundancy can be avoided.

      1. Thanks for your quick response! My point in that post is that the memory used by this redundant pattern is quite trivial, and is not a problem for us. We would prefer to trade the efficiency of having strict relationships (without foreign keys) for the better maintainability of having the foreign keys be present directly on the objects. The pattern of having foreign keys present allows us to write a single method which serializes all our objects, for example. This saves us from a nightmare of writing a huge number of custom serializers which navigate the parent/child relationships.

        Even if you don’t think it is the best solution, do you know how one would go about including both the foreign key and relationship on the pojo?

        1. Hey Isaac,

          I am not aware of JPA providing such a feature for mapping both the foreign key & relationship.

          However, it does make sense to write generalized methods as you described. In case JPA doesn’t help with the id fields, then I think you can treat the foreign-key id fields as normal fields in your table, maybe make them not-null, and then join generically using JPQL. You may already be zeroing in on this approach.

        2. Really appreciate you offering this solution. I’m hesitant to remove the foreign keys from the database itself. I think that will cause its own problems. I’m considering altering the source code of hibernate tools directly (if that is possible).

Comments are closed.