我无法让SPEL和Spring数据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}'!
答案 0 :(得分:0)
private String title = "title title1";
过滤器的标题是私有的,我看不到此属性的任何getter。可能是这个问题。
答案 1 :(得分:0)
通过SpEL访问传递的参数对象的值通常像魅力一样,甚至你的语法也是正确的。
可能会再次与Spring Data JPA and 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);
}
&#34;过滤&#34;:
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()
有哪些方法?你没有在这里使用它,它不会被查询使用。
如何在运行时设置/调整title
对象的成员MyFilter
的值?它只是硬编码吗?因此没有getter,JPA应如何访问并使用它进行比较?
为什么您的存储库会扩展JpaSpecificationExecutor
?
最后一件事最令人困惑。您是否可能希望使用Specifications?然后,您需要进行一些Predicate
检查以实现您的过滤&#34;。
答案 2 :(得分:0)
当我在查询花括号中遗漏了“#”字符时,我遇到了同样的问题,所以在您的情况下,您将遇到以下问题:
@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}"
这与您粘贴的代码不完全匹配,但可能会对其他人有所帮助。