【问题标题】:Java make better use of inheritance and abstract classJava更好地利用继承和抽象类
【发布时间】:2020-08-29 12:50:53
【问题描述】:

我的项目中有以下结构。 我的问题是如何避免向抽象服务添加越来越多的查询?随着我不断添加模块,抽象服务中的代码行数会不断增加,我不希望这样。

public abstract class AbstractService < T, C > implements GenericService < T, C > {

    @Autowired
    private QueryReader queryReader;

    private String readQuery(String query) {
        return queryReader.getPropertyValue(query);
    }

    public String getOrdersQuery(List < Criteria> request) {
        return addConditionsToQuery(getOrdersQuery(), request);
    }

    public String getCustomersQuery(List < Criteria> request) {
        return addConditionsToQuery(getCustomersQuery(), request);
    }

    private String addConditionsToQuery(String sql, List < Criteria> conditions) {
        return QueryHelper.addConditionsToQuery(conditions, sql);
    }


    private String getOrdersQuery() {
        return readQuery("queries.orders.retrieve");
    }

    private String getCustomersQuery() {
        return readQuery("queries.customers.retrieve");
    }

    public String updateCustomerQuery() {
        return readQuery("queries.customer.update");
    }

}

通用服务是这样的 -

public interface GenericService<T,C> {

    void update(T t);

    void create(T t);

    T search(C t);
}

这是我的订单服务 -

@Service
public class OrderService extends AbstractService<OrderModel, List<Criteria>> {

    @Autowired
    private OrderRepository orderRepository;

    @Override
    public OrderModel search(List<Criteria> request) {
        String query = getOrdersQuery(request);
        List<OrderEntity> orderEntities = orderRepository.findByQuery(query);
        // entity dto conversion and so on
        // ....
        return orderModel;

    }
}

这是我的客户服务 -

@Service
public class CustomerService extends AbstractService < CustomerModel, List < Criteria >> {

    @Autowired
    private CustomerRepository customerRepository;

    @Override
    public CustomerModel search(List < Criteria > request) {
        String query = getCustomersQuery(request);
        List < CustomerEntity > customerEntities = customerRepository.findByQuery(request);
        // entity dto conversion and so on
        // ....
        return customerModel;

    }

    @Transactional
    @Override
    public void update(CustomerModel request) {
        // dto to entity conversion
        // .....
        // update entity with new values 
        customerRepository.update(orderEntity, updateCustomerQuery());
    }

}

【问题讨论】:

  • 为什么需要所有这些 getXQuery() getYQuery()?只需放置一个 getQuery(),并为实现 getQuery() 的每个 X、Y、.. 都有一个子类。您的抽象类不应该知道它的子类。
  • @Stultuske 我想将所有查询保存在一个地方,而不是在所有地方自动装配查询阅读器并将常见的东西保存在抽象类中
  • 继承并不是你保存通用代码的地方,而是一个将Person->Worker等通用专业元素分组的概念。你不应该仅仅因为它们有一个共同点而将它用于不相关的事物——你不想仅仅因为它们都有一个名称字段而做人扩展图形。使用组合它将解决您的问题
  • @Vishal_Kotecha 为什么要在子类中自动装配 QueryReader?你知道继承是做什么的吗?
  • @Stultuske 对不起,我听不懂。我在抽象类中自动装配了 QueryReader。如果还有其他更好的地方,请建议我。

标签: java oop inheritance interface abstract-class


【解决方案1】:

第一步,暴露两个受保护的方法:

  • addConditionsToQuery
  • 读取查询

并阅读所有“特定于服务”的方法。抽象类知道它的子类是没有意义的。


public abstract class AbstractService < T, C > implements GenericService < T, C > {

    @Autowired
    private QueryReader queryReader;

    protected String readQuery(String query) {
        return queryReader.getPropertyValue(query);
    }

    protected String addConditionsToQuery(String sql, List < Criteria> conditions) {
        return QueryHelper.addConditionsToQuery(conditions, sql);
    }
}

现在,例如OrdersService,应该知道应该从哪里解决它的查询

@Service
public class OrderService extends AbstractService<OrderModel, List<Criteria>> {

    @Autowired
    private OrderRepository orderRepository;

    @Override
    public OrderModel search(List<Criteria> request) {
        String sql = readQuery("queries.orders.retrieve"); 
        String query = addConditionsToQuery(sql, request);
        List<OrderEntity> orderEntities = orderRepository.findByQuery(query);
        // entity dto conversion and so on
        // ....
        return orderModel;

    }
}

仅此而已直接回答您的问题。

总而言之,既然我们在谈论 SQL,而您在这里有 spring,它可能不是一个教育项目,所以您可能可以考虑使用像 MyBatis 这样的 sql 管理库,这可能是一个很好的解决方案,因为它还管理文件中的 SQL 查询(代码外部),并为动态 SQL 查询生成提供模板引擎。

我提到 MyBatis 只是因为它在设计概念上与您在问题中提出的内容很接近。如果您不想处理 Hibernate/JPA/Spring Data(Jooq、jdbi 等等),还有其他选择。

【讨论】:

  • 这正是我发布此问题后所实现的
猜你喜欢
  • 1970-01-01
  • 2013-08-04
  • 1970-01-01
  • 2015-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多