J'essaie de mapper les résultats d'une requête native sur un POJO à l'aide de @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é n'est prise en charge que 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 mapping in jpa 2.1 . Mais je n'ai toujours pas de chance.
Qu'est-ce que je rate? Pourquoi le SqlResultSetMapping ne peut-il pas être trouvé?
javax.persistence.PersistenceException: org.hibernate.MappingException: Unknown SqlResultSetMapping [foo]
@SqlResultSetMapping
annotation ne doit pas être placé sur un POJO. Mettez-le à (n'importe quel) classe @Entity
. "Unknown SqlResultSetMapping [foo]" vous indique que le fournisseur JPA ne voit aucun mappage sous le nom "foo". S'il vous plaît voir une autre de mes réponses pour le bon exemple
Exemple de travail court:
DTO POJO class
@lombok.Getter
@lombok.AllArgsConstructor
public class StatementDto {
private String authorName;
private Date createTime;
}
Bean de référentiel:
@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;} // <- workaround
}
Je suis capable de 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();
J'ai une réponse légèrement variée qui vient juste de la réponse de wildloop.
Voici ma réponse:
Classe Constants: Constants.Java
public class Constants {
public final String TESTQUERYRESULT_MAPPING_NAME = "TestQueryResultMapping";
}
Classe de mappage des résultats: TestQueryResult.Java
import lombok.Getter;
import lombok.Setter;
import javax.persistence.Entity;
import javax.persistence.EntityResult;
import javax.persistence.FieldResult;
import javax.persistence.Id;
import javax.persistence.SqlResultSetMapping;
@Getter
@Setter
@SqlResultSetMapping(
//name = "TestQueryResultMapping"
name = Constants.TESTQUERYRESULT_MAPPING_NAME
,entities = @EntityResult(
entityClass = TestQueryResult.class
,fields = {
@FieldResult(name = "rowId", column = "row_id")
,@FieldResult(name = "rowName", column = "row_name")
,@FieldResult(name = "value", column = "row_value")
}
)
)
@Entity
public class TestQueryResult {
@Id
private Integer rowId;
private String rowName;
private String value;
}
Alors ... quelque part dans mon code d'implémentation de référentiel:
public class TestQueryRepository {
//... some code here to get the entity manager here
public TestQueryResult getTopMost(Integer rowName) {
//... some code here
String queryString = "... some query string here" + rowName;
TestQueryResult testQueryResult = null;
//this.entityManager.createNativeQuery(queryString ,"TestQueryResultMapping").getResultList();
List<TestQueryResult> results = this.entityManager.createNativeQuery(queryString ,Constants.TESTQUERYRESULT_MAPPING_NAME).getResultList();
if (results != null && !results.isEmpty()) {
testQueryResult = results.get(0);
}
return testQueryResult;
}
}
... alors violah! J'ai eu quelques résultats: D!
À votre santé,
Artanis Zeratul
QLRM pourrait être une alternative: http://simasch.github.io/qlrm/
Il n'est pas lié à une implémentation JPA spécifique et fonctionne également avec JDBC.