2015-04-13 23 views
8

Sto cercando di chiamare la stored procedure Terminal_GetTicket nel mio database, ma continuo a ricevere la seguente eccezione:Come posso eseguire una stored procedure con JPA e Spring Data?

PropertyReferenceException: No property getTicket found for type TicketInfo 

ho croce convalidato la mia configurazione con un semplice soggetto di prova e tutto sembra funzionare bene, tuttavia per la caso reale, qualcosa non va.

Ecco la mia entità del dominio (TicketInfo):

@Entity 
@NamedStoredProcedureQuery(name = "TicketInfo.getTicket", procedureName = "Terminal_GetTicket", resultClasses = TicketInfo.class, parameters = { 
    @StoredProcedureParameter(mode = ParameterMode.IN, name = "sys_id_game", type = Integer.class)}) 
public class TicketInfo { 

    @Id @GeneratedValue 
    private Long id; 
    private String idTicket; 
    private Integer externalTicketCode; 
    private Short sequenseAlert; 
    private Integer dlTimeStamp; 

Tutte le variabili di istanza hanno i loro getter e setter correttamente definito e la stored procedure dispone di un totale di 5 parametri di output che corrispondono gli attributi di TicketInfo.

Inoltre, qui è la mia interfaccia repository:

public interface TicketInfoRepository extends CrudRepository<TicketInfo, Long> { 
    @Transactional(timeout = 5) 
    @Procedure 
    TicketInfo getTicket(Integer sys_id_game); 
} 

Inoltre, qui è la mia context.xml di file (per la primavera):

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:jpa="http://www.springframework.org/schema/data/jpa" 
    xmlns:context="http://www.springframework.org/schema/context" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:repository="http://www.springframework.org/schema/data/repository" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans-4.0.xsd 
     http://www.springframework.org/schema/context 
     http://www.springframework.org/schema/context/spring-context-4.1.xsd 
     http://www.springframework.org/schema/data/jpa 
     http://www.springframework.org/schema/data/jpa/spring-jpa-1.8.xsd 
     http://www.springframework.org/schema/data/repository 
     http://www.springframework.org/schema/data/repository/spring-repository-1.5.xsd"> 

    <context:component-scan base-package="ar.com.boldt.godzilla" /> 
    <jpa:repositories base-package="xx.xxx.xxx.godzilla.business.dao" /> 

    <bean id="jpaVendorAdapter" 
     class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> 
     <property name="showSql" value="${dataSource.show.sql}" /> 
     <property name="generateDdl" value="false" /> 
     <property name="database" value="SQL_SERVER" /> 
    </bean> 

    <bean id="entityManagerFactory" 
     class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
     <property name="dataSource" ref="dataSource" /> 
     <property name="jpaVendorAdapter" ref="jpaVendorAdapter" /> 
     <!-- spring based scanning for entity classes --> 
     <property name="packagesToScan" value="xx.xxx.xxx.godzilla.business.dao" /> 
    </bean> 

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" /> 

    <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager"> 
     <property name="cacheManager" ref="ehcache" /> 
    </bean> 

    <bean id="ehcache" 
     class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"> 
     <property name="configLocation" value="classpath:ehcache.xml" /> 
    </bean> 
</beans> 

E infine una versione annacquata della stored procedure in sé :

ALTER PROCEDURE [Terminal_GetTicket](
@arg int 
,@res int output 
,@res2 int output 
) 
as 
Declare @error int 

select 0, 1, 2 

RETURN @error 

Ora, ogni volta che provare a impostare ilAnnotazione, ottengo l'eccezione sopra menzionata.

+0

Non l'ho mai fatto prima, ma ho le seguenti due ipotesi (basate su questo collegamento [1]: Sembra che sia possibile impostare il nome della stored procedure in modo esplicito impostando @Procedure (name = "TicketInfo .getTicket ") oppure puoi allineare procedureName con il nome del tuo metodo (Terminal_GetTicket vs getTicket) [1] https://github.com/spring-projects/spring-data-examples/tree/master/jpa/jpa21 –

+0

Ho cambiato il mio codice come suggerito, ho usato @Procedure (name = "TicketInfo.getTicket"), ma ottengo lo stesso errore. – Rys

risposta

4

Ricordo che ho avuto difficoltà con le procedure MS SQL memorizzate e spring-data-jpa. Questo è come sono stato in grado di eseguire con successo:

Modello:

@NamedNativeQueries({ 
    @NamedNativeQuery(
      name = "yourInternalName", 
      query = "EXEC [procedure_name] :param1, :param2", 
      resultClass = Foo.class 
    ) 
}) 
@Entity 
public class Foo{ 

    /* Fields, getters, setters*/ 
} 

Questo è abbastanza semplice. Questo approccio è diverso, tuttavia, non si dichiarano le procedure direttamente (è anche il motivo per cui non deve funzionare se si decide di cambiare RDBS).

Poi si deve estendere la vostra repository:

public interface FooRepositoryCustom { 

    Foo fancyMethodName(arg1, arg2); 
} 

e direttamente implementarlo:

public class FooRepositoryImpl implements FooRepositoryCustom { 


@PersistenceContext 
EntityManager entityManager; 

@Override 
public Foo fancyMethodName(arg1, arg2) { 

    Query query = entityManager.createNamedQuery("yourInternalName"); 
    query.setParameter("param1", arg1); 
    query.setParameter("param2", arg2); 
    return query.getResultList(); 
} 

Mettiamola tutto insieme:

public interface FooRepository extends CrudRepository<Foo, Long>, FooRepositoryCustom { 

} 

Si noti che se si decide di ritorna ad esempio un elenco di oggetti modifichi solo il valore restituito nel tuo cu repository stom.

2

Ho seguito il consiglio di SirKometas ma non sono riuscito a farlo funzionare, quindi mi è venuto in mente qualcosa che ha funzionato per me e penso che dal punto di vista della sintassi è meglio. Per prima cosa crea la tua classe di entità come di seguito.

@NamedStoredProcedureQueries({// 
    @NamedStoredProcedureQuery(// 
      name = "MySP"// 
      , procedureName = "my_sp"// 
      , parameters = { // 
        @StoredProcedureParameter(mode = ParameterMode.IN, name = "arg", type = String.class)}// 
      , resultClasses = Foo.class)//}) 
@Entity 
public class Foo { 

Poi la classe di implementazione del repository sarebbe:

@Component 
public class FooRepositoryImpl implements FooCustomRepository { 

    @PersistenceContext 
    EntityManager entityManager; 

    @Override 
    public List<Foo> foo(String arg) { 
     Query query = entityManager.createNamedStoredProcedureQuery("MySP"); 
     query.setParameter("arg", arg); 
     return query.getResultList(); 
    } 
} 

Il resto l'attuazione è come la risposta da SirKometa sopra.Pensa anche che devi creare un bean EntityManager nell'applicazione perché funzioni.