Pergunta

Eu estou usando Spring JPA para executar todas as operações de banco de dados.No entanto, eu não sei como selecionar colunas específicas de uma tabela no Spring JPA?

Por exemplo:
SELECT projectId, projectName FROM projects

Foi útil?

Solução

Você pode definir nativeQuery = true no @Query anotação a partir de um Repository classe assim:

public static final String FIND_PROJECTS = "SELECT projectId, projectName FROM projects";

@Query(value = FIND_PROJECTS, nativeQuery = true)
public List<Object[]> findProjects();

Note que você terá para fazer o mapeamento-se embora.É provavelmente mais fácil apenas usar a regular mapeada de pesquisa como este, a menos que você realmente precisa apenas esses dois valores:

public List<Project> findAll()

É provavelmente vale a pena olhar a Primavera de dados docs bem.

Outras dicas

Você pode usar projeções de Spring Data JPA (doc).No seu caso, crie a interface:

interface ProjectIdAndName{
    String getId();
    String getName();
}

e adicione o seguinte método para o seu repositório

List<ProjectIdAndName> findAll();

Eu não gosto da sintaxe especial (parece um pouco hacky...), mas esta é a solução mais elegante que eu era capaz de encontrar (ele usa um costume consulta JPQL no JPA classe repositório):

@Query("select new com.foo.bar.entity.Document(d.docId, d.filename) from Document d where d.filterCol = ?1")
List<Document> findDocumentsForListing(String filterValue);

Em seguida, claro, você apenas tem que fornecer um construtor para Document que aceita docId & filename como construtor de args.

Na minha situação, eu só preciso de json resultado, e isso funciona para mim:

public interface SchoolRepository extends JpaRepository<School,Integer> {
    @Query("select s.id, s.name from School s")
    List<Object> getSchoolIdAndName();
}

no Controlador:

@Autowired
private SchoolRepository schoolRepository;

@ResponseBody
@RequestMapping("getschoolidandname.do")
public List<Object> getSchool() {
    List<Object> schools = schoolRepository.getSchoolIdAndName();
    return schools;
}

No meu caso eu criei uma entidade separada de classe, sem os campos que não são necessários (apenas com os campos que são necessários).

Mapa da entidade para a mesma tabela.Agora, quando todas as colunas são necessárias eu uso o velho da entidade, quando apenas algumas colunas são necessárias, eu uso o lite entidade.

exemplo:

@Entity
@Table(name = "user")
Class User{
         @Column(name = "id", unique=true, nullable=false)
         int id;
         @Column(name = "name", nullable=false)
         String name;
         @Column(name = "address", nullable=false)
         Address address;
}

Você pode criar algo como :

@Entity
@Table(name = "user")
Class UserLite{
         @Column(name = "id", unique=true, nullable=false)
         int id;
         @Column(name = "name", nullable=false)
         String name;
}

Isso funciona quando você sabe as colunas para buscar (e isso não vai mudar).

não vai funcionar se você precisa para escolher dinamicamente as colunas.

Eu acho que a maneira mais fácil é usando QueryDSL, que vem com a Primavera de Dados.

Usando a sua pergunta, a resposta pode ser

JPAQuery query = new JPAQuery(entityManager);
List<Tuple> result = query.from(projects).list(project.projectId, project.projectName);
for (Tuple row : result) {
 System.out.println("project ID " + row.get(project.projectId));
 System.out.println("project Name " + row.get(project.projectName)); 
}}

A entidade gestora pode ser Autowired e você sempre vai trabalhar com o objeto e clases sem uso *QL idioma.

Como você pode ver no link a última opção parece, quase para mim, o mais elegante, que é, usando um DTO para armazenar o resultado.Aplicar para o exemplo que será:

JPAQuery query = new JPAQuery(entityManager);
QProject project = QProject.project;
List<ProjectDTO> dtos = query.from(project).list(new QProjectDTO(project.projectId, project.projectName));

A definição de ProjectDTO como:

class ProjectDTO {

 private long id;
 private String name;
 @QueryProjection
 public ProjectDTO(long projectId, String projectName){
   this.id = projectId;
   this.name = projectName;
 }
 public String getProjectId(){ ... }
 public String getProjectName(){....}
}

Na minha opinião esta é uma grande solução:

interface PersonRepository extends Repository<Person, UUID> {

    <T> Collection<T> findByLastname(String lastname, Class<T> type);
}

e usando-o como

void someMethod(PersonRepository people) {

  Collection<Person> aggregates =
    people.findByLastname("Matthews", Person.class);

  Collection<NamesOnly> aggregates =
    people.findByLastname("Matthews", NamesOnly.class);
}

Com a mais recente Primavera versões pode-se fazer da seguinte forma:

Se não utilizar a consulta nativa isso pode feito como abaixo:

public interface ProjectMini {
    String getProjectId();
    String getProjectName();
}

public interface ProjectRepository extends JpaRepository<Project, String> { 
    @Query("SELECT p FROM Project p")
    List<ProjectMini> findAllProjectsMini();
}

Usando a consulta nativa o mesmo pode ser feito como abaixo:

public interface ProjectRepository extends JpaRepository<Project, String> { 
    @Query(value = "SELECT projectId, projectName FROM project", nativeQuery = true)
    List<ProjectMini> findAllProjectsMini();
}

Para detalhes, verifique o docs

Using Spring Data JPA there is a provision to select specific columns from database


---- In DAOImpl ----
@Override
    @Transactional
    public List<Employee> getAllEmployee() throws Exception {
    LOGGER.info("Inside getAllEmployee");
    List<Employee> empList = empRepo.getNameAndCityOnly();
    return empList;
    }

---- In Repo ----
public interface EmployeeRepository extends CrudRepository<Employee,Integer> {
    @Query("select e.name, e.city from Employee e" )
    List<Employee> getNameAndCityOnly();
}

It worked 100% in my case.
Thanks.

É possível especificar null como o valor do campo em sql nativo.

@Query(value = "select p.id, p.uid, p.title, null as documentation, p.ptype " +
            " from projects p " +
            "where p.uid = (:uid)" +
            "  and p.ptype = 'P'", nativeQuery = true)
Project findInfoByUid(@Param("uid") String uid);

Você pode aplicar o código abaixo em seu repositório de interface da classe.

entityname significa que seu banco de dados nome da tabela como projetos.E a Lista de meios Projeto é Entidade de classe em seus Projetos.

@Query(value="select p from #{#entityName} p where p.id=:projectId and p.projectName=:projectName")

List<Project> findAll(@Param("projectId") int projectId, @Param("projectName") String projectName);

Você pode usar JPQL:

TypedQuery <Object[]> query = em.createQuery(
  "SELECT p.projectId, p.projectName FROM projects AS p", Object[].class);

List<Object[]> results = query.getResultList();

ou você pode usar a consulta sql nativa.

Query query = em.createNativeQuery("sql statement");
List<Object[]> results = query.getResultList();

Usando Nativo De Consulta:

Query query = entityManager.createNativeQuery("SELECT projectId, projectName FROM projects");
List result = query.getResultList();

Você pode usar a resposta sugerida pelo @jombie, e:

  • colocar a interface em um arquivo separado, fora da entidade de classe;
  • use consulta nativa ou não (a escolha dependia de suas necessidades);
  • não substituir findAll() método para esse propósito, mas usar o nome de sua escolha;
  • lembre-se de voltar de uma List parametrizando com a sua nova interface (e.g. List<SmallProject>).
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top