Working with JPA 2.0, every time I need to create a new bean (named PersonDetail) from the result of a query, I create a NamedQuery like this:
A constructor with the desired output should be set in the PersonDetail bean.
But using the NativeQuery, this is not possible as the Query will be executed like it is given.
In fact while creating the query (NativeQuery or NamedQuery), we can fore the result to be the desired Bean, but this will generate this error:
org.hibernate.MappingException: Unknown entity: org.nd.enterprise.bean.PersonDetail
This is normal as it accepts only an Entity and not a Class (See this post to know how to fix that with JPA2.0). Fortenately JPA2.1 comes with the solution, by adding the @ConstructorResult in the @SqlResultSetMapping where you cone construct your Class (In JPA 2.0 only the Entity cn be specified and not another POJO .)
1 2 3 | @NamedQuery(name="findPerson", query = "SELECT new org.nd.enterprise.bean.PersonDetail(e.personId, e.birthDate)" + " FROM Person p WHERE p.personId = :person") |
A constructor with the desired output should be set in the PersonDetail bean.
But using the NativeQuery, this is not possible as the Query will be executed like it is given.
In fact while creating the query (NativeQuery or NamedQuery), we can fore the result to be the desired Bean, but this will generate this error:
1 2 3 4 | // Here we declare a @NamedNativeQuery List<PersonDetail> rec = entityManager.createNamedQuery("findPerson", PersonDetail.class).getResultList(); // Here we declare just a String query = "select ...." List<PersonDetail> rec2 = entityManager.createNativeQuery(query,PersonDetail.class).getResultList(); |
org.hibernate.MappingException: Unknown entity: org.nd.enterprise.bean.PersonDetail
This is normal as it accepts only an Entity and not a Class (See this post to know how to fix that with JPA2.0). Fortenately JPA2.1 comes with the solution, by adding the @ConstructorResult in the @SqlResultSetMapping where you cone construct your Class (In JPA 2.0 only the Entity cn be specified and not another POJO .)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | Query q = em.createNativeQuery( "SELECT personId, birthDate)" + " FROM Person p", "PersonDetailsResult"); @SqlResultSetMapping( name="PersonDetailsResult", classes={ @ConstructorResult( targetClass=org.nd.enterprise.bean.PersonDetail, columns={ @ColumnResult(name="personId"), @ColumnResult(name="birthDate") } ) } ) |
I have tried ConstructorResult with JPA 2.1 but it always returns list of objects to me. Here is my code
ReplyDeletefinal String SELECT_EXPIRED_OFFLINE_TRANSFERS = "select "
+ "b.paymnt_ref_number, b.request_date, b.paymnt_amt, b.paymnt_status_code, a.trans_date,b.payer_fi_id, b.payee_fi_userid ,a.trans_initiated_by"
+ "from payment_status_history a, payments b "
+ "where a.trans_date >= :fiTransStartDate "
+ "and a.trans_date < :fiTransEndDate "
+ "and a.paymnt_ref_number = b.paymnt_ref_number "
+ "and a.paymnt_status_code = b.paymnt_status_code ";
Query query = em().createNativeQuery(SELECT_EXPIRED_OFFLINE_TRANSFERS,"OfflineUnsuccessfulTransferResultSet");
@SqlResultSetMapping(name = "OfflineUnsuccessfulTransferResultSet", classes = {
@ConstructorResult(
targetClass = OfflineUnsuccessfulTransferInfo.class,
columns = {
@ColumnResult(name = "paymnt_ref_number"),
@ColumnResult(name = "request_date"),
@ColumnResult(name = "paymnt_amt"),
@ColumnResult(name = "paymnt_status_code"),
@ColumnResult(name = "trans_date"),
@ColumnResult(name = "Fi_Id"),
@ColumnResult(name = "name"),
@ColumnResult(name = "last_changed_by")
})
})
public class OfflineUnsuccessfulTransferInfo {
private String paymentRefNumber;
private Date requestDate;
private String recipientName;
private BigDecimal amount;
private String lastChangedBy;
private PaymentStatus paymentStatus;
private String fiId;
private String fiName;
private Date transactionDate;
public OfflineUnsuccessfulTransferInfo(String paymentRefNumber, Timestamp requestDate, BigDecimal amount, BigDecimal paymentStatus, Timestamp transactionDate, String fiId, String recipientName, String lastChangedBy) {
this.paymentRefNumber = paymentRefNumber;
this.requestDate = requestDate;
this.recipientName = recipientName;
this.amount = amount;
this.lastChangedBy = lastChangedBy;
// this.paymentStatus = paymentStatus;
this.fiId = fiId;
this.transactionDate = transactionDate;
}
Getter/Setters
}
How can i return list of my objects
I think the problem is in the constructor, You declare your paymentStatus once as PaymentStatus and once as BigDecimal.
Delete" The target class must define a constructor taking the same number of arguments and types as defined by the columns.".
DeleteYou can even define your columns type :
@ColumnResult(name="paymnt_ref_number", type=String.class),
.......
Thanks Mariem for looking into it. Finally i was able to figure out the problem, actually i was using older version of hibernate due to which it was not using sqlResultMapping. I had following dpendecies in my pom, so though i had updated JPA version but still it was running with older hibernate version which does not support JPA2.1
ReplyDeleteorg.hibernate
hibernate-entitymanager
4.1.7.Final
org.hibernate.javax.persistence
hibernate-jpa-2.1-api
1.0.0.Final
After updating hibernate-entitymanager jar to latest version it worked fine locally. But now i am struggling to run it on Jboss server as jboss injects jpa2.0 version. I tried to follow below blog but it gives me below mentioned error. Any clue about that?
http://mariemjabloun.blogspot.ca/2014/03/use-jboss-jpa-21-and-hibernate-43-on.html
Error: nested exception is java.lang.NoSuchMethodError: javax.persistence.Table.indexes()[Ljavax/persistence/Index;
Why not using Wildfly 8 which comes with JPA 2.1 .
DeleteThis comment has been removed by a blog administrator.
ReplyDelete