2014-06-11 29 views
9

Próbuję odwzorować natywny wynik SQL na moje POJO. Oto konfiguracja. Używam sprężyny.Błąd pobierania Nie można znaleźć odpowiedniego konstruktora na klasie

<bean id="ls360Emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" > 
    <property name="dataSource" ref="ls360DataSource" /> 
    <property name="jpaVendorAdapter" ref="vendorAdaptor" />   
    <property name="packagesToScan" value="abc.xyz"/> 
    <property name="jpaProperties"> 
     <props> 
      <prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop> 
      <prop key="hibernate.max_fetch_depth">3</prop> 
      <prop key="hibernate.jdbc.fetch_size">50</prop> 
      <prop key="hibernate.jdbc.batch_size">10</prop> 
      <prop key="hibernate.show_sql">true</prop>    
     </props>   
    </property> 
</bean> 

Oto moja klasa

@SqlResultSetMapping(
    name="courseCompletionMapping", 
    classes = { 
     @ConstructorResult(targetClass = CourseCompletion.class, 
      columns={ 
       @ColumnResult(name = "StoreId", type = String.class), 
       @ColumnResult(name = "ProductId", type = String.class), 
       @ColumnResult(name = "UserName", type = String.class), 
       @ColumnResult(name = "Score", type = Integer.class), 
       @ColumnResult(name = "CompletionDate", type = Date.class) 
      } 
     ) 
    } 
) 
@Entity 
public class CourseCompletion { 
    private String storeId; 

    @Id 
    private String productId; 
    private String userName; 
    private int score; 
    private Date completionDate; 

    public CourseCompletion() { 
    } 

    public CourseCompletion(String storeId, String productId, String userName, int score, Date completionDate) { 
     this.storeId = storeId; 
     this.productId = productId; 
     this.userName = userName; 
     this.score = score; 
     this.completionDate = completionDate; 
    } 

    // getters and setters 

Oto jak Wołam go

Properties coursePropertiesFile = SpringUtil.loadPropertiesFileFromClassPath("course.properties"); 
    String queryString = coursePropertiesFile.getProperty("course.completion.sql"); 

    long distributorId = 1; 
    String fromDate = "2009-09-22 00:00:00"; 
    String toDate = "2014-04-11 23:59:59"; 

    Query query = em.createNativeQuery(queryString, "courseCompletionMapping"); 

    //Query query = em.createNamedQuery("findAllEmployeeDetails"); 
    query.setParameter("distributorId", distributorId); 
    query.setParameter("fromDate", fromDate); 
    query.setParameter("toDate", toDate); 

    @SuppressWarnings("unchecked") 
    List<CourseCompletion> courseCompletionList = query.getResultList(); 

Ale kiedy przychodzi do linii

List<CourseCompletion> courseCompletionList = query.getResultList(); 

pojawia się błąd, że

Could not locate appropriate constructor on class : mypackage.CourseCompletion 

Oto zapytanie, które staram

select d.DISTRIBUTORCODE AS StoreId, u.USERGUID AS ProductId, u.UserName, 
    lcs.HIGHESTPOSTTESTSCORE AS Score, lcs.CompletionDate 
from VU360User u 
inner join learner l on u.ID = l.VU360USER_ID 
inner join LEARNERENROLLMENT le on le.LEARNER_ID = l.ID 
inner join LEARNERCOURSESTATISTICS lcs on lcs.LEARNERENROLLMENT_ID = le.ID 
inner join customer c on c.ID = l.CUSTOMER_ID 
inner join DISTRIBUTOR d on d.ID = c.DISTRIBUTOR_ID 
where d.ID = :distributorId 
and lcs.COMPLETIONDATE is not null 
and (lcs.COMPLETIONDATE between :fromDate and :toDate) 
and lcs.COMPLETED = 1 

Dlaczego otrzymuję ten błąd?

Dzięki

Odpowiedz

27

Ten wyjątek dzieje ponieważ JPA nie zmienia typów kolumn zwrócony z bazy danych dla rodzimych zapytaniami. Z tego powodu masz niedopasowanie typu. Nie jestem pewien, która kolumna powoduje ten problem w twoim przypadku (zależy to od DBMS, którego używasz), ale podejrzewam, że masz BigInteger w zestawie wyników zamiast Integer dla kolumny wynik. Aby mieć 100% pewności, dodaj punkt przerwania do ConstructorResultColumnProcessor.resolveConstructor(Class targetClass, List<Type> types) i sprawdź. Po znalezieniu niezgodności zmień typ pola w klasie odwzorowania.

Innym rozwiązaniem nie będzie w ogóle używać @SqlResultSetMapping. Ponieważ Twoja klasa CourseCompletion jest jednostką zarządzaną, powinieneś być w stanie bezpośrednio zamapować na nią zapytanie natywne. Aby uzyskać więcej informacji, patrz this question.

+3

Dzięki :). Rozwiązałem problem. Debuguję program, a następnie stwierdzam, że kolumna wyniku jest podwójnego typu. Potem po prostu zrobiłem '@ ColumnResult (name =" Score ", type = Double.class)' i zmieniono typ wyniku na 'Double'. – Basit

+1

Dziękuję bardzo :). Pomogło to w debugowaniu. W moim przypadku problem był spowodowany java.sql.Datetime. Hibernacja konwertuje datetime z kolumny Microsoft SQL na java.util.Datetime. Po zmianie typu kolumny na java.util.Datetime została ona rozwiązana. –

+0

Dziękuję bardzo :). Pomogło to w debugowaniu. W moim przypadku problem był spowodowany przez java.sql.Timestamp. Hibernacja konwertuje datetime z kolumny Microsoft SQL na java.util.Date. Po zmianie typu kolumny na java.util.Date została ona rozwiązana. – whoami