Spring JPA特定の列を選択します
-
21-12-2019 - |
質問
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();
.
あなたは自分でマッピングをする必要があることに注意してください。あなたが本当にそれらの2つの値だけを必要としていない限り、このような通常のマッピングルックアップを使うのはおそらくより簡単です:
public List<Project> findAll()
.
おそらくそれは春データを見る価値がある docs も。
他のヒント
スプリングデータからの予測を使用することができます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);
.
それでも、Constructor ARGSとして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;
}
.
これは、取得する列を知っているときに機能します(これは変更されません)。
は列を動的に決める必要がある場合は機能しません。
私は簡単な方法があると思いますか?は春データに付属しています。
あなたの質問に使う答えは
になることができます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));
}}
.
エンティティマネージャを自動的にすることができ、常にオブジェクトとクリーズを使用せずに使用されます。* 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);
}
. 新しいスプリングバージョンでは、次のようにすることができます。
ネイティブクエリを使用しない場合、これは以下のように行うことができます。
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();
}
.
詳細は 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.
. ネイティブSQLのフィールド値としてnull
を指定することができます。
@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>
)。