web-dev-qa-db-ja.com

Spring JPAが特定の列を選択する

Spring JPAを使用してすべてのデータベース操作を実行しています。しかし、Spring JPAのテーブルから特定の列を選択する方法がわかりませんか。

例えば:
SELECT projectId, projectName FROM projects

101
user1817436

RepositoryクラスのnativeQuery = trueアノテーションで@Queryを次のように設定できます。

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のデータ docs も見る価値があります。

52
Durandal

私は特に構文が好きではありません(それはちょっとハックに見えます...)、これは私が見つけることができた最も洗練された解決策です(それは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);

もちろん、docIdとfilenameをコンストラクタ引数として受け入れるDocumentのコンストラクタを用意するだけです。

111
jm0

Spring Data JPA (doc) の射影を使用できます。あなたの場合は、インターフェイスを作成します。

interface ProjectIdAndName{
    String getId();
    String getName();
}

次のメソッドをリポジトリに追加してください

List<ProjectIdAndName> findAll();
103
mpr

私の状況では、私は唯一の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;
}
13
Atal

私の場合、私は必須ではないフィールドなしで(必須のフィールドだけで)別のエンティティクラスを作成しました。

エンティティを同じテーブルにマップします。すべての列が必要なときは古いエンティティを使いますが、必要な列がいくつかあるときは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;
}

これはあなたが取得するカラムを知っているときにうまくいきます(そしてこれは変更されません)。

動的に列を決定する必要がある場合は機能しません。

12
Sachin Sharma

簡単な方法は 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(){....}
}
7
kszosze

私の意見では、これは素晴らしい解決策です。

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);
}
3
Evgeni Atanasov
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.
2
SR Ranjan

ネイティブ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);
2
hahn

あなたのリポジトリインタフェースクラスに以下のコードを適用することができます。

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);
2
ajaz

あなたは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();
1
Henrik

新しい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();
}

詳しくは docs をチェックしてください。

1
jombie

ここでの回答のほとんどは、ネイティブSQLクエリのバリエーションを使用することを提案しています。ただし、作り付けのspring-data jpaを使っても実現できます。

Repositoryクラスでは以下のメソッドシグネチャを使用するだけです。

ModelClass findBy$Column_1And$Column_2In(Object $col1Value, Object $col2Value );

スキーマに応じて、リストまたは単一のインスタンスを返すことがあります。このアプローチは、上記のように単一または複数の列に適用できます。

あなたの例では、それは次のようになります。

Project findByProjectIdAndProjectNameIn(long projectId, String projectName);

projectId、projectName

0
Sudip Bhandari

@jombieが提案した答えを使うことができます。

  • エンティティクラスの外側の別のファイルにインタフェースを配置します。
  • ネイティブクエリを使用するかどうか(選択はニーズによります)。
  • この目的のためにfindAll()メソッドをオーバーライドしないで、あなたの選んだ名前を使ってください。
  • 新しいインターフェースでパラメータ化されたListを返すことを忘れないでください(例:List<SmallProject>)。
0
foxbit

ネイティブクエリを使用する:

Query query = entityManager.createNativeQuery("SELECT projectId, projectName FROM projects");
List result = query.getResultList();
0
ukchaudhary