Spring JPA 选择特定列
-
21-12-2019 - |
题
我正在使用 Spring JPA 执行所有数据库操作。但是我不知道如何从 Spring JPA 中的表中选择特定列?
例如:
SELECT projectId, projectName FROM projects
解决方案
您可以在像这样的nativeQuery = true
类中设置生成的@Query
注释:
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()
.
它可能值得看看春天数据 docs 。
其他提示
您可以使用来自Spring Data JPA (doc)。在您的情况下,创建界面:
interface ProjectIdAndName{
String getId();
String getName();
}
.
并将以下方法添加到您的存储库
List<ProjectIdAndName> findAll();
. 我特别不喜欢这种语法(它看起来有点老套……),但这是我能找到的最优雅的解决方案(它在 JPA 存储库类中使用自定义 JPQL 查询):
@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实体。
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;
}
.
您可以创建类似的东西:
@Entity
@Table(name = "user")
Class UserLite{
@Column(name = "id", unique=true, nullable=false)
int id;
@Column(name = "name", nullable=false)
String name;
}
.
当您知道要获取的列(而这不会更改)时,这会有效。
如果需要动态决定列。
我猜是可以使用 querydsl,带有弹簧数据。
使用您的问题答案可以是
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));
}}
.
实体管理器可以自动浏览,您始终将使用Object和Clases而无需使用* 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.
. 可以在本机SQL中指定生成acodeTagcode作为字段值。
@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表示您的数据库表名称等项目。 并列出意味着项目是项目中的实体类。
@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();
. 可以使用@jombie建议的答案,以及:
- 将界面放在单独的文件中,在实体类之外;
- 使用本机查询(选择依赖于您的需求);
- 不覆盖
findAll()
方法,以便使用您选择的名称; - 记得用新的接口返回一个
List
参数(例如,List<SmallProject>
)。