Criteria Builder 和 Jquery DataTables - 自定义查询

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

附注。我显然已经为这些 DTO 声明了存储库、映射器和实体,我只是避免编写所有类,因为我觉得它没用。

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 从实体映射 dtos)。 如何在我的存储库和服务中使用条件构建器根据 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,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 仅适用于规范,我根本不了解。 我只是想创建一个类似于我在 repo 中的 public List 的方法,但返回的是 DataTablesOutput。

freepear 回答:Criteria Builder 和 Jquery DataTables - 自定义查询

  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)
,

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,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,query) ->
                // WHERE id > 0
                query.where(cb.gt(from.get("id"),0)));

        assertEquals(1,sezionis.get(0).getComune().getComCap());
    }

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

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

本文链接:https://www.f2er.com/33548.html

大家都在问