我有一个包含多个表的数据库以及表数据的相应对象。对于(几乎)所有表,我有一个Model类,它处理与其对应表的交互(添加记录,获取数据并实例化一个包含数据的对象。
所有Model类都有getById(int id)
方法,所以我认为把它放在超类(CoreModel)中会很好。
但是这里的事情: 由于Model类只是一种交互层,我认为在创建它的实例时没有用处。所以我认为我使类最终并且它的方法是静态的,但随后出现的问题是无法从静态方法调用super()方法。
我的问题:这通常是怎么做的?我对OOP不熟悉并且对整个多态性事情感到非常困惑。是否有任何设计模式或标准解决方案以通用方式解决此问题?
示例代码:
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;
}
}
答案 0 :(得分:2)
由于Model类只是一种交互层,我明白了 没有用于创建它的实例。所以我以为我上课了 final和它的方法是静态的,但问题就出现了 无法从静态方法调用super()方法。
首先,您的CoreModel
是final
类,并且您无法扩展final
中的PersonModel
类,并且您的代码将无法编译。
此外,将CoreModel
重命名为CoreDAO
& PersonModel
为PersonDAO
(实际上是数据访问对象),因为它们包含访问数据库表/连接/等的逻辑。 (称为DAO图层,对此图案看here)。
通常,Model对象(如Person
,Product
等等是带有getter / setter的普通数据类),它们不是单例,而是DAO对象(如PersonDAO
,{ {1}}等等。)是单身人士。
DAO图层类需要是singleton(整个应用程序的单线程安全实例),它只保存行为(即包含从数据库获取/存储数据的逻辑)。
是否有任何设计模式或标准解决方案可以解决这个问题 通用方式的问题?
为了避免样板代码从数据库加载对象(如CoreDAO
等),你可以实际使用 ORM(对象关系映射)框架(实现 JPA ),例如Hibernate,spring-data-jpa等。即,
这些框架将为您提供从持久存储加载/保存对象的API,而不用我们直接处理大量Person
和PreparedStatement
对象。
我建议你不需要重新编写/重写这个样板逻辑,而是直接使用JPA API。这里还有一点是,如果您使用JPA,那么您不会被锁定到单个ORM供应商,而是可以在供应商之间切换。
答案 1 :(得分:1)
你所问的是ORM。有几种用于创建ORM的设计模式,您可以阅读有关DataMapper或ActiveRecord的信息,以便更好地理解这个概念。
根据你的代码只获取一个Id并生成一个对象是不够的。你需要有一个可区分的Id,所以超类可以与不同的对象不同。
创建用于创建不同对象的超类的一种方法是工厂设计模式。
类似于以下代码:
//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();
}
}
}