Pregunta

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

¿Fue útil?

Solución

Puedes configurar nativeQuery = true en el @Query anotación de un 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 realizar el mapeo usted mismo.Probablemente sea más fácil usar la búsqueda asignada normal como esta, a menos que realmente solo necesite esos dos valores:

public List<Project> findAll()

Probablemente valga la pena mirar los datos de Spring. documentos también.

Otros consejos

Puede usar las proyecciones de Spring Data JPA (doc) .En su caso, cree interfaz:

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

y agregue el siguiente método a su repositorio

List<ProjectIdAndName> findAll();

No me gusta la sintaxis particularmente (se ve un poco hacky ...), pero esta es la solución más elegante que pude encontrar (utiliza una consulta de JPQL personalizada en la clase de repositorio de 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);

Luego, por supuesto, solo tiene que proporcionar un constructor para Document que acepte docId y filename como constructor args.

En mi situación, solo necesito el resultado de 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 controlador:

@Autowired
private SchoolRepository schoolRepository;

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

En mi caso, creé una clase de entidad separada sin los campos que no se requieren (solo con los campos que se requieren).

Mapa la entidad a la misma tabla. Ahora, cuando se requieren todas las columnas, utilizo la entidad antigua, cuando solo se requieren algunas columnas, utilizo la entidad Lite.

e.g.

@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 forma fácil puede estar usando QueryDSL, que viene con los datos de primavera.

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 entidades puede ser en vista de aprobación y siempre trabajará con objeto y clases sin usar * QL Idioma.

Como puede ver en el enlace, la última opción parece, casi para mí, más elegante, es decir, utilizando DTO para almacenar el resultado.Aplicar 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));

Definición 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(){....}
}

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);
}

Con las versiones más nuevas de la primavera, se puede hacer de la siguiente manera:

Si no está utilizando una consulta nativa, esto puede hacer lo siguiente:

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 verificar la 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.

Es posible especificar null como valor de campo en 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);

Puede aplicar el siguiente código en su clase de interfaz de repositorio.

EntityName significa su nombre de base de datos Nombre como proyectos. Y la lista significa que el proyecto es la clase de 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);

Puede 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();

usando la consulta nativa:

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

Puede utilizar la respuesta sugerida por @jombie y:

  • coloque la interfaz en un archivo separado, fuera de la clase de entidad;
  • utilizar consulta nativa o no (la elección dependía de sus necesidades);
  • no anular findAll() método para este propósito pero use el nombre de su elección;
  • recuerda devolver un List parametrizado con su nueva interfaz (p. ej. List<SmallProject>).
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top