Search code examples
spring-boothibernatespring-data-jpanhibernate-mapping

How should i define which Hibernate mapping to use, and when/where to use it?


i and having a use case where there are 2 kinds of users namely the "clients" and "professionals". These 2 entities have a parent entity called the "users" where each "user" has one entry in either "client/professional" depending on their role.

Let's consider a "clients".

  1. A "user" has a one-to-one mapping with a "client"
  2. A client might have several "companies" under him, i.e "client" has one-to-many relationship with "companies".

I am creating a REST API for this use case using spring boot. I still dont have any idea about why i should be using mapping in Hibernate. So far the only advantage i see is that, the CASCADING property of it. If a "user" gets removed, all the tables having the "user-id" will also be flushed. But consider a scenario where i need to add "companies" for a "client". I am confused to whether i should persist "companies" via "clients" entity or should i directly persist to "client" entity. I dont see any major advantage here because in both cases we are checking whether a "client" exists with the given ID before persisting in the "clients" table.

User Entity

public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long UID;

    private Integer userRoleId;

    private String username;
    private String email;
    private String phoneNumber;
    private String firstName;
    private String lastName;
    private Long dateOfJoin;
    private Boolean activeStatus;
    private Long createdAt;
    private Long updatedAt;

    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "user")
    private Client client;
}

Client Entity

public class Client {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long CID;

    @Column(unique = true)
    private Long userId;
    private Long createdAt;
    private Long updatedAt;

    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "client")
    private ClientCompany clientCompany;

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "userId" ,referencedColumnName = "UID", insertable = false, updatable = false)
    private User user;
}

Client Company Entity

public class ClientCompany {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long CCID;

    private Long clientId;
    private String email;
    private String phoneNumber;
    public String streetAddress1;
    public String streetAddress2;
    public String zipCode;
    public String city;
    public String state;
    public String country;
    private Long createdAt;
    private Long updatedAt;

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "clientId", referencedColumnName = "CID", insertable = false, updatable = false)
    private Client client;
}

Solution

  • The advantage of using Hibernate/JPA is that you do not need to code JDBC calls. You just use objects. In your scenario,

    1. load a Client instance from the database;
    2. create a ClientCompany object;
    3. assign the Client instance to it (no need to check the client existence since you loaded it from the database);
    4. save to database.

    Hibernate will take care of everything without you writing any SQL statements.

    Step 1) can also be replaced with creating a new Client that will be saved to the database, but again Hibernate will handle saving correctly (if you configured it correctly).