Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to map two JPA or Hibernate entities on the same database table

In our project, we have an entity 'Restaurant' with nearly 30 fields(some have relationships with other entities). So, every time we need a 'Restaurant' object even for a few fields, all the others are retrieved. This effects the performance. So, in the HBM file, we wrote two classes both pointing to the same physical class and same database table, as shown below.

=== restaurant.hbm.xml ===
<!-- Light Weight Version -->
<class name="com.raj.model.Restaurant" table="RESTAURANTS" entity-name="RestaurantLite" 
                dynamic-update="false" dynamic-insert="false">
<cache usage="read-only"/>
     <!-- few basic properties and relationships -->
</class>

<!-- Restaurant -->
<class name="com.raj.model.Restaurant" table="RESTAURANTS" entity-name="Restaurant">
     <!-- all properties and relationships -->
</class>

In one of the DAO implementations, we are using Criteria which takes 'RestaurantLite' and returning list of restaurants as shown below.

Criteria criteria = session.createCriteria("RestaurantLite");

   // criteria related stuff

return new LinkedHashSet<Restaurant>(criteria.list());

Now we want to remove all hbm files and use annotations. So how the same can be done using annotations for entites? Do we need to create an extra class 'RestaurantLite'? If then, how the above criteria returns 'Restaurant' objects??

like image 208
Raj44 Avatar asked Mar 12 '15 10:03

Raj44


People also ask

How do you map multiple entities on the same table?

If you want to map the same database table to two entities, you should create a simple inheritance hierarchy. The superclass should be abstract and contain all attributes that are shared by both entities. You should map it as a mapped superclass so that it is not an entity itself.

How do you map an entity to multiple tables in hibernate?

Yes, you can map an entity to 2 database tables in 2 simple steps: You need to annotate your entity with JPA's @Table and @SecondaryTable annotations and provide the names of the first and second table as the value of the name parameters.

How do I join two entities in JPA?

The only way to join two unrelated entities with JPA 2.1 and Hibernate versions older than 5.1, is to create a cross join and reduce the cartesian product in the WHERE statement. This is harder to read and does not support outer joins. Hibernate 5.1 introduced explicit joins on unrelated entities.

How do you map entity and table?

In Spring Data JPA we can map an entity to a specific table by using @Table annotation where we can specify schema and name. But Spring Data JDBC uses a NamingStrategy to map an entity to a table name by converting the entities class name.


1 Answers

To summarize it, the following mappings are going to demonstrate how you can map multiple entities to the same database table:

@Entity(name = "Post")
public class Post {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;

    private String name;

    private String description;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}

@Entity(name = "PostSummary")
@Table(name = "Post")
@Immutable
public class PostSummary {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

@Entity(name = "UpdatablePostSummary")
@Table(name = "Post")
@DynamicUpdate
public class UpdatablePostSummary {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

And Hibernate will work just fine:

@Test
public void testOneTableMultipleEntities() {
    doInTransaction(session -> {
        Post post = (Post) session.get(Post.class, 1L);
        PostSummary postSummary = (PostSummary) session.get(PostSummary.class, 1L);
        UpdatablePostSummary updatablePostSummary = (UpdatablePostSummary) session.get(UpdatablePostSummary.class, 1L);
        assertEquals(post.getName(), postSummary.getName());
        assertEquals(post.getName(), updatablePostSummary.getName());
        updatablePostSummary.setName("Hibernate Master Class Tutorial.");
    });
}
  1. The PostSummary is just a read-only View over your original entity, hence I annotated it with @Immutable.

  2. The UpdatablePostSummary is marked with @DynamicUpdate and so you can propagate changes from this View entity too.

This test is also available on GitHub.

like image 126
Vlad Mihalcea Avatar answered Oct 19 '22 17:10

Vlad Mihalcea