Handling Database Tables with no Primary key in Spring MVC and Hibernate

If you are building your web application in Java, you might be using Spring MVC with Hibernate. Both these Frameworks are extremely powerful and lets you, the developer to focus on building the application itself rather than to worry about many other factors required to manage and maintain the project dependencies.

You might have designed a database model, and might have tables without a primary key. Tables which map multiple tables (a.k.a Mapping tables), usually do not have a primary key. While this seems normal, there are situations when you will have to insert or update values into the table and you will find it difficult to do so. Why?  That’s because, without a key, there exists an ambiguity as to which row to update or delete. Fortunately, there is an easy way to solve this problem.

This is gonna be a long post. So, brace yourselves. I will try my best to make my point, but if you have any queries/ suggestions, feel free to let me know in the comments below. So, let’s begin.

The answer to this issue is to use an Embedded Entity which provides a key to the persistent entity without a primary key. And these are the two annotations that will be required: @Embeddable and @Embedded.

Consider two persistent entities called Car.java and Color.java. These two have a Primary Key each and represent the tables “CAR” and “COLOR” tables in the “VEHICLE” database/schema.

Car.java:


package com.example.entities;</pre>

@Entity
@Table(name = "CAR", catalog = "VEHICLE")
public class Car implements java.io.Serializable {

private int carId;
private String carName;

@Id
@Column(name = "CAR_ID", unique = true, nullable = false)
public int getId(){
return this.colorId;
}
public void setId(int colorId){
this.colorId = colorId;
}

public void setCarName(String carName){
this.carName = carName;
}
@Column(name = "CAR_NAME", nullable = false)
public String getCarName(){
return this.CarName;
}

}

Color.java:

package com.example.entities;
@Entity
@Table(name = "COLOR", catalog = "VEHICLE")
public class Color implements java.io.Serializable{

private int colorID;
private String colorName;

@Id
@Column(name = "COLOR_ID", unique = true, nullable = false)
public int getId(){
return this.colorId;
}
public void setId(int colorId){
this.colorId = colorId;
}

@Column(name = "COLOR_NAME", nullable = false)
public String getColor(){
return this.colorName;
}
public void setColor(String colorName){
this.colorName = colorName;
}

}

For these two entities let there be another mapping entity called “CarColor.java”.This is the representation of the mapping table between “CAR” and “COLOR”. As this is a mapping table, it does not have any primary key. In Spring Hibernate scenario, the entity CarColor.java would be like:

CarColor.java

package com.example.entities;

@Entity
@Table(name = "CAR_COLOR", catalog = "VEHICLE")
public class CarColor implements java.io.Serializable{

private Car car;
private Color color;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "CAR_NAME", nullable = false, insertable = false, updatable = false)
public Car getCar(){
return this.car;
}
public void setCar(Car car){
this.car = car;
}

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "COLOR_NAME", nullable = false, insertable = false, updatable = false)
public COLOR getColor(){
return this.color;
}
public void setColor(Color color){
this.color = color;
}
}

[themify_box color=”yellow”]If you are interested in becoming an expert at Java Spring Framework and Hibernate, you can now learn from world experts. Enroll to this best seller course on the Spring Framework and get 90% discount upon login. check out Spring Framework Master Class – Beginner to Expert[/themify_box]
This above example is correct, but as you would have seen, No primary key is there. So, if there are scenarios where you want to identify a record uniquely, you will find yourself in a bit of trouble. But, there is a  way around it. If you have auto generated the entities, then this workaround is automatically implemented. If not, yo can do it yourself. Here is what needs to be done:

adding another entity called CarColorId.java. This class is NOT a persistent class. But this can be used to uniquely identify each record in the CarColor.java   table. Here is the new Implementation of CarColor.java and also CarColorId.java .

CarColor.java


package com.example.entities;

@Entity
@Table(name = "CAR_COLOR", catalog = "VEHICLE")
public class CarColor implements java.io.Serializable{

<strong>//The following variable is of the type CarColorId</strong>
private CarColorId id;
private Car car;
private Color color;

@EmbeddedId
@AttributeOverrides({
@AttributeOverride(name = "carId", column = @Column(name = "CAR_ID", nullable = false)),
@AttributeOverride(name = "colorId", column = @Column(name = "COLOR_ID", nullable = false))})
public CarColorId getId() {
<span style="font-size: 16px; line-height: 1.5;">return this.id;
</span><span style="font-size: 16px; line-height: 1.5;">}</span>

public void setId(CarColorId id) {
this.id = id;
}

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "CAR_NAME", nullable = false, insertable = false, updatable = false)
public Car getCar(){
return this.car;
}

public void setCar(Car car){
this.car = car;
}

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "COLOR_NAME", nullable = false, insertable = false, updatable = false)
public COLOR getColor(){
return this.color;
}

public void setColor(Color color){
this.color = color;
}

}

CarColorId.java


package com.example.entities;

@Embeddable
public class CarColorId implements java.io.Serializable{

private int carId;
private int colorId;

@Column(name = "COLOR_ID", nullable = false)
public int getColorId(){
return this.colorId;
}
public void setColorId(int colorId){
this.colorId = colorId;
}
@Column(name = "CAR_ID", nullable = false)
public int getCarId(){
return this.colorId;
}
public void setCarId(int colorId){
this.colorId = colorId;
}

public int hashCode() {
int result = 17;

result = 37 * result + this.getCarId();
result = 37 * result + this.getColorId();
return result;
}

}

Let’s analyze the new things that have been included in the above two classes.  Firstly, you would have observed two new annotations: @Embeddable and @EmbeddedId . Here embeddable is used to indicate an entity that isn’t a persistent class but has persistent objects within them and these persistent objects can be used to gain an identity to the persistent class to which it forms an ID. @EmbeddedId is used to represent the object of the embeddable class.

Also, there is method in carColorId called hashCode() . hashcode() are methods are the ones which gives an integer value for a given object. So, the hash value of an object always remains the same and a carefully created hashCode() is the one which gives a unique identity to an object of the persistent class. So, in our example, class CarColorId gives a unique Identity to our persistent class CarColor.  

To perform operations on the CarColor table, one can find and compare objects of the type CarColor by making use of the hashCode() and using that value as a value that provides uniqueness to the objects of that class.

As an example, If you want to update an object of type CarColor, then first fetch the objects that match the criteria of car name and/or car color . Then apply the hashcode() on that object to check it matches the object that has to be updated. If it does, then perform the update operation.

So, this is it from me. Hope that you have found what you have been looking for. Feel free to comment regarding any questions or suggestions.

 

akshay pai

I am a data science engineer and I love working on machine learning problems. I have experience in computer vision, OCR and NLP. I love writing and sharing my knowledge with others. This is why I created Source Dexter. Here I write about Python, Machine Learning, and Raspberry Pi the most. I also write about technology in general, books and topics related to science. I am also a freelance writer with over 3 years of writing high-quality, SEO optimized content for the web. I have written for startups, websites, and universities all across the globe. Get in Touch! We can discuss more.

One thought on “Handling Database Tables with no Primary key in Spring MVC and Hibernate

  • May 16, 2020 at 12:50 am
    Permalink

    In the source code car.java, do you intend to return this.carId?

    Reply

Leave a Reply