2015-04-13 5 views
8

Ich versuche, die Terminal_GetTicket gespeicherte Prozedur in meiner Datenbank zu nennen, aber halte die folgende Ausnahme erhalten:Wie kann ich eine gespeicherte Prozedur mit JPA- und Spring-Daten ausführen?

PropertyReferenceException: No property getTicket found for type TicketInfo 

Ich habe Kreuz validiert meine Konfiguration scheint mit einer sehr einfachen Testeinheit und alles gut zu funktionieren, aber für die tatsächlicher Fall, etwas stimmt nicht.

Hier ist meine Domain-Einheit (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; 

Alle Instanzvariablen haben ihre Getter und Setter richtig definiert und die gespeicherte Prozedur insgesamt 5 Ausgabeparameter hat die Attribute TicketInfo entsprechen.

Außerdem ist hier meine Repository-Schnittstelle:

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

Auch hier ist meine context.xml Datei (Frühling):

<?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> 

Und schließlich eine verwässerte Version der gespeicherten Prozedur selbst :

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

select 0, 1, 2 

RETURN @error 

Jetzt, wenn ich versuche, dieEinstellungAnnotation, ich bekomme die oben erwähnte Ausnahme.

+0

Ich habe das noch nie gemacht, aber ich habe die folgenden zwei Vermutungen (basierend auf diesem Link [1]: Es scheint, dass Sie den Namen der gespeicherten Prozedur explizit festlegen können, indem Sie @Procedure (name = "TicketInfo .getTicket ") oder Sie können den procedureName mit dem Namen Ihrer Methode (Terminal_GetTicket vs getTicket) verknüpfen [1] https://github.com/spring-projects/spring-data-examples/tree/master/jpa/jpa21 –

+0

Ich habe meinen Code wie vorgeschlagen geändert, ich habe @Procedure (name = "TicketInfo.getTicket") verwendet, aber ich bekomme denselben Fehler. – Rys

Antwort

4

Ich erinnere mich, dass ich mit den gespeicherten MS SQL-Prozeduren und Spring-Data-jpa gekämpft habe. Dies ist, wie ich in der Lage gewesen erfolgreich um es auszuführen:

Modell:

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

    /* Fields, getters, setters*/ 
} 

Das ist ziemlich einfach ist. Dieser Ansatz unterscheidet sich jedoch dadurch, dass Sie Prozeduren nicht direkt deklarieren (das ist auch der Grund, warum es nicht funktionieren muss, wenn Sie sich entscheiden, RDBS zu ändern).

Dann müssen Sie Ihr Repository erweitern:

public interface FooRepositoryCustom { 

    Foo fancyMethodName(arg1, arg2); 
} 

Und es direkt implementieren:

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(); 
} 

Sagen wir es alle zusammen:

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

} 

Beachten Sie, wenn Sie sich entscheiden, Geben Sie zum Beispiel eine Liste von Foo Objekten zurück, die Sie nur Rückgabewert in Ihrem Cu bearbeiten Stom-Repository.

2

Ich folgte SirKometas Rat, aber ich konnte es nicht zum Laufen bringen, also kam ich auf etwas, das für mich funktionierte, und ich denke, vom Syntaxstandpunkt ist besser. Erstellen Sie zuerst Ihre Entitätsklasse wie unten.

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

Dann würde die Implementierungsklasse des Repository sein:

@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(); 
    } 
} 

Der Rest der Implementierung ist wie die Antwort von SirKometa oben.Denken Sie auch, dass Sie eine EntityManager-Bean in Ihrer Anwendung erstellen müssen, damit dies funktioniert.

Verwandte Themen