Ich verwende Spring JPA, um alle Datenbankoperationen auszuführen. Ich weiß jedoch nicht, wie ich in Spring JPA bestimmte Spalten aus einer Tabelle auswählen soll.
Beispielsweise:
SELECT projectId, projectName FROM projects
Ich verwende Spring JPA, um alle Datenbankoperationen auszuführen. Ich weiß jedoch nicht, wie ich in Spring JPA bestimmte Spalten aus einer Tabelle auswählen soll.
Beispielsweise:
SELECT projectId, projectName FROM projects
Antworten:
Sie können nativeQuery = true
die @Query
Annotation aus einer Repository
Klasse wie dieser festlegen :
public static final String FIND_PROJECTS = "SELECT projectId, projectName FROM projects";
@Query(value = FIND_PROJECTS, nativeQuery = true)
public List<Object[]> findProjects();
Beachten Sie jedoch, dass Sie das Mapping selbst durchführen müssen. Es ist wahrscheinlich einfacher, nur die reguläre Zuordnung wie diese zu verwenden, es sei denn, Sie benötigen wirklich nur diese beiden Werte:
public List<Project> findAll()
Es lohnt sich wahrscheinlich auch, sich die Spring- Datendokumente anzusehen .
FIND_PROJECTS
) mit dem value
Attributnamen qualifizieren (wenn dies also mein Code wäre, hätte ich ihn schreiben @Query(value = FIND_PROJECTS, nativeQuery = true)
müssen usw.
Sie können Projektionen aus Spring Data JPA (doc) verwenden . Erstellen Sie in Ihrem Fall eine Schnittstelle:
interface ProjectIdAndName{
String getId();
String getName();
}
und fügen Sie Ihrem Repository die folgende Methode hinzu
List<ProjectIdAndName> findAll();
Ich mag die Syntax nicht besonders (sie sieht ein bisschen hackig aus ...), aber dies ist die eleganteste Lösung, die ich finden konnte (sie verwendet eine benutzerdefinierte JPQL-Abfrage in der JPA-Repository-Klasse):
@Query("select new com.foo.bar.entity.Document(d.docId, d.filename) from Document d where d.filterCol = ?1")
List<Document> findDocumentsForListing(String filterValue);
Dann müssen Sie natürlich nur einen Konstruktor bereitstellen Document
, der docId
& filename
als Konstruktorargumente akzeptiert .
In meiner Situation brauche ich nur das json-Ergebnis, und das funktioniert bei mir:
public interface SchoolRepository extends JpaRepository<School,Integer> {
@Query("select s.id, s.name from School s")
List<Object> getSchoolIdAndName();
}
im Controller:
@Autowired
private SchoolRepository schoolRepository;
@ResponseBody
@RequestMapping("getschoolidandname.do")
public List<Object> getSchool() {
List<Object> schools = schoolRepository.getSchoolIdAndName();
return schools;
}
Object
durch eine benutzerdefinierte Schnittstelle ersetzen, wie von mpr beschrieben. funktioniert einwandfrei
In meinem Fall habe ich eine separate Entitätsklasse ohne die Felder erstellt, die nicht benötigt werden (nur mit den Feldern, die benötigt werden).
Ordnen Sie die Entität derselben Tabelle zu. Wenn nun alle Spalten erforderlich sind, verwende ich die alte Entität. Wenn nur einige Spalten erforderlich sind, verwende ich die Lite-Entität.
z.B
@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;
}
Sie können so etwas erstellen wie:
@Entity
@Table(name = "user")
Class UserLite{
@Column(name = "id", unique=true, nullable=false)
int id;
@Column(name = "name", nullable=false)
String name;
}
Dies funktioniert, wenn Sie die abzurufenden Spalten kennen (und dies wird sich nicht ändern).
funktioniert nicht, wenn Sie die Spalten dynamisch festlegen müssen.
Ich denke, der einfachste Weg ist die Verwendung von QueryDSL , das mit den Spring-Data geliefert wird.
Mit Ihrer Frage kann die Antwort sein
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));
}}
Der Entitätsmanager kann automatisch verdrahtet sein und Sie arbeiten immer mit Objekten und Klassen ohne Verwendung der * QL-Sprache.
Wie Sie im Link sehen können, erscheint die letzte Auswahl fast für mich eleganter, dh die Verwendung von DTO zum Speichern des Ergebnisses. Wenden Sie auf Ihr Beispiel Folgendes an:
JPAQuery query = new JPAQuery(entityManager);
QProject project = QProject.project;
List<ProjectDTO> dtos = query.from(project).list(new QProjectDTO(project.projectId, project.projectName));
Definieren von ProjectDTO als:
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(){....}
}
Mit den neueren Spring-Versionen kann man wie folgt vorgehen:
Wenn Sie keine native Abfrage verwenden, können Sie dies wie folgt tun:
public interface ProjectMini {
String getProjectId();
String getProjectName();
}
public interface ProjectRepository extends JpaRepository<Project, String> {
@Query("SELECT p FROM Project p")
List<ProjectMini> findAllProjectsMini();
}
Mit der nativen Abfrage können Sie wie folgt vorgehen:
public interface ProjectRepository extends JpaRepository<Project, String> {
@Query(value = "SELECT projectId, projectName FROM project", nativeQuery = true)
List<ProjectMini> findAllProjectsMini();
}
Einzelheiten finden Sie in den Dokumenten
Meiner Meinung nach ist dies eine großartige Lösung:
interface PersonRepository extends Repository<Person, UUID> {
<T> Collection<T> findByLastname(String lastname, Class<T> type);
}
und es so zu benutzen
void someMethod(PersonRepository people) {
Collection<Person> aggregates =
people.findByLastname("Matthews", Person.class);
Collection<NamesOnly> aggregates =
people.findByLastname("Matthews", NamesOnly.class);
}
Bei Verwendung von Spring Data JPA ist die Auswahl bestimmter Spalten aus der Datenbank vorgesehen
---- 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();
}
In meinem Fall hat es zu 100% funktioniert. Vielen Dank.
Sie können JPQL verwenden:
TypedQuery <Object[]> query = em.createQuery(
"SELECT p.projectId, p.projectName FROM projects AS p", Object[].class);
List<Object[]> results = query.getResultList();
oder Sie können eine native SQL-Abfrage verwenden.
Query query = em.createNativeQuery("sql statement");
List<Object[]> results = query.getResultList();
Sie können den folgenden Code in Ihrer Repository-Schnittstellenklasse anwenden.
Entitätsname bedeutet, dass Ihr Datenbanktabellenname wie Projekte ist. Und Liste bedeutet, dass Projekt eine Entitätsklasse in Ihren Projekten ist.
@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);
Native Abfrage verwenden:
Query query = entityManager.createNativeQuery("SELECT projectId, projectName FROM projects");
List result = query.getResultList();
Sie können die von @jombie vorgeschlagene Antwort verwenden und:
findAll()
Methode zu diesem Zweck nicht, sondern verwenden Sie einen Namen Ihrer Wahl.List
mit Ihrer neuen Schnittstelle parametrisierte Datei zurückzugeben (z List<SmallProject>
. B. ).