Spring Data JPA SpEL - @Query问题

6

我遇到了使用SPEL和Spring Data JPA的问题

以下是我的Repository

package eg.repository;
public interface MyEntityRepository extends JpaRepository<MyEntity, Long>,JpaSpecificationExecutor<MyEntity> {

    @Query("SELECT e FROM eg.domain.MyEntity e " +
            "WHERE e.title = :#{#filter.title}"
    )
    Page<MyEntity> list1(@Param("filter") MyFilter filter,Pageable pageable);
}

过滤组件

package eg.service;

import org.springframework.stereotype.Component;

@Component("filter")
public class MyFilter {

    public String titleFilter() {
        return "%title%";
    }
    private String title = "title title1";
    public Long[] idFilter() {
        return new Long[] {
                1L, 2L
        };
    }
}

以下是MyEntity

package eg.domain;
@Entity
public class MyEntity implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "title")
    private String title;
    ......
}

主类

LOG.info("Application initialized " + annotationConfigApplicationContext);
        MyEntityRepository myEntityRepository =
                    (MyEntityRepository) annotationConfigApplicationContext.getBean(MyEntityRepository.class);
        MyFilter filter = annotationConfigApplicationContext.getBean(MyFilter.class);
        PageRequest pageRequest = new PageRequest(0, 5);
        Page<MyEntity> page = myEntityRepository.list1(filter,pageRequest);
        List<MyEntity> entities= page.getContent();
        for(MyEntity entity: entities){
            System.out.println(entity.getId() + " TITLE " +  entity.getTitle());
        }

以下是我遇到的错误:
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myEntityRepository': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalStateException: Using named parameters for method public abstract org.springframework.data.domain.Page eg.repository.MyEntityRepository.list1(eg.service.MyFilter,org.springframework.data.domain.Pageable) but parameter 'filter' not found in annotated query 'SELECT e FROM eg.domain.MyEntity e WHERE e.title = :#{#filter.title}'!

为什么你不直接将标题作为参数传递,而是像这样 @Query("SELECT e FROM eg.domain.MyEntity e WHERE e.title = :filter") - Uwe Allner
我只是在尝试让Spel与Spring Data一起工作。一旦这个成功了,我计划添加更复杂的东西,就像在idFilter()等方法中所看到的那样。 - ArunM
我也无法让一个简单的#{#variable}表达式正常工作。 - RedDeckWins
3个回答

1
当我在查询花括号内遗漏了“addtional” # 字符时,我遇到了相同的问题,所以在你的情况下,你会有:
@Query("SELECT e FROM eg.domain.MyEntity e     WHERE e.title = ?#{filter.title}"

但应该有。
@Query("SELECT e FROM eg.domain.MyEntity e     WHERE e.title = ?#{#filter.title}"

注意: 使用?#{filter.title}代替?#{#filter.title}"

这并不完全匹配您粘贴的代码,但可能会帮助其他人。


1

使用SpEL访问传递参数对象的值通常很顺利,即使您的语法似乎是正确的。

也许再与Spring Data JPA和SpEL进行比较。

您真的确定错误消息确实属于您发布的代码吗?您后来进行了调整吗?我简化了一下,这是一个有效的测试用例示例。

实体:

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class MyEntity {

    @Id
    @GeneratedValue
    private Long id;

    private String title;

    public MyEntity(String title) {
        this.title = title;
    }

    public Long getId() {
        return id;
    }

    public String getTitle() {
        return title;
    }

}

代码库:

package com.example.repository;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import com.example.model.MyEntity;
import com.example.model.MyFilter;

public interface MyEntityRepository extends JpaRepository<MyEntity, Long> {

    @Query("SELECT e FROM MyEntity e WHERE e.title = :#{#filter.title}")
    Page<MyEntity> list1(@Param("filter") MyFilter filter, Pageable pageable);

}

“过滤器”:
package com.example.model;

public class MyFilter {

    private String title;

    public MyFilter(String title) {
        this.title = title;
    }

    public String getTitle() {
        return title;
    }

}

并且相关的测试:

package com.example.repository;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.PageRequest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;

import com.example.model.MyEntity;
import com.example.model.MyFilter;

@RunWith(SpringRunner.class)
@Transactional
@SpringBootTest
public class MyEntityRepositoryTests {

    @Autowired
    private MyEntityRepository myEntityRepository;

    @Test
    public void insertAndReceiveEntityBySpEL() {
        final String titleA = "A";
        final String titleB = "B";

        final MyEntity entityA = new MyEntity(titleA);
        final MyEntity entityB = new MyEntity(titleB);
        final MyEntity entityB2 = new MyEntity(titleB);

        myEntityRepository.save(entityA);
        myEntityRepository.save(entityB);
        myEntityRepository.save(entityB2);

        final MyFilter filterA = new MyFilter(titleA);
        final MyFilter filterB = new MyFilter(titleB);

        assertThat("Expected one hit for value A!", myEntityRepository.list1(filterA, new PageRequest(0, 5)).getContent().size(), is(1));
        assertThat("Expected two hits for value B!", myEntityRepository.list1(filterB, new PageRequest(0, 5)).getContent().size(), is(2));
    }

}

也许你可以简化一下代码,找出具体的问题所在。SpEL表达式应该不是真正的问题。
还有一些其他的东西也不可能是错误的原因,但仍然很奇怪:
-
  • 什么是titleFilter()idFilter()方法?你在这里没有使用它,并且查询也不会使用它。

  • -
  • 你如何在运行时设置/调整MyFilter对象的成员title的值?它只是硬编码的吗?因此没有getter,JPA应该如何访问和使用它进行比较?

  • -
  • 为什么你的Repository要扩展JpaSpecificationExecutor

  • 最后一件事最令人困惑。你是否想要使用Specifications?那么你需要一些Predicate检查来实现你的“Filter”。

    0
    private String title = "title title1";
    

    过滤器的标题是私有的,我无法看到任何获取此属性的方法。也许这就是问题所在。


    不行了..我已经尝试了getter,但没有运气。 - ArunM
    你尝试过其他替代方案,比如 ?#{filter.title} 吗? - Diptopol Dam

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接