java - Spring Boot - 如何创建不同 JpaRepository 接口(interface)的工厂

标签 java spring-boot spring-data-jpa

我有一个服务层,可以像这样 Autowiring 存储库

@Service
public class OrderService {

    @Autowired
    private OrderRepository repository;

    public List<Order> retrieveOrders(String storeId) {
        try {

            return repository.getOrders(storeId)

        } catch(Exception e) {
            ...
        }
    }
}

我有一个新的要求,根据商店编号,存储库查询逻辑应该改变。我正在考虑抽象我的存储库并使用工厂模式。当前存储库是一个接口(interface)并扩展了 JpaRepository;此外,它的所有功能都使用@Query注释来定义JPQL。这是一个只有一个函数的示例,但我的实际存储库中有多个函数

public interface OrderRepository extends JpaRepository {

    @Query("select o " +
        " from Orders o " +
        " where o.storeId = :storeId")
    public List<Order> getOrders(@Param(value = "storeId") String storeId);

}

新要求规定,对于特定的 storeId,SQL 需要更改为如下内容:

public interface OrderRepositoryStore886 extends JpaRepository {

    @Query("select o " +
        " from Order o " +
        " where o.storeId = :storeId " +
        "     and o.status IN (1,3,10,15) " +
        "     and EXISTS (SELECT c from CollabOrder WHERE c.orderId = o.orderId)")
    public List<Order> getOrders(@Param(value = "storeId") String storeId);

}

但是,所有剩余的存储都应使用第一个 SQL 查询。

我试图弄清楚如何根据 storeId 有条件地 @Autowire 存储库。我正在考虑创建一个工厂,但我不知道如何创建一个返回接口(interface)对象的工厂(我对java还很陌生,这可能很简单,但我还没有弄清楚)。如果我尝试将 Repository 接口(interface)转换为类,它会迫使我重写所有抽象 JpaRepository 方法,这是不必要的额外代码。

最佳答案

您已经走在正确的道路上了。我会解决这个问题,但创建一个返回正确 bean 接口(interface)的工厂方法。

此方法的唯一缺点是您无法 Autowiring bean。您应该即时实例化它们。

create table orders
(
  id                      integer      not null,
  constraint pk_orders primary key(id)
);

@Entity
@Table(name = "orders")
@ToString
@Getter
@Setter
public class Order {

    @Id
    private long id;
}


public interface OrderRepository extends JpaRepository<Order, Long> {
    @Query("SELECT t FROM Order t")
    Order getOrder(String storeId);
}


@Repository
public interface OrderRepositoryStore100 extends OrderRepository {
    @Query("SELECT t FROM Order t WHERE t.id = 100")
    Order getOrder(@Param(value = "id") String storeId);
}

@Repository
public interface OrderRepositoryStore286 extends OrderRepository {
    @Query("SELECT t FROM Order t WHERE t.id = 286")
    Order getOrder(@Param(value = "id") String storeId);
}

public class OrderRepositoryStoreFactory {

    private static final String REPOSITORY_BASE_NAME = "orderRepositoryStore";

    public static OrderRepository getRepository(ApplicationContext context, String storeId) {

        return (OrderRepository) context.getBean(REPOSITORY_BASE_NAME + storeId);
    }
}

@Service
public class OrderService {

    @Autowired
    private ApplicationContext context;

    public Order retrieveOrders(String storeId) {
        try {

            OrderRepository repository = OrderRepositoryStoreFactory.getRepository(context, storeId);

            return repository.getOrder(storeId);

        } catch(Exception e) {
            return null;
        }
    }
}



@SpringBootApplication
public class FactoryApplication implements CommandLineRunner {

    @Autowired
    private ApplicationContext context;

    @Autowired
    private OrderService orderService;

    public static void main(String[] args) {
        SpringApplication.run(FactoryApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        Order order = orderService.retrieveOrders("100");
        System.out.println(order);

        order = orderService.retrieveOrders("286");
        System.out.println(order);
    }
}

这是输出:

2020-05-03 20:23:34.567 INFO 33955 --- [ main] com.factory.FactoryApplication :在 3.003 秒内启动 FactoryApplication (JVM 运行了 3.615 秒) 订单(id=100) 订单(id=286)

希望这有帮助

关于java - Spring Boot - 如何创建不同 JpaRepository 接口(interface)的工厂,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61576238/

相关文章:

java - 如何计算一个月中有多少个工作日?

java - Eclipse - 在 Debug模式下运行失败

java - Spring CrudRepository 在自定义查询方法定义上抛出 AbstractMethodError

java - 如何摆脱 Spring Boot 中的 JpaRepository 接口(interface)

java - @Query 不接受 LIKE 来执行细粒度搜索

java - Android RSS Xml 错误

C# 迭代字符数组非常慢

java - 使用 libopencore-amr 支持为 ARM 构建 ffmpeg

java - 使用 Postgresql 对 Spring Boot 应用进行 Docker 化

java - Swagger-ui.html 不显示 api 列表