'How to make generic class to use JPARepository for multiple entities

Scenario: An application has multiple Entities. Each Entity denotes a Database table. All the database table does have an primary key column but the column name differs.

Example of an Entity:

@Entity
@Table(name = "ABC",schema = "XYZ" )
public class SaveData extends EntityClass {

    @Id
    @Column(name = "ABC_ID", nullable = false, insertable = true, updatable = true, precision = 0)
    private int id;

    @Column(name = "ABC1_ID", nullable = false, insertable = true, updatable = true, precision = 0)
    private int abc1_id;

    @Column(name = "DATA", nullable = true, insertable = true, updatable = true, precision = 0)
    private String data;

   //Getter - Setter methods of the above member variables.

}

EntityClass is like a generic class. This abstract class will be extended by all the Entity Classes.

@MappedSuperclass
public abstract class EntityClass {

    @Id
    private int id;
}

The app have a Dao interface as:

@Repository
public interface DaoRepos extends JpaRepository<EntityClass,Long> {

}

Example of Service Class:

@Component
public class ServiceMethodsImpl implements ServiceMethods {

    @Autowired
    private DaoRepos daoRepos ;

    @Override
    public void saveDatainDB(SaveData saveData ) {
        daoRepos.save(saveData);
    }

}

Problem: If I declare the dao interface like below:

@Repository
public interface ReviewRepos extends JpaRepository<SaveData,Long> {

}

Sending the argument as SaveData in the JPARepository, then my saveDatainDB method in the service class functions fine.

Now that is only for saving data of an Entity. Same way, there are other entities present and the same saving feature needs to be applied. So I thought of creating a generic class that will represent all the entities (in this example EntityClass). The class will be sent as an argument to JPARepository so that at run time, we can override the EntityClass with child class (for example SaveData)

But Spring does not allow to create the Class EntityClass without @Id column. So I had to declare a ID column. Also in my database, every table have a primary column but the names of that column of all tables are different. For example, Table XYZ will have a primary column xyz_id Table ABC will have a primary column abc_id

So I had to define an ID column in the child class entity SaveData with a @Column annotation.

Now when I try to save, a separate id column gets created apart from the id column that exists in SaveData class. This extra id creates error as unrecognized column.

Also, I am interested to know if my approach is correct.



Solution 1:[1]

For legacy systems it is possible to override id column name using @AttributeOverride annotation.

@Entity
@AttributeOverride(name="id", column=@Column(name="ABC_ID"))
@Table(name = "ABC",schema = "XYZ" )
public class SaveData extends EntityClass {

    @Column(name = "ABC1_ID", nullable = false, insertable = true, updatable = true, precision = 0)
    private int abc1_id;

    @Column(name = "DATA", nullable = true, insertable = true, updatable = true, precision = 0)
    private String data;    
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Peter Šály