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

时间:2012-12-24 01:28:51

标签: java oop optimization

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

我想将 Diesel Electric Gas 对象中的变量放入同一个表中一个数据库。从 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. 创建每个方法以便它可以接受任何对象:(而不是使用任何对象,有没有办法指定它的对象列表可以采取,但仍然只采取其中之一?即。 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. 创建一个“主”类,可以包含任何类(柴油,电气或气体),然后将其传递给insert / update / view / delete方法。 (将insert / update / view方法设置为接受此“master”类作为参数。)“master”类的不完整构造函数:

    public MasterVehicle(Diesel diesel)
    public MasterVehicle(Electric electric)
    public MasterVehicle(Gas gas)
    
  4. 其他一些正确,清洁,更有意义的解决方案。

  5. 但是#4可能是什么?

5 个答案:

答案 0 :(得分:1)

关于您的选项两个: 首先,只要柴油电气气体,您就可以拥有车辆而不是对象 实施/扩展广告。 它应该完成这项工作。

此外,对于选项二中的ViewVehicle:

  

public Object ViewVehicle(Object vehicle)

您可以使用泛型方法,以便始终返回与其相同的类型。 更多信息:http://docs.oracle.com/javase/tutorial/extra/generics/methods.html ...虽然我不清楚为什么你试图将一个对象发送到一个从该方法返回的方法。

答案 1 :(得分:1)

正如你在问题开头所说:

  

我有一个抽象类,我们称之为Vehicle。类柴油,电力和燃气实施车辆。

因此,车辆是超级舱,柴油,电力和燃气是专业化。

db上的表可以反映这种布局

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
}

删除和插入也是一样。

答案 2 :(得分:1)

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

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

至于第一个问题,我会选择#2选项,因为它最符合OO设计原则。但我不会让方法接受Object。相反,让它接受Vehicle类型。

对于第二个问题,您可以查看以下链接:Entity Inheritance Mapping Strategies。即使您不打算使用JPA(或任何ORM框架),这些可能是您想要查看的策略。

以下是上述链接中提到的单表策略的更详细说明。这应该给你一个好主意 - > Inheritance: Single Table Strategy

答案 3 :(得分:1)

Generic DAO是您可能感兴趣的内容。尽量避免编写长答案,所以这里是链接。 j-genericdao

你可以在网上找到很多通用dao的变种。

答案 4 :(得分:1)

我建议将持久层(关系数据库)与面向对象的模型层(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()会更好。

{{1}}

然后,您可以像:

一样使用它
{{1}}

如果您需要控制交易,请引入另一种方法{{1}}。

相关问题