Soru JPA belirli sütunları seçerek


Tüm veritabanı işlemlerini gerçekleştirmek için Spring JPA kullanıyorum. Ancak, JPA'daki bir tablodan belirli sütunları nasıl seçeceğimi bilmiyorum?

Örneğin:
SELECT projectId, projectName FROM projects


76
2018-02-25 07:25


Menşei


bunu gör stackoverflow.com/questions/12618489/... - Rembo
JPA'nın belirli alanları aramamasının ardındaki fikir, maliyetin (verimlilik açısından) bir tablonun bir satırını veya tüm sütunlarını bir tablodan getirmesidir. - Desorder
@Desorder - maliyet her zaman aynı değildir. Muhtemelen daha basit, ilkel veri türleri için büyük bir anlaşma değil, ancak bu sayfada sona erme nedenim, basit bir "liste belgeleri" sorgusunun yavaş çalıştığını fark ettim. Bu varlığın bir BLOB sütunu var (dosya yükleme / depolama için gerekiyor) ve yavaş olduğundan şüpheleniyorum çünkü dokümanlar listelenmek için gerekli olmasa bile BLOB'ları belleğe yüklüyor. - jm0
@ jm0 Hatırladığınız kadarıyla, kaç tabloda BLOB sütunları vardı? - Desorder
@Desorder sadece bir tabloydu ama bir "liste" fonksiyonu yapıyordum (multirow - belirli bir kimlik tarafından oluşturulan tüm dokümanlar listeleniyor). Bu sorunu fark etmemin tek nedeni, bu basit liste sorgusunun birkaç saniye sürmesiydi, diğer tablolarda daha karmaşık sorgular neredeyse anında gerçekleşiyordu. Fark ettiğimde, satırlar eklendikçe daha fazla acı çekeceğini biliyordum çünkü Spring JPA her BLOB'u kullanılmadığı halde belleğe yüklüyor. Bahar verisi için iyi bir çözüm buldum (aşağıda kaydedildi) ama sanırım daha iyi bir JPA notu var. Çalışırsam tmrw yazacağım - jm0


Cevaplar:


Sen ayarlayabilirsiniz nativeQuery = true içinde @Query bir açıklama Repository sınıf böyle:

public static final String FIND_PROJECTS = "SELECT projectId, projectName FROM projects";

@Query(value = FIND_PROJECTS, nativeQuery = true)
public List<Object[]> findProjects();

Ancak haritayı kendiniz yapmak zorunda kalacağınızı unutmayın. Gerçekten sadece bu iki değere ihtiyacınız olmadıkça, düzenli olarak eşlenmiş haritayı kullanmak daha kolay olacaktır:

public List<Project> findAll()

Muhtemelen Bahar verilerine bakmaya değer. docs de.


39
2018-02-25 07:43



yerel sorgular için gerek yok. Bunları kullanmaktan kaçınmalısınız çünkü JPQL'nin avantajlarını mahvediyorlar. AIDS yanıtına bakınız. - Blauhirn
Benim için ilk niteliği (yukarıda belirtilen FIND_PROJECTS) ile value öznitelik adı (eğer bu benim kodum olsaydı şöyle yazmalıydım) @Query(value = FIND_PROJECTS, nativeQuery = true), vb. - smeeb


Özellikle sözdizimini sevmiyorum (biraz hacky görünüyor ...) ama bu bulabildiğim en zarif çözüm (JPA deposu sınıfında özel bir JPQL sorgusu kullanıyor):

@Query("select new com.foo.bar.entity.Document(d.docId, d.filename) from Document d where d.filterCol = ?1")
List<Document> findDocumentsForListing(String filterValue);

Daha sonra tabiki, docId & fameame dosyasını constructor args olarak kabul eden Document için bir kurucu sağlamanız gerekir.


89
2018-03-12 21:34



