当前位置: 首页 > 知识库问答 >
问题:

Spring数据JPA Spel-@Query问题

苏昂雄
2023-03-14

我无法让SPEL和Spring data jpa正常工作

以下是我的仓库

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}'!

共有3个答案

巫马修然
2023-03-14

通过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应该如何访问并使用它进行比较?

    为什么您的存储库要扩展JpaSpecificationExecutor

    最后一件事是最令人困惑的。有没有可能你想使用规范?然后你需要一些谓词检查来实现你的“过滤器”。

  • 何涵衍
    2023-03-14
    private String title = "title title1";
    

    过滤器的标题是私有的,我看不到这个属性的任何getter。可能是这个问题。

    郤浩慨
    2023-03-14

    当我错过了查询花括号中的“附加”#字符时,我也有同样的问题,所以在你的情况下,你会有:

    @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}"

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

     类似资料:
    • 包org.springframework.data.neo4j.annotation中的注释@Query提供了某些计数属性,如CountQuery、CountQueryName。 有人能解释一下这些的用法吗?更具体地说,我写了一个查询来获取关于一个主题的帖子。查询结果将被分页。下面的查询工作正常,并给我的结果。 现在我还需要结果的总数,我是否必须为此编写另一个查询,或者是否有一种方法可以容纳计数查

    • 问题内容: 我需要使用hibernate模式执行SQL查询(无映射),但是只要字段在MYSQL中具有TEXT数据类型,我都会不断收到此错误: 我不知道该怎么办,映射不是一种选择(数据库中的动态表,因此字段数是可变的)。 这是一段代码: sql是一个包含查询的字符串(使用mysql查询引擎可以正常运行)。如果我将TEXT数据类型更改为varchar,则可以正常工作,但这不是一个选择! 有什么线索吗?

    • 假设我有那些DTO: 在我的存储库中,我使用这些DTO作为投影进行查询: 我可以使用这个repo很好地访问ForumDTO中的id、name,但对于lasthread,它只返回null。我试过作为最后一个线程。Id、lastThread\u Id、lastThreadId均无效。

    • 您能帮助我在Spring Data Mongodb中使用@Query查找使用日期的数据吗? 我在下面提供了我的代码: 存储库类: ServiceImpl类: RestController类: Mongo数据库内的数据供客户收集: 如果我用日期字符串“2016-07-19T14:38:54.439Z”调用下面的URL,即使数据库中没有2016-07-19之后创建的记录,它仍然会返回2个结果(以上2个

    • 我在ES上运行查询,但参数的数量正在增加(由于业务原因)。 根据Spring数据弹性搜索中的文档,您可以使用和有序参数,如,等,用于方法签名中给出的参数,但这种方法似乎有点不舒服 是否可以进行类似于的查询,换句话说,使用SpEL访问参数属性? 而不是以一系列参数的方法结束,比如 更像jpa使用的spring数据 或者是否有其他方法可以在不离开spring数据接口的情况下进行查询?

    • 我使用的是spring-data-jpa。我写了一个本机查询,但它不起作用。这是我的实体类: 以下是查询: 起初,当我没有编写nativeQuery=true时,应用程序没有构建,我得到了一个异常“加入jpa的预期路径”。当我设置nativeQuery=true时,应用程序已启动,但当我调用该函数时,我收到以下错误: 是否有任何其他设置或注释可以解决此问题?我在谷歌上搜索过,但在所有情况下都有两个