Reputation: 643
I have a database with multiple tables and corresponding objects for the table's data. For (almost) all tables I have a Model class, which handle the interaction with it's corresponding table (adding records, fetching data and instantiate an object holding the data.
All Model classes have a getById(int id)
method, so I thought it would be nice to put it in a superclass (CoreModel).
But here the thing: Since the Model classes are just a sort of interaction layers, I see no use in creating an instance of it. So I thought I make the class final and it's methods static, but then the problem arises that super() methods cannot be called from static methods.
My question: How is this usually done? I'm sorta new to OOP and am pretty baffled by the whole polymorphism thing. Are there any design patterns or standard solutions to solve this problem in a generic way?
Example code:
public final class CoreModel {
public static ResultSet getById(int id, String table){
Statement stat = null;
ResultSet res = null;
try {
stat = DatabaseModel.getStatement();
res = stat.executeQuery("SELECT * FROM `"+table+"` WHERE `id` = " +id);
res.next();
stat.close();
res.close();
} catch (SQLException ex) {
// handle any errors
System.out.println("SQLException: " + ex.getMessage());
System.out.println("SQLState: " + ex.getSQLState());
System.out.println("VendorError: " + ex.getErrorCode());
}
return res;
}
}
public final class PersonModel extends CoreModel {
public static Person getById(int id) {
ResultSet personResult = super.getById(id, "person");
// instatiate Person object
return personObj;
}
}
Upvotes: 1
Views: 604
Reputation: 22442
Since the Model classes are just a sort of interaction layers, I see no use in creating an instance of it. So I thought I make the class final and it's methods static, but then the problem arises that super() methods cannot be called from static methods.
First thing is that your CoreModel
is final
class and you can't extend final
classes which you did in your PersonModel
and your code will not compile.
Also, it would be good to renameCoreModel
as CoreDAO
& PersonModel
as PersonDAO
(which are actually Data Access Objects) because they contain the logic to access database tables/connections/etc. (which is called as DAO layer, look here for this pattern).
In general, Model objects (like Person
, Product
, etc.. are plain data classes with getters/setters) which are NOT singletons whereas DAO objects (like PersonDAO
, CoreDAO
, etc..) are singletons.
DAO layer classes need to be singleton (single threadsafe instance for the whole application) which hold only behavior (i.e., contain logic fetching/storing data to/from the database).
Are there any design patterns or standard solutions to solve this problem in a generic way?
In order to avoid the boilerplate code to load the objects (like Person
, etc..) from database, you can actually use ORM (Object Relational Mapping) frameworks (implementation of JPA) like Hibernate, spring-data-jpa, etc.. i.e.,
these frameworks will provide you the API to load/save the objects from/to the persistent store without we directly dealing with lots of PreparedStatement
and ResultSet
objects.
I suggest you don't need to reinvent/rewriting this boilerplate logic, rather directly use the JPA API. One more point here is that if you use JPA, then you are NOT locked into single ORM vendor, rather you can have the portability to switch across the vendors.
Upvotes: 2
Reputation: 5240
What you are asking is called ORM. There are couple of design pattern for creating an ORM you can read about DataMapper or ActiveRecord to understand the concept better.
According to your code get only an Id and generating an object is not enough. you need to have a distinguishable Id so the super class can differ from different object.
One way to create a super class for create different object is Factory design pattern.
Something similar to following code :
//Character Class
public class Character implements Model {
public String age;
}
//Person Class
public class Person implements Model {
public String name;
}
//Model
public interface Model {
}
//CoreModel
public class CoreModel {
public static <T extends Model> T getById( int id) throws Exception {
int idType = id % 10; // the id has to be distinguishable
// get data from DB
switch (idType) {
case 0:
Person person = new Person();
person.name = "test";
return (T) Person.class.cast(person);
case 1:
Character character = new Character();
character.age = "100";
return (T) Character.class.cast(character);
default:
throw new Exception("Type Not Found");
}
}
}
//Main Class
public class Main {
public static void main(String[] args) {
try {
Person p = CoreModel.getById(100);
Character c = CoreModel.getById(101);
System.out.println(p.name);
System.out.println(c.age);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Upvotes: 1