Я использую Spring JPA для выполнения всех операций с базой данных. Однако я не знаю, как выбрать конкретные столбцы из таблицы в Spring JPA?
Например: SELECT projectId, projectName FROM projects
Я использую Spring JPA для выполнения всех операций с базой данных. Однако я не знаю, как выбрать конкретные столбцы из таблицы в Spring JPA?
Например: SELECT projectId, projectName FROM projects
Вы можете установить nativeQuery = true
в аннотации @Query
из класса Repository
следующим образом:
public static final String FIND_PROJECTS = "SELECT projectId, projectName FROM projects";
@Query(value = FIND_PROJECTS, nativeQuery = true)
public List<Object[]> findProjects();
Обратите внимание, что вам придется самому делать картографирование. Вероятно, проще просто использовать регулярный сопоставленный поиск, например, если вам действительно нужны только эти два значения:
public List<Project> findAll()
Возможно, стоит посмотреть на Spring данные docs.
Вы можете использовать проекции из Spring Data JPA (doc). В вашем случае создайте интерфейс:
interface ProjectIdAndName{
String getId();
String getName();
}
и добавьте следующий метод в ваш репозиторий
List<ProjectIdAndName> findAll();
Мне не очень нравится синтаксис (он выглядит немного хакерским...), но это самое элегантное решение, которое мне удалось найти (оно использует собственный запрос JPQL в классе репозитория 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);
Тогда, конечно, вам просто нужно предоставить конструктор для Document
, который принимает docId
& filename
в качестве аргумента конструктора.
В моей ситуации мне нужен только результат json, и это работает для меня:
public interface SchoolRepository extends JpaRepository<School,Integer> {
@Query("select s.id, s.name from School s")
List<Object> getSchoolIdAndName();
}
в контроллере:
@Autowired
private SchoolRepository schoolRepository;
@ResponseBody
@RequestMapping("getschoolidandname.do")
public List<Object> getSchool() {
List<Object> schools = schoolRepository.getSchoolIdAndName();
return schools;
}
В моем случае я создал отдельный класс сущности без полей, которые не требуются (только с полями, которые необходимы).
Сопоставьте объект с той же таблицей. Теперь, когда требуются все столбцы, я использую старый объект, когда требуются только некоторые столбцы, я использую объект Lite.
например.
@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;
}
Вы можете создать что-то вроде:
@Entity
@Table(name = "user")
Class UserLite{
@Column(name = "id", unique=true, nullable=false)
int id;
@Column(name = "name", nullable=false)
String name;
}
Это работает, когда вы знаете столбцы для извлечения (и это не изменится).
не будет работать, если вам нужно динамически решать столбцы.
Я предполагаю, что самый простой способ - использовать QueryDSL, который поставляется с Spring-Data.
Используя на ваш вопрос ответ может быть
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));
}}
Менеджер сущностей может быть Autowired, и вы всегда будете работать с объектом и предложениями без использования языка * QL.
Как видно из ссылки, последний вариант кажется мне более элегантным, то есть с помощью DTO для сохранения результата. Примените к вашему примеру, который будет:
JPAQuery query = new JPAQuery(entityManager);
QProject project = QProject.project;
List<ProjectDTO> dtos = query.from(project).list(new QProjectDTO(project.projectId, project.projectName));
Определение ProjectDTO как:
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(){....}
}
На мой взгляд, это отличное решение:
interface PersonRepository extends Repository<Person, UUID> {
<T> Collection<T> findByLastname(String lastname, Class<T> type);
}
и используя это так
void someMethod(PersonRepository people) {
Collection<Person> aggregates =
people.findByLastname("Matthews", Person.class);
Collection<NamesOnly> aggregates =
people.findByLastname("Matthews", NamesOnly.class);
}
С более новыми версиями Spring можно сделать следующее:
Если не используется собственный запрос, это можно сделать, как показано ниже:
public interface ProjectMini {
String getProjectId();
String getProjectName();
}
public interface ProjectRepository extends JpaRepository<Project, String> {
@Query("SELECT p FROM Project p")
List<ProjectMini> findAllProjectsMini();
}
Используя собственный запрос, можно сделать то же самое, как показано ниже:
public interface ProjectRepository extends JpaRepository<Project, String> {
@Query(value = "SELECT projectId, projectName FROM project", nativeQuery = true)
List<ProjectMini> findAllProjectsMini();
}
Для получения подробной информации проверьте документы
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.
Можно указать null
как значение поля в native 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);
Вы можете применить приведенный ниже код в своем классе интерфейса репозитория.
entityname означает имя вашей базы данных, например, проекты. И List означает, что Project - это класс Entity в ваших проектах.
@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);
Вы можете использовать JPQL:
TypedQuery <Object[]> query = em.createQuery(
"SELECT p.projectId, p.projectName FROM projects AS p", Object[].class);
List<Object[]> results = query.getResultList();
или вы можете использовать собственный SQL-запрос.
Query query = em.createNativeQuery("sql statement");
List<Object[]> results = query.getResultList();
Использование собственного запроса:
Query query = entityManager.createNativeQuery("SELECT projectId, projectName FROM projects");
List result = query.getResultList();
Большинство ответов здесь предлагают использовать некоторые вариации собственного SQL-запроса. Однако, используя встроенный Spring-Data JPA, мы также можем достичь этого:
Вам просто нужно использовать следующую сигнатуру метода в классе репозитория.
ModelClass findBy$Column_1And$Column_2In(Object $col1Value, Object $col2Value );
В зависимости от схемы он может вернуть список или один экземпляр. Этот подход может применяться к одному или нескольким столбцам, как показано выше.
Для вашего примера это может быть что-то вроде:
Project findByProjectIdAndProjectNameIn(long projectId, String projectName);
имя_проекта, имя_проекта
Вы можете использовать ответ, предложенный @jombie, и:
findAll()
для этой цели, но используйте имя по вашему выбору;List
параметризованный вашим новым интерфейсом (например, List<SmallProject>
).