有效地使用多个相似的类执行CRUD操作



我有一个抽象类,我们将其称为Vehicle。柴油类, ,和气体扩展车辆。这三个类都有自己的方法和变量,以及它们从Vehicle继承的内容。

我想把DieselElectricGas对象中的变量放入数据库中的同一表中。从Electric对象创建的记录只会有几个空列,其中不包含与Diesel对象相同的变量,等等。

我想创建方法来插入行、更新行和检索行,所有这些方法都接受来自这些类的对象作为参数。

我正在寻找这个问题的最佳解决方案,因为我想我不知道它是什么。到目前为止,我能想到一些解决方案,但我不喜欢任何一个:
  1. 创建以下4个方法:插入、更新、删除和检索/选择。这将导致大量重复代码。

    public void AddVehicle(Diesel diesel)
    public void AddVehicle(Electric electric)
    public void AddVehicle(Gas gas)
    public Electric ViewVehicles()
    public Diesel ViewVehicle()
    public Gas ViewVehicle()
    public void RemoveVehicle(Diesel diesel)
    public void RemoveVehicle(Electric electric)
    public void RemoveVehicle(Gas gas)
    public void UpdateVehicle(Diesel diesel)
    public void UpdateVehicle(Electric electric)
    public void UpdateVehicle(Gas gas)
    
  2. 创建每个方法,以便它可以接受任何对象:(而不是接受任何对象,是否有一种方法来指定它可以接受的对象列表,但仍然只接受其中一个?ie。public void AddVehicle (Diesel Diesel || Electric Electric || Gas Gas))

    public void AddVehicle(Object vehicle)
    public Object ViewVehicle(Object vehicle)
    public void RemoveVehicle(Object vehicle)
    public void UpdateVehicle(Object vehicle)
    
  3. 创建一个"主"类,可以包含任何类 (Diesel, Electric或Gas),然后将其传递到插入/更新/视图/删除方法中。(将insert/update/view方法设置为接受这个"主"类作为参数。)"master"类的不完整构造函数:

    public MasterVehicle(Diesel diesel)
    public MasterVehicle(Electric electric)
    public MasterVehicle(Gas gas)
    
  4. 其他更合适,更干净,更有意义的解决方案

但是#4可能是什么?

关于您的选项两个:首先,您可以使用Vehicle来代替Object,只要DieselElectricGas实现/扩展Vehicle。它应该能完成任务。

另外,选项2中的ViewVehicle:

public Object ViewVehicle(Object vehicle)

可以使用泛型方法,这样它总是返回与它进入的类型相同的类型。更多信息请访问:http://docs.oracle.com/javase/tutorial/extra/generics/methods.html...虽然我不清楚为什么你试图发送一个对象到一个方法,然后从该方法返回。

泛型DAO可能是您感兴趣的。尽量避免写冗长的答案,下面是链接。j-genericdao

你可以在网上找到很多变种的泛型dao

幸运的是,其他人也不得不处理这个问题:)

这里实际上有两个问题。一个是您已经确定的API的设计,另一个是如何处理实际的存储/读取数据库。

对于第一个问题,我选择你的选项#2,因为它最好地遵循了OO设计原则。但我不会让方法接受Object。相反,让它接受Vehicle类型。

对于第二个问题,您可以查看以下链接:实体继承映射策略。即使您不打算使用JPA(或任何ORM框架),这些也可能是您想要查看的策略。

下面是对上面链接中提到的单表策略的更详细的解释。这应该给你一个很好的想法——> Inheritance: Single Table Strategy

正如你在问题开头所说:

我有一个抽象类,我们将其称为Vehicle。类别柴油、电动、燃气实施车辆。

Vehicle是超类,Diesel, Electric和Gas是专门化。

数据库上的表可以反映这种布局

Vehicle (id, brand, price, type) // type could help you selecting electric,gas,diesel
Electric(vehicle_id, volts, amp, ohms, other_specific_stuff)
Gas(vehicle_id, pressure, gas_type, other_specific_stuff) 
Diesel(vehicle_id, other_specific_stuff) 

当你查询你的车辆时,你可以使用左外连接

select * from vehicle as v
    left outer join electric as e on (v.id = e.vehicle_id)
    left outer join gas as g on (v.id = g.vehicle_id)
    left outer join diesel as d on (v.id = d.vehicle_id)

然后使用type字段映射到特定的子类。

当您在数据库中存储或更新对象时,您需要一个方法来存储公共部分:

void update(Vehicle v) { 
    // store v.* in Vehicle table
}

和存储特定汽车

的其余部分的方法
void update(Electric e) {
    update(v)
    // store e.* on Electric table
}

删除和插入也是一样

我建议将持久层(关系数据库)与面向对象模型层(Java)解耦,忘记"CRUD"操作,更多地考虑对象行为

有一个类Garage实现Vehicles的集合会很好:

interface Garage extends Collection<? extends Vehicle> {
  Vehicle find(int id);
}

然后,你可以这样使用:

Garage garage = new GarageInSql(/* your persistence layer details */);
Electric vehicle = Electric.class.cast(garage.find(123));
int mileage = vehicle.mileage();
vehicle.rename("Chevrolet");
garage.remove(vehicle);

如果你需要控制事务引入一个方法Garage#commit() .

最新更新