(ve btw doğruladı, "Belge" içe aktarılırsa tam olarak nitelenmiş bir sınıf adı sağlamanız gerekmez - sadece bu şekilde vardı çünkü bu, bulamadığım tek örnekte yapıldığı için) - jm0
Bu kabul edilen cevap olmalı. Mükemmel çalışır ve gerçekten sadece gerekli alanları seçer. - Yonatan Wilkof
Gereksiz alanlar da dahil edildi, fakat 'null' değeriyle bu alanlar bellek kaplar mı? - gabbler
evet ama çok az o kadar büyük ölçüde, bu etrafında mühendisi çalışmak için çok saçma olurdu - stackoverflow.com/questions/2430655/... Bu alanlar olmadan özel hafif nesneler yapmanız ve aynı tabloya işaret etmelisiniz? ORM'leri kullanırken ve onların ilişkilerinden yararlanmak için hangi IMO'nun istenmediği ... hiper-optimizasyon, sadece biraz hafif DSL sorgusu kullanmak ve doğrudan DTO'larla eşleşmek için daha fazla olabilir, ve sonra da artıklığın kaldırıldığını düşünüyorum - jm0
jm0, tamamen ithal edilmiş olsa da, tam olarak nitelenmemiş bir classname olmadan benim için çalışmadı. Yine de başarılı bir şekilde derlemişti. - Heisenberg


Spring Data JPA projeksiyonlarını kullanabilirsiniz. (DOC). Durumunda, arayüz oluştur:

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

ve deponuza aşağıdaki yöntemi ekleyin

List<ProjectIdAndName> findAll();

57
2017-12-02 14:07



Bu temiz bir çözümdür. kazan şablonu olabilir, ancak arayüz varlığın iç sınıfı olabilir. Oldukça temiz. - iceman
Bu kabul edilen cevap olmalı. - sedooe
Harika, sadece varlığınızdaki arayüzü uygulamayacağınızı veya işe yaramayacağını unutmayın. - alizelzele
Yansıtılan arayüz nereye gider? kendi dosyasında veya tam varlık özelliklerini döndüren ortak arayüzde yer alabilir mi? - Micho Rizo


Benim durumumda, zorunlu olmayan alanlar olmadan (sadece gerekli olan alanlarla) ayrı bir varlık sınıfı oluşturdum.

Varlığı aynı tabloya eşleyin. Artık tüm sütunlar gerektiğinde, sadece bazı sütunlar gerektiğinde eski varlığı kullanıyorum, ben lite varlığını kullanıyorum.

Örneğin.

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

Şunun gibi bir şey oluşturabilirsiniz:

@Entity
@Table(name = "user")
Class UserLite{
         @Column(name = "id", unique=true, nullable=false)
         int id;
         @Column(name = "name", nullable=false)
         String name;
}

Bu, getirilecek sütunları bildiğinizde çalışır (ve bu değişmeyecektir).

sütunlara dinamik olarak karar vermeniz gerekiyorsa çalışmaz.


11
2017-12-07 10:50



Merhaba sachin, eğer yukarıda bahsettiğin gibi bir varlık yaratacağım eğer bir şüphe var. JPA ne zaman çalışacak ve kullanıcı adıyla tablo oluşturmaya çalışacaktır. hangi varlık kullanacaktır. - user3364549
hiçbir zaman JPA ile bir tablo yaratmayın, tablolarınızı db'de elle oluşturun, ilişkisel dünyayı nesne dünyasına eşlemek için JPA'yı kullanın. - Sachin Sharma


Benim durumumda, sadece json sonucuna ihtiyacım var ve bu benim için çalışıyor:

public interface SchoolRepository extends JpaRepository<School,Integer> {
    @Query("select s.id, s.name from School s")
    List<Object> getSchoolIdAndName();
}

denetleyicide:

@Autowired
private SchoolRepository schoolRepository;

@ResponseBody
@RequestMapping("getschoolidandname.do")
public List<Object> getSchool() {
    List<Object> schools = schoolRepository.getSchoolIdAndName();
    return schools;
}

11
2017-07-07 13:29



yerine koymalısın Object mpr tarafından açıklandığı gibi özel bir arayüze sahip. kusursuz çalışır - Blauhirn


Sanırım kullanmanın kolay yolu QueryDSLBu, Spring-Data ile birlikte gelir.

Sorunuza göre cevap olabilir

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

Varlık yöneticisi Otomatik Kablolu olabilir ve her zaman * QL dili kullanılmadan nesne ve claslarla çalışacaksınız.

Bağlantıda gördüğünüz gibi, son seçenek, neredeyse benim için, daha zarif, yani sonucu depolamak için DTO kullanıyor gibi görünüyor. Aşağıdaki örnekte uygula:

JPAQuery query = new JPAQuery(entityManager);
QProject project = QProject.project;
List<ProjectDTO> dtos = query.from(project).list(new QProjectDTO(project.projectId, project.projectName));

ProjectDTO'nun tanımlanması:

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(){....}
}

6
2017-09-15 08:49





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
2018-04-20 07:51