Estou usando o Spring JPA para executar todas as operações do banco de dados. No entanto, não sei como selecionar colunas específicas de uma tabela no Spring JPA?
Por exemplo:
SELECT projectId, projectName FROM projects
Estou usando o Spring JPA para executar todas as operações do banco de dados. No entanto, não sei como selecionar colunas específicas de uma tabela no Spring JPA?
Por exemplo:
SELECT projectId, projectName FROM projects
Respostas:
Você pode definir nativeQuery = true
a @Query
anotação de uma Repository
classe como esta:
public static final String FIND_PROJECTS = "SELECT projectId, projectName FROM projects";
@Query(value = FIND_PROJECTS, nativeQuery = true)
public List<Object[]> findProjects();
Observe que você terá que fazer o mapeamento sozinho. Provavelmente é mais fácil usar a pesquisa mapeada regular como esta, a menos que você realmente precise apenas desses dois valores:
public List<Project> findAll()
Provavelmente vale a pena examinar também os documentos de dados do Spring .
FIND_PROJECTS
) com o value
nome do atributo (portanto, se este foi o meu código que eu teria que escrevê-lo como @Query(value = FIND_PROJECTS, nativeQuery = true)
, etc.
Você pode usar projeções do Spring Data JPA (doc) . No seu caso, crie uma interface:
interface ProjectIdAndName{
String getId();
String getName();
}
e adicione o seguinte método ao seu repositório
List<ProjectIdAndName> findAll();
Não gosto particularmente da sintaxe (parece um pouco hacky ...), mas esta é a solução mais elegante que consegui encontrar (ela usa uma consulta JPQL personalizada na classe de repositório JPA):
@Query("select new com.foo.bar.entity.Document(d.docId, d.filename) from Document d where d.filterCol = ?1")
List<Document> findDocumentsForListing(String filterValue);
Então, é claro, você apenas precisa fornecer um construtor para Document
que aceite docId
& filename
como construtor args.
Na minha situação, eu só preciso do resultado json, 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;
}
Object
por uma interface personalizada, conforme descrito por mpr. funciona perfeitamente
No meu caso, criei uma classe de entidade separada sem os campos que não são obrigatórios (apenas com os campos necessários).
Mapeie a entidade para a mesma tabela. Agora, quando todas as colunas são necessárias, eu uso a entidade antiga, quando apenas algumas colunas são necessárias, eu uso a entidade lite.
por 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 que as colunas devem ser buscadas (e isso não vai mudar).
não funcionará se você precisar decidir dinamicamente as colunas.
Eu acho que a maneira mais fácil pode ser usar QueryDSL , que vem com o Spring-Data.
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));
}}
O gerente da entidade pode ser conectado automaticamente e você sempre trabalhará com objetos e classes sem usar a linguagem * QL.
Como você pode ver no link, a última opção parece, quase para mim, mais elegante, ou seja, usar o DTO para armazenar o resultado. Aplique ao seu 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));
Definindo o 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(){....}
}
Com as versões mais recentes do Spring, é possível fazer o seguinte:
Se não estiver usando a consulta nativa, isso pode ser feito da seguinte maneira:
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 os documentos
Na minha opinião, esta é uma ótima solução:
interface PersonRepository extends Repository<Person, UUID> {
<T> Collection<T> findByLastname(String lastname, Class<T> type);
}
e usá-lo assim
void someMethod(PersonRepository people) {
Collection<Person> aggregates =
people.findByLastname("Matthews", Person.class);
Collection<NamesOnly> aggregates =
people.findByLastname("Matthews", NamesOnly.class);
}
Usando o Spring Data JPA, existe uma disposição para selecionar colunas específicas do banco de dados
---- No DAOImpl ----
@Override
@Transactional
public List<Employee> getAllEmployee() throws Exception {
LOGGER.info("Inside getAllEmployee");
List<Employee> empList = empRepo.getNameAndCityOnly();
return empList;
}
---- No Repo ----
public interface EmployeeRepository extends CrudRepository<Employee,Integer> {
@Query("select e.name, e.city from Employee e" )
List<Employee> getNameAndCityOnly();
}
Funcionou 100% no meu caso. Obrigado.
Você pode usar o 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();
Você pode aplicar o código abaixo na sua classe de interface de repositório.
entityname significa o nome da tabela do banco de dados como projetos. E Lista significa que Projeto é a classe Entidade 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);
Usando consulta nativa:
Query query = entityManager.createNativeQuery("SELECT projectId, projectName FROM projects");
List result = query.getResultList();
Você pode usar a resposta sugerida por @jombie e:
findAll()
método para esse fim, mas use o nome de sua escolha;List
parametrizado com sua nova interface (por exemplo List<SmallProject>
).