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();
ただし、自分でマッピングを行う必要があります。これらの2つの値だけが本当に必要な場合を除いて、次のような通常のマップされたルックアップを使用する方がおそらく簡単です。
public List<Project> findAll()
おそらく、Springデータのドキュメントも一見の価値があります。
FIND_PROJECTS
)をvalue
属性名で修飾する必要がありました(そのため、これが私のコードである場合、次のように記述しなければなりませんでした@Query(value = FIND_PROJECTS, nativeQuery = true)
。など
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;
}
Object
mprで説明されているカスタムインターフェイスに置き換える必要があります。完璧に動作
私の場合、必要のないフィールドなしで(必要なフィールドのみで)別個のエンティティークラスを作成しました。
エンティティを同じテーブルにマップします。すべての列が必要な場合は古いエンティティを使用し、一部の列のみが必要な場合は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));
}}
エンティティマネージャーは自動接続することができ、* 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(){....}
}
新しい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();
}
詳細はドキュメントを確認してください
私の意見では、これは素晴らしい解決策です:
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 Data JPAを使用すると、データベースから特定の列を選択するための規定があります
---- DAOImplで----
@Override
@Transactional
public List<Employee> getAllEmployee() throws Exception {
LOGGER.info("Inside getAllEmployee");
List<Employee> empList = empRepo.getNameAndCityOnly();
return empList;
}
----リポジトリ内----
public interface EmployeeRepository extends CrudRepository<Employee,Integer> {
@Query("select e.name, e.city from Employee e" )
List<Employee> getNameAndCityOnly();
}
私の場合は100%動作しました。ありがとう。
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();
以下のコードをリポジトリインターフェースクラスに適用できます。
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);
ネイティブクエリの使用:
Query query = entityManager.createNativeQuery("SELECT projectId, projectName FROM projects");
List result = query.getResultList();