Estoy usando Spring JPA para realizar todas las operaciones de la base de datos. Sin embargo, no sé cómo seleccionar columnas específicas de una tabla en Spring JPA.
Por ejemplo:
SELECT projectId, projectName FROM projects
Estoy usando Spring JPA para realizar todas las operaciones de la base de datos. Sin embargo, no sé cómo seleccionar columnas específicas de una tabla en Spring JPA.
Por ejemplo:
SELECT projectId, projectName FROM projects
Respuestas:
Puede establecer nativeQuery = true
la @Query
anotación de una Repository
clase como esta:
public static final String FIND_PROJECTS = "SELECT projectId, projectName FROM projects";
@Query(value = FIND_PROJECTS, nativeQuery = true)
public List<Object[]> findProjects();
Tenga en cuenta que tendrá que hacer el mapeo usted mismo. Probablemente sea más fácil usar la búsqueda asignada regular como esta, a menos que realmente solo necesite esos dos valores:
public List<Project> findAll()
Probablemente también valga la pena mirar los documentos de datos de Spring .
FIND_PROJECTS
) con el value
nombre del atributo (por lo tanto si se trataba de mi código que habría tenido que escribir como @Query(value = FIND_PROJECTS, nativeQuery = true)
, etc
Puede usar proyecciones de Spring Data JPA (doc) . En su caso, cree la interfaz:
interface ProjectIdAndName{
String getId();
String getName();
}
y agregue el siguiente método a su repositorio
List<ProjectIdAndName> findAll();
No me gusta la sintaxis en particular (parece un poco hacky ...) pero esta es la solución más elegante que pude encontrar (utiliza una consulta JPQL personalizada en la clase de repositorio 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);
Entonces, por supuesto, solo tiene que proporcionar un constructor Document
que acepte docId
& filename
como argumentos de constructor.
En mi situación, solo necesito el resultado json, y esto funciona para mí:
public interface SchoolRepository extends JpaRepository<School,Integer> {
@Query("select s.id, s.name from School s")
List<Object> getSchoolIdAndName();
}
en el controlador:
@Autowired
private SchoolRepository schoolRepository;
@ResponseBody
@RequestMapping("getschoolidandname.do")
public List<Object> getSchool() {
List<Object> schools = schoolRepository.getSchoolIdAndName();
return schools;
}
Object
por una interfaz personalizada como la describe mpr. funciona a la perfección
En mi caso, creé una clase de entidad separada sin los campos que no son obligatorios (solo con los campos que son obligatorios).
Asigne la entidad a la misma tabla. Ahora, cuando se requieren todas las columnas, uso la entidad anterior, cuando solo se requieren algunas columnas, uso la entidad lite.
p.ej
@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;
}
Puedes crear algo como:
@Entity
@Table(name = "user")
Class UserLite{
@Column(name = "id", unique=true, nullable=false)
int id;
@Column(name = "name", nullable=false)
String name;
}
Esto funciona cuando conoce las columnas para buscar (y esto no va a cambiar).
no funcionará si necesita decidir dinámicamente las columnas.
Supongo que la manera más fácil es usar QueryDSL , que viene con Spring-Data.
Usando su pregunta, la respuesta puede 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));
}}
El administrador de la entidad puede ser Autowired y siempre trabajará con objetos y clases sin usar * lenguaje QL.
Como puede ver en el enlace, la última opción parece, casi para mí, más elegante, es decir, usar DTO para almacenar el resultado. Aplique a su ejemplo que será:
JPAQuery query = new JPAQuery(entityManager);
QProject project = QProject.project;
List<ProjectDTO> dtos = query.from(project).list(new QProjectDTO(project.projectId, project.projectName));
Definiendo 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(){....}
}
Con las versiones Spring más recientes, se puede hacer lo siguiente:
Si no utiliza la consulta nativa, puede hacerlo de la siguiente manera:
public interface ProjectMini {
String getProjectId();
String getProjectName();
}
public interface ProjectRepository extends JpaRepository<Project, String> {
@Query("SELECT p FROM Project p")
List<ProjectMini> findAllProjectsMini();
}
Usando la consulta nativa, lo mismo se puede hacer de la siguiente manera:
public interface ProjectRepository extends JpaRepository<Project, String> {
@Query(value = "SELECT projectId, projectName FROM project", nativeQuery = true)
List<ProjectMini> findAllProjectsMini();
}
Para más detalles, consulte los documentos
En mi opinión, esta es una gran solución:
interface PersonRepository extends Repository<Person, UUID> {
<T> Collection<T> findByLastname(String lastname, Class<T> type);
}
y usándolo así
void someMethod(PersonRepository people) {
Collection<Person> aggregates =
people.findByLastname("Matthews", Person.class);
Collection<NamesOnly> aggregates =
people.findByLastname("Matthews", NamesOnly.class);
}
Usando Spring Data JPA hay una disposición para seleccionar columnas específicas de la base de datos
---- En DAOImpl ----
@Override
@Transactional
public List<Employee> getAllEmployee() throws Exception {
LOGGER.info("Inside getAllEmployee");
List<Employee> empList = empRepo.getNameAndCityOnly();
return empList;
}
---- En Repo ----
public interface EmployeeRepository extends CrudRepository<Employee,Integer> {
@Query("select e.name, e.city from Employee e" )
List<Employee> getNameAndCityOnly();
}
Funcionó al 100% en mi caso. Gracias.
Puedes usar JPQL:
TypedQuery <Object[]> query = em.createQuery(
"SELECT p.projectId, p.projectName FROM projects AS p", Object[].class);
List<Object[]> results = query.getResultList();
o puede usar la consulta SQL nativa.
Query query = em.createNativeQuery("sql statement");
List<Object[]> results = query.getResultList();
Puede aplicar el siguiente código en su clase de interfaz de repositorio.
nombre de entidad significa el nombre de la tabla de la base de datos como proyectos. Y Lista significa que Proyecto es la clase Entidad en sus Proyectos.
@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 la consulta nativa:
Query query = entityManager.createNativeQuery("SELECT projectId, projectName FROM projects");
List result = query.getResultList();
Puede usar la respuesta sugerida por @jombie y:
findAll()
método para este propósito, pero use el nombre de su elección;List
parametrizado con su nueva interfaz (por ejemplo List<SmallProject>
).