2016-05-11 24 views
5

Sto usando Spring Boot (1.3.3.RELEASE) e Hibernate JPA nel mio progetto. Il mio soggetto è simile al seguente:Come recuperare solo gli attributi selezionati di un'entità utilizzando 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; 
} 

mio repository è simile al seguente:

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

In alcuni casi ho bisogno di prendere solo id e nome attributi di soggetti RuleVO. Come posso raggiungere questo obiettivo? Ho trovato un avviso che dovrebbe essere possibile usando Criteria API e Proiezioni ma come? Molte grazie in anticipo. Vojtech

+1

che non può essere fatto, tutto quello che puoi fare è carico pigro le collezioni. Direi che non vi è alcun vantaggio in termini di prestazioni nel ritrarre i dati in modo selettivo. –

+1

Vedere 19.1.7 https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/performance.html che afferma essenzialmente che, in linea con il commento sopra, per i campi non di raccolta è fattibile ma stai sprecando il tuo tempo. –

risposta

7

UPDATE:

Come è stato sottolineato a me, Sono pigro e questo può essere fatto molto bene quindi sto aggiornando la mia risposta dopo aver guardato intorno al web per uno corretto.

Ecco un esempio di come ottenere solo le ID e solo i nomi:

@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); 
} 

Speriamo che questo aggiornamento dimostra utile


Old Risposta:

Solo il recupero dell'attrazione specifica ibutes nome/id non è possibile in quanto questo non è il modo in cui è stata progettata la molla o qualsiasi database SQL per quella materia come si seleziona sempre una riga che è un'entità.

Cosa si può fare è di query sulle variabili nell'entità, per esempio:

@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 
} 

È possibile modificare questi tuttavia si desidera w.r.t. I tuoi bisogni. È possibile chiamare questi metodi direttamente tramite il repository autowired

Vedi http://docs.spring.io/spring-data/jpa/docs/current/reference/html/ sezione 5.3 per ulteriori opzioni ed esempi

+1

Questo non è vero. Sql riguarda solo il recupero di colonne di righe. 'select * from mytable' è solo la nostra pigrizia per gli sviluppatori;) –

+0

Hai ragione. In realtà non ho scritto una query = D 'seleziona il campo da table', voilà: colonna –

+0

Sto supportando i suoi aggiornamenti. –

2

Sì, si può raggiungere con le proiezioni. Esistono molti modi per applicarli:

Se è possibile eseguire l'aggiornamento a Spring Data Hopper, fornisce un supporto di facile utilizzo per le proiezioni. Vedi come usarli nello reference documentation.

In caso contrario, prima di tutto creare un DTO con gli attributi che si desidera caricare, qualcosa come:

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; 
    } 
} 

Naturalmente, è possibile utilizzare anche le annotazioni Lombok.

Quindi, è possibile utilizzare nelle query JPQL come questo:

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

Un'altra opzione, se si vuole evitare di utilizzare i nomi delle classi DTO nelle query, è quello di implementare il proprio metodo di query utilizzando QueryDSL. Con Spring Data JPA, è necessario:

  • Creare una nuova interfaccia con il nuovo metodo. Es:

    public interface RuleRepositoryCustom { 
        public List<RuleProjection> findAllWithProjection(); 
    } 
    
  • Modificare il repository per estendere la nuova interfaccia. Es:

    public interface RuleRepository extends JpaRepository<RuleVO, Long>, RuleRepositoryCustom { 
    ... 
    
  • Creare un'implementazione del repository personalizzati utilizzando il supporto della molla dati JPA QueryDSL. In precedenza devi generare le Q Clases di QueryDSL, usando il suo plugin Maven. Es:

    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

È possibile anche definire costruttore personalizzato per andare a prendere le colonne specifiche utilizzando JPQL.

Esempio:

sostituire {} javaPackagePath con percorso completo pacchetto Java della classe di utilizzo come costruttore in 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); 
} 
Problemi correlati