La cartographie des résultats de NativeQuery dans un POJO
j'essaie de mapper les résultats D'une requête Native à un POJO en utilisant @SqlResultSetMapping avec @ConstructorResult. Voici mon code:
@SqlResultSetMapping(name="foo",
classes = {
@ConstructorResult(
targetClass = Bar.class,
columns = {
@ColumnResult(name = "barId", type = Long.class),
@ColumnResult(name = "barName", type = String.class),
@ColumnResult(name = "barTotal", type = Long.class)
})
})
public class Bar {
private Long barId;
private String barName;
private Long barTotal;
...
et puis dans mon DAO:
Query query = em.createNativeQueryBar(QUERY, "foo");
... set some parameters ...
List<Bar> list = (List<Bar>) query.getResultList();
j'ai lu que cette fonctionnalité est prise en charge uniquement dans JPA 2.1, mais c'est ce que j'utilise. Voici ma dépendance:
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.1-api</artifactId>
<version>1.0.0.Final</version>
</dependency>
j'ai trouvé quelques ressources, dont celle-ci: @ConstructorResult la cartographie en jpa 2.1 . Mais je ne suis pas encore avoir de la chance.
Qu'est-ce que je rate? Pourquoi ne trouve-t-on pas le SqlResultSetMapping?
javax.persistence.PersistenceException: org.hibernate.MappingException: Unknown SqlResultSetMapping [foo]
5 réponses
@SqlResultSetMapping
annotation ne doit pas être mis sur un POJO . Mettez-le dans la classe @Entity
. "Sqlresultsetmapping [foo] inconnu" vous dit, que le fournisseur JPA ne voit pas de cartographie sous le nom de 'foo'. S'il vous plaît voir une autre réponse de la mienne pour le bon exemple
Court exemple:
-
classe DTO POJO
@lombok.Getter @lombok.AllArgsConstructor public class StatementDto { private String authorName; private Date createTime; }
-
référentiel bean:
@Repository public class StatementNativeRepository { @PersistenceContext private EntityManager em; static final String STATEMENT_SQLMAP = "Statement-SQL-Mapping"; public List<StatementDto> findPipelinedStatements() { Query query = em.createNativeQuery( "select author_name, create_time from TABLE(SomePipelinedFun('xxx'))", STATEMENT_SQLMAP); return query.getResultList(); } @SqlResultSetMapping(name= STATEMENT_SQLMAP, classes = { @ConstructorResult(targetClass = StatementDto.class, columns = { @ColumnResult(name="author_name",type = String.class), @ColumnResult(name="create_time",type = Date.class) } ) }) @Entity class SQLMappingCfgEntity{@Id int id;} // <- walkaround }
je peux le faire de cette façon:
Session session = em().unwrap(Session.class);
SQLQuery q = session.createSQLQuery("YOUR SQL HERE");
q.setResultTransformer( Transformers.aliasToBean( MyNotMappedPojoClassHere.class) );
List<MyNotMappedPojoClassHere> postList = q.list();
@Entity
@SqlResultSetMapping(name="ConnexionQueryBean",
entities={
@EntityResult(entityClass=com.collecteJ.business.bean.ConnexionQueryBean.class, fields={
@FieldResult(name="utilisateurId", column="UTILISATEUR_ID"),
@FieldResult(name="nom", column="NOM"),
@FieldResult(name="prenom", column="PRENOM"),
@FieldResult(name="nomConnexion", column="NOM_CONNEXION"),
@FieldResult(name="codeAgence", column="CODE_AGENCE"),
@FieldResult(name="codeBanque", column="CODE_BANQUE"),
@FieldResult(name="codeDevise", column="CODE_DEVISE"),
@FieldResult(name="codeCollecteur", column="CODE_COLLECTEUR")})
})
public class ConnexionQueryBean implements Serializable {
@Id
private long utilisateurId;
private String codeCollecteur;
private String nom;
private String prenom;
private String nomConnexion;
private String codeAgence;
private String codeBanque;
private String codeDevise;
public ConnexionQueryBean() {
}
public long getUtilisateurId() {
return utilisateurId;
}
public void setUtilisateurId(long utilisateurId) {
this.utilisateurId = utilisateurId;
}
public String getCodeCollecteur() {
return codeCollecteur;
}
public void setCodeCollecteur(String codeCollecteur) {
this.codeCollecteur = codeCollecteur;
}
public String getNom() {
return nom;
}
public void setNom(String nom) {
this.nom = nom;
}
public String getPrenom() {
return prenom;
}
public void setPrenom(String prenom) {
this.prenom = prenom;
}
public String getNomConnexion() {
return nomConnexion;
}
public void setNomConnexion(String nomConnexion) {
this.nomConnexion = nomConnexion;
}
public String getCodeAgence() {
return codeAgence;
}
public void setCodeAgence(String codeAgence) {
this.codeAgence = codeAgence;
}
public String getCodeBanque() {
return codeBanque;
}
public void setCodeBanque(String codeBanque) {
this.codeBanque = codeBanque;
}
public String getCodeDevise() {
return codeDevise;
}
public void setCodeDevise(String codeDevise) {
this.codeDevise = codeDevise;
}
@Override
public String toString() {
return "ConnexionQueryBean{" + "utilisateurId=" + utilisateurId + ", codeCollecteur=" + codeCollecteur + ", nom=" + nom + ", prenom=" + prenom + ", nomConnexion=" + nomConnexion + ", codeAgence=" + codeAgence + ", codeBanque=" + codeBanque + ", codeDevise=" + codeDevise + '}';
}
ce n'est pas vraiment une entité car elle ne correspond à aucune table de base de données. Mais les annotations @Entity
et @Id
sont obligatoires pour JPA pour comprendre la cartographie. Si vous ne voulez pas vraiment avoir @Entity / @Id
dans cette classe, vous pouvez supprimer l'annotation @SqlResultSetMapping
et la mettre dans n'importe quelle autre entité aussi loin que JPA peut la Scanner.
, Vous devez également vous assurer que votre @ComponentScan
contenu du paquet correspondant, si vous êtes en utilisant une configuration Java, vous devez explicitement déclarer votre entité dans le répertoire persistence.xml/orm.xml
sous le répertoire META-INF
.
C'est l'appel
String connexionQuery = "SELECT u.UTILISATEUR_ID, u.NOM, u.PRENOM, u.NOM_CONNEXION, a.CODE_AGENCE, a.CODE_BANQUE, a.CODE_DEVISE, c.CODE_COLLECTEUR FROM UTILISATEUR u, AGENCE a, COLLECTEUR c "
+ " WHERE (a.CODE_AGENCE = c.CODE_AGENCE AND u.UTILISATEUR_ID = c.UTILISATEUR_ID AND u.NOM_CONNEXION = '"+nomConnextion+"')";
ConnexionQueryBean ConnexionResults = (ConnexionQueryBean) defaultService.getEntityManager().createNativeQuery(connexionQuery,"ConnexionQueryBean").getSingleResult();
System.out.println(ConnexionResults.toString());
j'utilise Spring, JPA 2.1, Hibernate 5 et Oracle, je pense que cela pourrait ne pas être possible avec la version inférieure de JPA, en savoir plus http://www.thoughts-on-java.org/result-set-mapping-complex-mappings /
QLRM pourrait être une alternative: http://simasch.github.io/qlrm/
il n'est pas lié à une mise en œuvre spécifique de L'app et fonctionne également avec JDBC.