如何简化两个相似方法的代码?

How to simplify the code of two similar methods?

我想重构这两种方法,除了“maxResult ()”外,它们几乎相同,这两种方法指的是两种不同的获取方式,一种是 returns 我是单个用户,另一种是 returns returns 改为列表。我怎样才能简化这两种方法(总是在有意义的情况下) 这些是 2 种方法:

第一种方法:

public List findFirstByTransactionId(String transactionId) {
        CriteriaBuilder builder = em.getCriteriaBuilder();
        CriteriaQuery<User> criteria = builder.createQuery(User.class);
        Root<User> root = criteria.from(User.class);
        criteria.select(root).where(builder.equal(root.get(User_.transactionId), transactionId));
        criteria.orderBy(builder.asc(root.get(User_.date)));
        TypedQuery<User> query = em.createQuery(criteria).setMaxResults(1);
         return query.getSingleResult();

第二种方法:

public List<User> findAllByTransactionId(String transactionId) {
        CriteriaBuilder builder = em.getCriteriaBuilder();
        CriteriaQuery<User> criteria = builder.createQuery(User.class);
        Root<User> root = criteria.from(User.class);
        criteria.select(root).where(builder.equal(root.get(User_.transactionId), transactionId));
        criteria.orderBy(builder.asc(root.get(User_.date)));
        TypedQuery<User> query = em.createQuery(criteria);
         return query.getResultList();

您在 query 上调用的方法与任何其他方法一样工作,因此您可以将一些调用放在 if 块中,如下所示:

public List<User> findByTransactionId(String transactionId, boolean onlyFirst) {
    CriteriaBuilder builder = em.getCriteriaBuilder();
    CriteriaQuery<User> criteria = builder.createQuery(User.class);
    Root<User> root = criteria.from(User.class);
    criteria.select(root).where(builder.equal(root.get(User_.transactionId), transactionId));
    criteria.orderBy(builder.asc(root.get(User_.date)));
    TypedQuery<User> query = em.createQuery(criteria);
    if (onlyFirst) {
      query=query.setMaxResults(1);
    }
    return query.getResultList();
}

嗯,最简单的选择通常是尝试将相同的代码移动到它自己的方法中。在这里,您有多种选择,其中之一可能是这样的:

  1. 写一个新的(私有)方法:
private List<User> findFirstByTransactionId(String transactionId, boolean onlyOneResult) {
    CriteriaBuilder builder = em.getCriteriaBuilder();
    CriteriaQuery<User> criteria = builder.createQuery(User.class);
    Root<User> root = criteria.from(User.class);

    criteria.select(root).where(builder.equal(root.get(User_.transactionId), transactionId));
    criteria.orderBy(builder.asc(root.get(User_.date)));
    TypedQuery<User> query = em.createQuery(criteria);

    if (onlyOneResult) {
        query = query.setMaxResults(1);
    }
    
    return query.getResultList();
}

然后像这样重构现有的方法:

public List<User> findFirstByTransactionId(String transactionId) {
    return findFirstByTransactionId(transactionId, false);
}
public List<User> findFirstByTransactionId(String transactionId) {
    return findFirstByTransactionId(transactionId, true);
}

现在您消除了 8 行重复代码:)

更多的是附录。

建议添加布尔参数的其他答案是有效的,但是:干净的编码建议始终争取最少的参数数量。尤其不鼓励使用此类布尔参数。当然,这样做还是有意义的,可以避免代码重复。

但我会怎么做:

  • 是的,内部有一个private List<User> findFirstByTransactionId()采用布尔参数
  • 但是在您的 public 界面上,只需提供两种不同的方法,例如 public List<User> findFirstUserByTransactionId() 和 `public List findUsersByTransactionId()``

这两个public方法可以调用内部方法并传递true/false。使用布尔值来做出该决定是一个实现细节,您应该避免在事物的 public 方面使其可见。