【问题标题】:Criteria Builder and Jquery DataTables - Custom queryCriteria Builder 和 Jquery DataTables - 自定义查询
【发布时间】:2021-10-02 16:14:56
【问题描述】:

我将 jquery 数据表与 Spring JPA 一起使用。 我想创建一个自定义查询,以便我的 Datatable 将根据 ManyToOne 相关对象的 id 显示项目列表。

PS。我显然已经为这些 DTO 声明了 Repositories、Mapper 和 Entities,我只是避免编写所有类,因为我发现它没用。

public class SezioniDTO {
    private static final long serialVersionUID = 1L;

    private long id;

    private LocalDate sezDtaggiornamento;


    private Comune Comune;


}

public class Comune {

    private static final long serialVersionUID = 1L;    

    private long id;

    private String comCap;

    private String comCodbelfiore;

    private String comCodcomune;





}

这些是我的类(我使用 mapstruct 从实体映射 dto)。 我如何在我的存储库和服务中使用标准构建器来根据 Comunes id 搜索 Sezionis?

我是 QueryDSL 和规范的新手,我只想获得这样的东西:

  @Query("Select * from Sezioni s WHERE s.id_Comune = :id", native="true")
   public DataTablesOutput <Object> findByField (@Param(value="id", input);

这是当前的服务实现

@Service
public class SezioniServiceImpl implements SezioniService{

    @Autowired
    SezioniRepository repo;
    @Autowired
    SezioniMapper mapper;
    
    @Autowired
    SezioniSpecifications sezSpec;
    
    @Override
    public List<SezioniDTO> findAll() {
        return repo.findAll().stream().map(x -> mapper.entityToDto(x, new CycleAvoidingMappingContext()))
                .collect(Collectors.toList());
    }
    
    @Override
    public List<SezioniDTO> findByIdComune(Long idcom){
        return repo.findSezionibyIdComune(idcom).stream().map(x -> mapper.entityToDto(x, new CycleAvoidingMappingContext()))
                .collect(Collectors.toList());
    }

    @Override
    public SezioniDTO save(SezioniDTO entity) {
        return null;
        
    }

    @Override
    public Optional<SezioniDTO> findById(Long id) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void delete(SezioniDTO entity) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void deleteById(Long id) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public long count() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public DataTablesOutput<SezioniDTO> getSezioniTable(@Valid DataTablesInput input) {
        return repo.findAll(input, null, null, a -> mapper.entityToDto(a, new CycleAvoidingMappingContext()) );
    }

    

}

以及 SezioniDTO 的当前存储库

@Repository
public interface SezioniRepository extends JpaRepository<Sezione,Long>, JpaSpecificationExecutor<Sezione>, DataTablesRepository<Sezione,Long> {

    @Query(value = "SELECT * FROM db.sezione WHERE sez_com_prg = :id  ORDER BY sez_numsezione", nativeQuery = true)
    public List <Sezione> findSezionibyIdCom(@Param(value = "id") Long id);

    

}

Sezione 是当前实体。如您所见,它 extends 和 DataTablesOutput 仅适用于 Specifications,我根本不了解。 我只是想创建一个类似于我在 repo 中的公共 List 的方法,但使用 DataTablesOutput 返回。

【问题讨论】:

    标签: java jquery datatables spring-data-jpa querydsl


    【解决方案1】:
    1. 定义实体:
    
        @Entity
        public class Sezioni {
            @Id
            @GeneratedValue(strategy = GenerationType.IDENTITY)
            private Long id;
            private LocalDate sezDtaggiornamento;
        
            @OneToOne(cascade = {CascadeType.ALL})
            @JoinColumn(name = "comune_id")
            private Comune Comune;
        
            // getters & setter are omitted
        }
    
    

    
        @Entity
        public class Comune {
            @Id
            @GeneratedValue(strategy = GenerationType.IDENTITY)
            private Long id;
            private String comCap;
            private String comCodbelfiore;
            private String comCodcomune;
        
            // getters & setter are omitted
        }
    
    
    1. 定义存储库
    
        @Repository
        public interface SezioniRepository extends JpaRepository<Sezioni, Long> {
        
            @Query("select s from Sezioni s where s.Comune.id = :id")
            List<Sezioni> findByComuneId(Long id);
        }
    
    1. 使用(测试中)
    
        @DataJpaTest
        class SezioniRepositoryTest {
            @Autowired
            SezioniRepository sezioniRepository;
        
            @BeforeEach
            void setUp() {
                Comune comune = new Comune();
                comune.setComCap("cap42");
                comune.setComCodcomune("cod43");
        
                Sezioni sezioni = new Sezioni();
                sezioni.setComune(comune);
                sezioni.setSezDtaggiornamento(LocalDate.of(1970, 1, 1));
        
                sezioniRepository.save(sezioni);
            }
        
            @Test
            void test() {
                List<Sezioni> sezionis = sezioniRepository.findByComuneId(1L);
                assertEquals(1, sezionis.size());
                assertEquals("cap42",sezionis.get(0).getComune().getComCap());
            }
        }
    
    
    1. 接下来,您可以使用 MapStruct 将实体映射到 DTO(如果您希望在 API 上公开 DTO)

    【讨论】:

    • 谢谢迈克尔。无论如何,我故意从问题中省略了实体、存储库和映射器,但我明白,如果不提及它,人们可能会认为我没有声明它们。我需要了解的是别的东西,我将 Spring 与 jquery 数据表一起使用,我根本不明白 Criteria Builder 和 QueryDSL 是如何工作的
    【解决方案2】:

    Criteria Builder 的优势在于根据您的业务登录需求动态构建查询

    考虑下一个例子:

        @Service
    public class SezioniQuery {
    
        @PersistenceContext
        private EntityManager entityManager;
    
        List<Sezioni> select(TriFunction<CriteriaBuilder, Root<Sezioni>, CriteriaQuery<Sezioni>, CriteriaQuery<Sezioni>> builder) {
            CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
            CriteriaQuery<Sezioni> query = criteriaBuilder.createQuery(Sezioni.class);
            // SQL FROM clause
            Root<Sezioni> from = query.from(Sezioni.class);
            // SQL SELECT clause
            CriteriaQuery<Sezioni> select = query.select(from);
    
            // build WHERE somewhere later
            CriteriaQuery<Sezioni> apply = builder.apply(criteriaBuilder, from, query);
    
            // execute
            TypedQuery<Sezioni> typedQuery = entityManager.createQuery(apply);
            return typedQuery.getResultList();
        }
    }
    

    ^^ 这里我们定义样板。

    接下来我们可以重用它来构建不同的查询:

        // @BeforeEach void setUp() {...} omitted see prev. answer
    
        @Test
        void testEqual() {
            Long id = 1L;
            List<Sezioni> sezionis = sezioniQuery.select((cb, from, query) ->
                    // WHERE id=1  
                    query.where(cb.equal(from.get("id"), id)));
    
            assertEquals(1, sezionis.size());
            assertEquals("cap42",sezionis.get(0).getComune().getComCap());
        }
    
        @Test
        void testGreater() {
            List<Sezioni> sezionis = sezioniQuery.select((cb, from, query) ->
                    // WHERE id > 0
                    query.where(cb.gt(from.get("id"), 0)));
    
            assertEquals(1, sezionis.size());
            assertEquals("cap42",sezionis.get(0).getComune().getComCap());
        }
    
    

    因此,使用 CriteriaBuilder 您可以动态构建查询,但这需要更多代码,非类型安全代码。

    而 JpaRepository 扩展是类型安全但非动态的

    【讨论】:

      猜你喜欢
      • 2020-06-08
      • 2017-07-20
      • 2019-04-01
      • 2017-03-26
      • 2019-07-11
      • 2020-10-06
      • 2015-05-16
      • 1970-01-01
      相关资源
      最近更新 更多