2016-05-11 11 views
5

Używam Spring Boot (1.3.3.RELEASE) i Hibernate JPA w moim projekcie. Moja jednostka wygląda następująco:Jak pobrać tylko wybrane atrybuty jednostki przy użyciu Spring JPA?

@Data 
@NoArgsConstructor 
@Entity 
@Table(name = "rule") 
public class RuleVO { 

    @Id 
    @GeneratedValue 
    private Long id; 

    @Column(name = "name", length = 128, nullable = false, unique = true) 
    private String name; 

    @Column(name = "tag", length = 256) 
    private String tag; 

    @OneToMany(mappedBy = "rule", cascade = CascadeType.ALL, orphanRemoval = true) 
    private List<RuleOutputArticleVO> outputArticles; 

    @OneToMany(mappedBy = "rule", cascade = CascadeType.ALL, orphanRemoval = true) 
    private List<RuleInputArticleVO> inputArticles; 
} 

mój repozytorium wygląda następująco:

@Repository 
public interface RuleRepository extends JpaRepository<RuleVO, Long> { 
} 

w niektórych przypadkach muszę sprowadzić tylko Numer ID i nazw atrybuty jednostki RuleVO. Jak mogę to osiągnąć? Zauważyłem, że powinna być wykonalna przy użyciu API Kryteriów i Prognozy, ale w jaki sposób? Z góry bardzo dziękuję. Vojtech

+1

I nie można zrobić wszystko, co możesz zrobić, to Lazy obciążenie zbiory. Powiedziałbym, że nie ma korzyści z wydajności polegającej na selektywnym pobieraniu danych. –

+1

Zobacz 19.1.7 https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/performance.html, która zasadniczo stwierdza, że ​​zgodnie z powyższym komentarzem w przypadku pól niereksploatacyjnych jest to możliwe ale marnujesz swój czas. –

Odpowiedz

7

UPDATE:

Jak zostało wskazane do mnie Jestem leniwy i może to być bardzo dobrze zrobione, dlatego aktualizuję swoją odpowiedź po tym, jak rozejrzałem się po Internecie.

Oto przykład, w jaki sposób dostać tylko Dokumentach interpretacyjnych i tylko nazwiska:

@Repository 
public interface RuleRepository extends JpaRepository<RuleVO, Long> { 

    @Query("SELECT r.id FROM RuleVo r where r.name = :name") 
    List<Long> findIdByName(@Param("name") String name); 

    @Query("SELECT r.name FROM RuleVo r where r.id = :id") 
    String findNameById(@Param("id") Long id); 
} 

Mam nadzieję, że ta zmiana okaże się pomocna


Old odpowiedź:

Tylko pobieranie określonego attr ibutes nazwa/id nie jest możliwe, ponieważ nie jest to sposób, w jaki została zaprojektowana wiosna lub jakakolwiek baza danych SQL, ponieważ zawsze wybierasz wiersz będący jednostką.

co można zrobić, to zapytanie w ciągu zmiennych w jednostce, na przykład:

@Repository 
public interface RuleRepository extends JpaRepository<RuleVO, Long> { 

    public RuleVo findOneByName(String name); 
    public RuleVo findOneByNameOrId(String name, Long id); 
    public List<RuleVo> findAllByName(String name); 
    // etc, depending on what you want 
} 

Można modyfikować te jednak chcesz w.r.t. Twoje potrzeby. Można nazwać tych metod bezpośrednio przez autowired repozytorium

Zobacz http://docs.spring.io/spring-data/jpa/docs/current/reference/html/ Rozdział 5.3 po więcej informacji i przykładów

+1

To nieprawda. Sql polega na pobieraniu kolumn z wierszy. 'select * from mytable' to tylko nasze lenistwo programisty;) –

+0

Masz rację. Nie napisałem od razu zapytania = D 'wybierz pole z tabeli', voila: kolumna –

+0

Popieram jego aktualizacje. –

2

Tak, można osiągnąć to z projekcji. Możesz je zastosować na wiele sposobów:

Jeśli możesz przeprowadzić aktualizację do Spring Data Hopper, zapewnia ona łatwą obsługę projekcji. Zobacz, jak z nich korzystać w reference documentation.

W przeciwnym razie, przede wszystkim stworzenie dto z atrybutami, które chcesz załadować, coś takiego:

package org.example; 

public class RuleProjection { 

    private final Long id; 

    private final String name; 

    public RuleProjection(Long id, String name) { 
     this.id = id; 
     this.name = name; 
    } 

    public Long getId() { 
     return id; 
    } 

    public String getName() { 
     return name; 
    } 
} 

Oczywiście, można użyć także adnotacje Lombok.

Następnie można używać w zapytaniach JPQL jak ten:

select new org.example.RuleProjection(rule.id, rule.name) from RuleVO rule order by rule.name 

Inną opcją, jeśli chcesz uniknąć używania nazwy klas Dto w zapytaniach, jest wdrożenie własną metodę zapytania przy użyciu QueryDSL. W Spring Data JPA musisz:

  • Stwórz nowy interfejs za pomocą nowej metody. Przykład:

    public interface RuleRepositoryCustom { 
        public List<RuleProjection> findAllWithProjection(); 
    } 
    
  • Zmień swoje repozytorium, aby rozszerzyć nowy interfejs. Ex:

    public interface RuleRepository extends JpaRepository<RuleVO, Long>, RuleRepositoryCustom { 
    ... 
    
  • Załóż wdrożenia repozytorium niestandardowym wykorzystaniem wsparcia Wiosna danych JPA QueryDSL. Musisz wcześniej wygenerować klauzule Q QueryDSL, używając wtyczki Maven. Ex:

    public class RuleRepositoryImpl { 
    
        public List<RuleProjection> findAllWithProjection() { 
         QRuleVO rule = QRuleVO.ruleVO; 
         JPQLQuery query = getQueryFrom(rule);  
         query.orderBy(rule.name.asc()); 
         return query.list(ConstructorExpression.create(RuleProjection.class, rule.id, rule.name)); 
        } 
    } 
    
0

Można również zdefiniować niestandardowy konstruktor przynieść konkretne kolumny używając JPQL.

przykład:

wymienić {javaPackagePath} na drodze całkowitego pakietu Java stosowania klasy jako konstruktora JPQL.

public class RuleVO { 
    public RuleVO(Long id, String name) { 
    this.id = id; 
    this.name = name; 
    } 
} 


@Repository 
public interface RuleRepository extends JpaRepository<RuleVO, Long> { 

    @Query("SELECT new {javaPackagePath}.RuleVO(r.id, r.name) FROM RuleVo r where r.name = :name") 
    List<RuleVO> findIdByName(@Param("name") String name); 
} 
Powiązane problemy