Spring JPA wybór konkretnych kolumn

Używam Spring JPA do wykonywania wszystkich operacji bazodanowych. Jednak nie wiem, jak wybrać konkretne kolumny z tabeli na wiosnę JPA?

Na przykład:
SELECT projectId, projectName FROM projects

Author: ElGavilan, 2014-02-25

12 answers

Możesz ustawić nativeQuery = true w adnotacji @Query z klasy Repository w następujący sposób:

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

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

Zauważ, że będziesz musiał zrobić mapowanie samodzielnie. Prawdopodobnie łatwiej jest po prostu użyć zwykłego wyszukiwania mapowanego w ten sposób, chyba że naprawdę potrzebujesz tylko tych dwóch wartości:

public List<Project> findAll()

Warto też przyjrzeć się źródłowym danym docs.

 42
Author: Durandal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-19 18:34:17

Nie podoba mi się składnia szczególnie (wygląda trochę chwiejnie...), ale jest to najbardziej eleganckie rozwiązanie, jakie udało mi się znaleźć (używa niestandardowego zapytania JPQL w klasie repozytorium 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);

Wtedy, oczywiście, wystarczy podać konstruktor dla dokumentu, który akceptuje docId & filename jako konstruktor args.

 95
Author: jm0,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-12 21:34:23

Możesz użyć prognoz z danych źródłowych JPA (doc). W Twoim przypadku utwórz interfejs:

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

I dodaj następującą metodę do repozytorium

List<ProjectIdAndName> findAll();
 68
Author: mpr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-02 14:07:56

W moim przypadku utworzyłem osobną klasę encji bez pól, które nie są wymagane (tylko z polami, które są wymagane).

Mapuj obiekt do tej samej tabeli. Teraz, gdy wszystkie kolumny są wymagane, używam starego encji, gdy tylko niektóre kolumny są wymagane, używam encji lite.

Np.

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

Możesz utworzyć coś w stylu:

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

To działa, gdy znasz kolumny do pobrania(i to się nie zmieni).

Nie zadziała, jeśli trzeba dynamicznie decydować o kolumnach.

 11
Author: Sachin Sharma,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-07 10:50:43

W mojej sytuacji potrzebuję tylko wyniku json, a to działa dla mnie:

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

In Controller:

@Autowired
private SchoolRepository schoolRepository;

@ResponseBody
@RequestMapping("getschoolidandname.do")
public List<Object> getSchool() {
    List<Object> schools = schoolRepository.getSchoolIdAndName();
    return schools;
}
 11
Author: Atal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-10 23:19:05

Myślę, że łatwym sposobem może być użycie QueryDSL , które pochodzi z Spring-Data.

Używając do twojego pytania odpowiedź może być

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

Menedżer encji może być Autowirowany i zawsze będziesz pracować z obiektami i klasami bez użycia języka *QL.

Jak widać w linku ostatni wybór wydaje się, prawie dla mnie, bardziej elegancki, czyli używanie DTO do przechowywania wyniku. Zastosuj do swojego przykładu, który będzie:

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

Definiowanie ProjectDTO jako:

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(){....}
}
 7
Author: kszosze,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-15 08:49:31

Można określić null jako wartość pola w natywnym sql.

@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);
 3
Author: hahn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-08 19:36:12
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.
 2
Author: SR Ranjan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-20 07:51:24

Możesz zastosować poniższy kod w klasie interfejsu repozytorium.

Entityname oznacza nazwę tabeli bazy danych, podobnie jak projekty. A lista oznacza, że projekt jest klasą encji w twoich projektach.

@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);
 2
Author: ajaz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-12 10:59:42

Możesz użyć JPQL:

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

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

Lub możesz użyć natywnego zapytania sql.

Query query = em.createNativeQuery("sql statement");
List<Object[]> results = query.getResultList();
 1
Author: Henrik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-25 07:39:08

Using Native Query:

Query query = entityManager.createNativeQuery("SELECT projectId, projectName FROM projects");
List result = query.getResultList();
 0
Author: ukchaudhary,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-04 08:39:53

Większość odpowiedzi sugeruje użycie pewnej odmiany natywnego zapytania SQL. Jednak przy użyciu wbudowanego spring-data jpa również możemy to osiągnąć:

Musisz tylko użyć następującej metody w klasie repozytorium.

ModelClass findBy$Column_1And$Column_2In(Object $col1Value, Object $col2Value );

W zależności od schematu może zwrócić listę lub pojedynczą instancję. Podejście to można zastosować do pojedynczych lub wielu kolumn, jak pokazano powyżej.

Dla Twojego przykładu może to być coś w stylu:

Project findByProjectIdAndProjectNameIn(long projectId, String projectName);

ProjectId, projectName

 0
Author: Sudip Bhandari,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-04 08:23:34