2009-11-13 6 views
0

J'ai 2 entités dans une relation one-to-Many:requête Hibernate avec fetch question

OfficeView.java:

public class OfficeView implements java.io.Serializable { 

    private Integer officeId; 
    private String addr1; 
    private String city; 
    private String state; 
    private String zip; 
    private List<Devices> devices; 

getters and setters 

    @OneToMany(mappedBy = "officeView", fetch = FetchType.EAGER) 
    public List<Devices> getDevices() { 
     return devices; 
    } 

    public void setDevices(List<Devices> devices) { 
     this.devices = devices; 
    } 

} 

Devices.java:

public class Devices implements java.io.Serializable { 

    private Integer devId; 
    private String devName; 
    private Date lastUpdate; 
    private OfficeView officeView; 

getters and setters 

    @ManyToOne(fetch = FetchType.LAZY) 
    @JoinColumn(name = "office_id") 
    public OfficeView getOfficeView() { 
     return officeView; 
    } 

    public void setOfficeView(OfficeView officeView) { 
     this.officeView = officeView; 
    } 

} 

Pour certains périphériques, dans la table il y a 2 entrées presque identiques à l'exception de lastUpdate. Je veux toujours récupérer l'entrée la plus récente dans la table. Et seulement cette entrée.

Par exemple, vous avez 2 entrées pour cet appareil:

SSA-PITTSB-PA-NEF82 2009-10-12 23:51:07 SSA-PITTSB-PA-NEF82 2009-10-15 14: 19:35

Lorsque je charge l'instance OfficeView pour le bureau qui la contient (et d'autres périphériques), je veux seulement récupérer le plus récent de ces 2 périphériques. Dans la base de données, je peux obtenir cette courte liste de la table appareils avec cette requête SQL:

select t.* from 
    (select dev_id, dev_name, max(last_update) maxValue 
from devices 
    group by dev_name) x 
join devices t on x.dev_name=t.dev_name 
and x.maxValue=t.last_update 

SSA-PITTSB-PA-NEF82 2009-10-15 14:19:35

C'est L'application seam et OfficeViewHome.java, à partir de laquelle la requête est appelée, étend EntityHome. Je pense que la méthode correcte consiste à surcharger loadInstance avec une requête personnalisée. Je n'ai juste aucune idée de comment construire la requête. Comment puis-je faire cela?

Je sais comment écrire la requête de jointure dans SQL pour joindre les tables oFunction_view et devices et obtenir toutes les données correctes. Mais je ne peux pas utiliser cette requête pour charger l'instance (comme dans createNativeQuery) car les données de la table devices doivent être chargées en tant que liste d'objets Devices. J'espère vraiment que cela a du sens parce que je suis complètement perplexe.

april26

Répondre

0

Vous devez override collection loader - être conscient que cela est une extension Hibernate à la norme JPA. Vous pouvez utiliser une requête SQL pour faire ceci au lieu d'écrire HQL - en effet, écrire HQL peut être quelque peu gênant dans ce scénario.

@Loader(namedQuery = "latestDevices") 
@NamedNativeQuery(name="latestDevices", query="...", resultClass = Devices.class) 
@OneToMany(mappedBy = "officeView", fetch = FetchType.EAGER) 
public List<Devices> getDevices() { 
    return devices; 
} 

La requête réelle est celle que vous avez écrit ci-dessus avec la condition supplémentaire sur office_id, dont la valeur du paramètre va être fourni par Hibernate:

select t.* from 
(select dev_id, dev_name, max(last_update) maxValue 
    from devices 
    group by dev_name) x 
    join devices t on x.dev_name=t.dev_name 
    and x.maxValue=t.last_update 
    and t.office_id = ? 

Si les noms ne sont pas uniques à travers vous aurez devez réécrire ce qui précède pour rejoindre explicitement office sur id pour la sélection interne car vous ne pouvez pas répéter l'espace réservé ?.

Soyez très prudent avec la mise à jour/suppression Devices par la collecte sur Office, Hibernate tente d'optimiser certaines opérations et peut finir par la suppression des dispositifs de données Office qui ne sont pas récupérées par sélection ci-dessus.

+0

Je savais que vous viendriez via ChssPly76! Merci. Je veux bien essayer. Je ne vais pas mettre à jour ou supprimer des appareils du tout dans mon application, cela ne posera donc aucun problème. – april26