在 DAO 模式中添加服务有什么好处?

Whats the benefit of adding Service in DAO pattern?

我正在设计我的 JSF 网络应用程序。我不想在我的 Beans classes 中包含业务逻辑代码。所以我决定使用 DAO 模式。现在 Beans 数据(修复数据)存储在 xml 文件中。现在我想为数据库扩展它并使用 Hibernate。

但是我不知道应该在我的服务中放入什么(如果有的话)class。

如果我有这个 DAO

public interface IRepairDao {

public Repairs fetchRepairs() throws RepairDaoException;
public Manufacturers fetchManufacturers() throws RepairDaoException;
public List<Model> fetchManufacturerModels(Manufacturer manufacturer) throws RepairDaoException;
public void saveRepairs(Repairs repairs) throws RepairDaoException;
}

例如这个 DAO 实现

public class RepairXmlDao implements IRepairDao {

private Serializer xmlSer;
private final String repairsXmlPath = "E:\WORK\Mariusz\repairs.xml";
private final String setupXmlPath = "E:\WORK\Mariusz\setup.xml";

@Override
public Repairs fetchRepairs() throws RepairDaoException {
    try {
        xmlSer = new Persister();
        InputStream fis = new FileInputStream(repairsXmlPath);
        BufferedReader in = new BufferedReader(
                new InputStreamReader(fis, Charset.forName("UTF-8")));
        String str = "", s;
        while((s = in.readLine()) != null)
            str += s;
        Repairs repairs = xmlSer.read(Repairs.class, str);
        return repairs;
    } catch(Exception e) {
        throw new RepairDaoXmlExcpetion("Thrown when fetching repairs from xml", e);
    }
}

@Override
public Manufacturers fetchManufacturers() throws RepairDaoException {
    try {
    xmlSer = new Persister();
    InputStream fis = new FileInputStream(setupXmlPath);
    BufferedReader in = new BufferedReader(
            new InputStreamReader(fis, Charset.forName("UTF-8")));
    String str = "", s;
    while((s = in.readLine()) != null)
        str += s;
    Manufacturers manufacturers = xmlSer.read(Manufacturers.class, str);
    //models = manufacturers.getManufacturers().get(0).getModels();
    return manufacturers;
    } catch(Exception e) {
        throw new RepairDaoXmlExcpetion("Thrown when fetching manufacturers from xml", e);
    }
}

@Override
public List<Model> fetchManufacturerModels(Manufacturer manufacturer) throws RepairDaoException {
    List<Model> models = new ArrayList<>();
    Manufacturers manufacturers = fetchManufacturers();
    for(Manufacturer m : manufacturers.getManufacturers()) {
        if(m.getName().equals(manufacturer.getName())) {
            models = m.getModels();
            break;
        }
    }
    return models;
}

@Override
public void saveRepairs(Repairs repairs) throws RepairDaoException {
    try {
        xmlSer = new Persister();
        File result = new File(repairsXmlPath);
        xmlSer.write(repairs, result);
    } catch(Exception e) {
        throw new RepairDaoXmlExcpetion("Thrown when saving repairs to xml", e);
    }
}

}

添加此服务给我的真正好处是什么?

public class RepairService {

private IRepairDao repairDao;

public Repairs fetchRepairs() throws RepairDaoException {
    return repairDao.fetchRepairs();
}

public Manufacturers fetchManufacturers() throws RepairDaoException {
    return repairDao.fetchManufacturers();
}

public List<Model> fetchManufacturerModels(Manufacturer manufacturer) 
        throws RepairDaoException {
    return repairDao.fetchManufacturerModels(manufacturer);
}

public void saveRepairs(Repairs repairs) throws RepairDaoException {
    repairDao.saveRepairs(repairs);
}
}

我看不到对我有任何真正的好处。尽管我确实看到了缺点,例如,如果我需要修改我的 DAO,我也将不得不修改我的服务。或者也许我的服务代码是错误的,它缺少一些重要的部分?感谢您提供任何提示或建议。

编辑

您是否建议创建服务层次结构,类似于我的 DAO 设计?

public abstract class ARepairService {

protected IRepairDao repairDao;

public ARepairService(IRepairDao repairDao) {
    this.repairDao = repairDao;
}

public abstract Repairs fetchRepairs() throws RepairDaoException;

public abstract Manufacturers fetchManufacturers() throws RepairDaoException;

public abstract List<Model> fetchManufacturerModels(Manufacturer manufacturer) 
        throws RepairDaoException;

public abstract void saveRepairs(Repairs repairs) throws RepairDaoException;
}

例如这个实现

public class RepairServiceXml extends ARepairService {

public RepairServiceXml(IRepairDao repairDao) {
    super(repairDao);
}

@Override
public Repairs fetchRepairs() throws RepairDaoException {
    return repairDao.fetchRepairs();
}

@Override
public Manufacturers fetchManufacturers() throws RepairDaoException {
    return repairDao.fetchManufacturers();
}

@Override
public List<Model> fetchManufacturerModels(Manufacturer manufacturer) 
        throws RepairDaoException {
    return repairDao.fetchManufacturerModels(manufacturer);
}

@Override
public void saveRepairs(Repairs repairs) throws RepairDaoException {
    repairDao.saveRepairs(repairs);
}
}

服务通常是指将 DAO 捆绑在一起以形成一些业务逻辑。假设您有这样的事情:

public interface CarService {
  public void repairCar(Car car);
}

在实施中,您必须从 ManufacturerDao 检索维修过的零件,更新汽车状态并最终向车主收费。例如

// skipped non-relevant parts(e.g. DAO injection) for brevity
public class CarServiceImpl implements CarService {

public ManufacturerDao manufacturerDao;
public BillingDao billingDao;
public CarDao carDao;

public void repairCar(Car car) {
    // get the car part
    Model model = car.getMissingPart();
    CarPart carPart = manufacturerDao.getNewCarPart(model);
    // install it and save the car
    car.installCarPart(carPart);
    car.setStatus(Status.REPAIRED);
    carDao.updateCar(car);
    // bill the owner
    billingDao.bill(car.getOwner());
}

}

整个 repairCar 必须是一笔交易。想象一下,如果你正在修车,而当你想给客户开账单时,你会得到一个例外!如果整件事情不在交易中,您将不得不向供应商支付固定汽车零件的费用,但是……您无法向客户开具账单。没有事务,业务逻辑和数据库状态都坏了。

这可能就是您看不到在 DAO 层之上添加服务层的价值的原因。您的业​​务逻辑非常简单,您的服务层只需将调用委托给 DAO 层即可。对于您的用例,您可以在没有服务层的情况下生活,直到您需要它。然而在现实世界中,业务逻辑不会那么微不足道,服务层是必须具备的。