2015-04-17 26 views
12

Ho una classe come segue che ha bisogno di recuperare da DB usando Hibernate. Il problema è che la mia classe ha più membri e la maggior parte di loro sono classi, come posso recuperarli?Come recuperare una classe complessa e i suoi membri usando Hibernate Projection?

@Entity 
public class Student { 
    @Id 
    long id; 
    String name; 
    String fname; 
    @OneToMany 
    List<Course> courses; 
    @ManyToOne 
    Dealer dealer; 
    ... 
} 

@Entity 
public class Dealer { 
    @Id 
    long id; 
    String name; 
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "cr.dealer", cascade = CascadeType.ALL) 
    Set<Car> cars = new HashSet<Cars>(0); 
    .. 

} 

Ho bisogno di recuperare studente id 1 e tutti i suoi corsi, proprio dealer e la lista delle auto concessionari.

La mia proiezione è come segue ma non restituisce nulla.

... 
    .setProjection(Projections.projectionList() 

    .add(Projections.property("friends.cars").as("cars") 
    ... 

risposta

1

Perché hai un elenco di corsi e una serie di automobili, si può semplicemente prendere l'intero grafico in una singola query:

select s 
from Student s 
left join fetch s.courses 
left join fetch s.dealer d 
left join fetch d.cars 
where s.id = :id 

Perché stai recuperando due collezioni, questa query genererà un prodotto cartesiano, quindi è necessario assicurarsi che le raccolte figli selezionate non contengano troppe voci.

Se don; t vuole incorrere in un prodotto cartesiano, si può semplicemente eseguire questa query:

select s 
from Student s 
left join fetch s.courses 
left join fetch s.dealer d 
where s.id = :id 

e poi si accede alle dealer.cars per andare a prendere quella raccolta con una query separata:

Student s = ...; 
s.getDealer().getCars().size(); 
+0

Grazie per la risposta, la prego di dare un'occhiata alla mia domanda su http://stackoverflow.com/questions/29980421/how-to-retireve-a-set-member-objects-using-hibernate – Jack

0

Se alte performences non sono un problema, allora si dovrebbe lasciare che Hibernate fare il suo lavoro. Usa semplicemente i getter di te entità. Per Esempio:

Student student1 = session.get(Student.class, 1L); 
List<Course> courses = student1.getCourses(); 
Dealer dealer = student1.getDealer(); 
Set<Car> cars = dealer.getCars(); 
+1

Grazie ma prestazioni elevate dovrebbero essere considerate. – Jack

4
// Projection is not needed, Hibernate will load child values as shown below 

    Student student = session.get(Student.class); 
    List<Course> courses = student.getCourses(); 
    Dealer dealer = student.getDealer(); 

    // If u want records only where child records are present, u can use LEFT_OUTER_JOIN 

    Criteria criteria = getHibernateSession().createCriteria(Student.class); 
    criteria.createAlias("Course", "Course", JoinType.LEFT_OUTER_JOIN); 

    // If u want to use Projections for performance, u have to add each and every column in projection 

    Criteria criteria = getHibernateSession().createCriteria(A.class); 
    criteria.createAlias("b", "b", JoinType.INNER_JOIN); 
    criteria.createAlias("b.r", "b.r", JoinType.INNER_JOIN); 
    criteria.createAlias("b.c", "b.c", JoinType.LEFT_OUTER_JOIN); 
    ProjectionList projectionList = Projections.projectionList(); 
    projectionList.add(Projections.groupProperty("column1")); 
    projectionList.add(Projections.property("column2")); 
    projectionList.add(Projections.property("column3")); 
    criteria.setProjection(projectionList); 
    criteria.setResultTransformer(Transformers.aliasToBean(Table.class)); 
+0

Grazie per la risposta , Ho un nuovo problema con questo e ho postato una nuova domanda per questo problema, per favore date un'occhiata, http://stackoverflow.com/questions/29980421/how-to-retireve-a-set-list-of-member-objects -Utilizzo-hibernate – Jack

0

non sono sicuro se è possibile utilizzare QueryOver ma sarebbe molto facile per questo tipo di attività.

Student student = null; 
Dealer dealer = null; 
Course course = null; 
Car car = null; 

var myStudent = Session.QueryOver<Student>(() => student) 
.Left.JoinQueryOver(() => student.courses,() => courses) 
.Left.JoinQueryOver(() => student.dealer,() => dealer) 
.Left.JoinQueryOver(() => dealer.cars,() => car) 
.SelectList(list => list 
    .Select(() => student.Name) 
    .Select(() => student.Age) 
    .Select(() => courses.Description) 
    .Select(() => dealer.locaiton) 
    .Select(() => car.Model)) 
    .TransformUsing(Transformers.AliasToBean<StudentModel>()) 
    .List<StudentModel>().AsQueryable(); 

Creare un DTO StudentModel per ottenere i risultati. Questo è solo un suggerimento per iniziare, puoi modificarlo in base alle tue esigenze. Spero che funzioni. :)