2015-04-13 2 views
8

Я пытаюсь вызвать хранимую процедуру Terminal_GetTicket в моей базе данных, но получает следующее исключение:Как выполнить хранимую процедуру с данными JPA и Spring?

PropertyReferenceException: No property getTicket found for type TicketInfo 

У меня есть крест подтверждена моя конфигурация с очень простым тестом сущностью, и все, кажется, работает хорошо, однако для фактический случай, что-то не так.

Вот мой домен объект (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; 

Все переменные экземпляра имеют свои методы получения и установки правильно определены и хранимая процедура имеет в общей сложности 5 выходных параметров, соответствующих атрибутов TicketInfo.

Кроме того, здесь мой репозиторий интерфейс:

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

Кроме того, здесь мой context.xml файл (на весну):

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

И, наконец, разбавленную версию самой хранимой процедуры :

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

select 0, 1, 2 

RETURN @error 

Теперь, когда я пытаюсь установить @Autowired аннотация, я получаю исключение, упомянутое выше.

+0

Я никогда не делал этого раньше, но у меня есть следующие две догадки (на основе этой ссылки [1]: Кажется, что вы можете либо установить имя хранимой процедуры явным образом, установив @Procedure (name = "TicketInfo .getTicket ") или вы можете выровнять имя процедуры с именем вашего метода (Terminal_GetTicket vs getTicket) [1] https://github.com/spring-projects/spring-data-examples/tree/master/jpa/jpa21 –

+0

Я изменил свой код, как вы предложили, я использовал @Procedure (name = "TicketInfo.getTicket"), но я получаю ту же ошибку. – Rys

ответ

4

Я помню, что я боролся с хранимыми процедурами MS SQL и spring-data-jpa. Это, как я был в состоянии успешно запустить его:

Модель:

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

    /* Fields, getters, setters*/ 
} 

Это довольно просто. Этот подход отличается, хотя вы не декларируете процедуры напрямую (это также причина, по которой он не должен работать, если вы решили изменить RDBS).

Тогда вы должны расширить хранилище:

public interface FooRepositoryCustom { 

    Foo fancyMethodName(arg1, arg2); 
} 

И непосредственно реализовать:

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

Давайте соберем все вместе:

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

} 

Обратите внимание, что если вы решите return, например, список объектов Foo, вы редактируете только возвращаемое значение в своем cu стоп-хранилище.

2

Я следил за советом SirKometas, но я не мог заставить его работать, поэтому я придумал что-то, что сработало для меня, и я думаю, что с точки зрения синтаксиса лучше. Сначала создайте класс сущности, как показано ниже.

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

Тогда классом реализации хранилища будет:

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

Остальная часть реализации, как ответ от SirKometa выше.Подумайте также, что вам нужно создать компонент EntityManager в вашем приложении, чтобы это работало.

Смежные вопросы