我正在回答这个问题,在单个表的日期、整数和字符串数据类型字段上执行多列搜索?并且该方法必须返回Java 8中类型specification
实际上,我想在关联实体中搜索,以及全局搜索的一部分。使用JPA2规范API
是否可能?
我有Employee
和Department
@onetomany双向
关系。
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Entity
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "EMPLOYEE_ID")
private Long employeeId;
@Column(name = "FIRST_NAME")
private String firstName;
@Column(name = "LAST_NAME")
private String lastName;
@Column(name = "EMAIL_ID")
private String email;
@Column(name = "STATUS")
private String status;
@Column(name = "BIRTH_DATE")
private LocalDate birthDate;
@Column(name = "PROJECT_ASSOCIATION")
private Integer projectAssociation;
@Column(name = "GOAL_COUNT")
private Integer goalCnt;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "DEPT_ID", nullable = false)
@JsonIgnore
private Department department;
}
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Entity
public class Department implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "DEPT_ID")
private Long departmentId;
@Column(name = "DEPT_NAME")
private String departmentName;
@Column(name = "DEPT_CODE")
private String departmentCode;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "department")
@JsonIgnore
private Set<Employee> employees;
}
@SpringBootApplication
public class MyPaginationApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(MyPaginationApplication.class, args);
}
@Autowired
private EmployeeRepository employeeRepository;
@Autowired
private DepartmentRepository departmentRepository;
@Override
public void run(String... args) throws Exception {
saveData();
}
private void saveData() {
Department department1 = Department.builder()
.departmentCode("AD")
.departmentName("Boot Depart")
.build();
departmentRepository.save(department1);
Employee employee = Employee.builder().firstName("John").lastName("Doe").email("john.doe@gmail.com")
.birthDate(LocalDate.now())
.goalCnt(1)
.projectAssociation(2)
.department(department1)
.build();
Employee employee2 = Employee.builder().firstName("Neha").lastName("Narkhede").email("neha.narkhede@gmail.com")
.birthDate(LocalDate.now())
.projectAssociation(4)
.department(department1)
.goalCnt(2)
.build();
Employee employee3 = Employee.builder().firstName("John").lastName("Kerr").email("john.kerr@gmail.com")
.birthDate(LocalDate.now())
.projectAssociation(5)
.department(department1)
.goalCnt(4)
.build();
employeeRepository.saveAll(Arrays.asList(employee, employee2, employee3));
}
}
EmployeeController.java
@GetMapping("/employees/{searchValue}")
public ResponseEntity<List<Employee>> findEmployees(@PathVariable("searchValue") String searchValue) {
List<Employee> employees = employeeService.searchGlobally(searchValue);
return new ResponseEntity<>(employees, HttpStatus.OK);
}
java
public class EmployeeSpecification {
public static Specification<Employee> textInAllColumns(Object value) {
return (root, query, builder) -> builder.or(root.getModel().getDeclaredSingularAttributes().stream()
.filter(attr -> attr.getJavaType().equals(value.getClass()))
.map(attr -> map(value, root, builder, attr))
.toArray(Predicate[]::new));
}
private static Object map(Object value, Root<?> root, CriteriaBuilder builder, SingularAttribute<?, ?> a) {
switch (value.getClass().getSimpleName()) {
case "String":
return builder.like(root.get(a.getName()), getString((String) value));
case "Integer":
return builder.equal(root.get(a.getName()), value);
case "LocalDate":
return builder.equal(root.get(a.getName()), value);//date mapping
default:
return null;
}
}
private static String getString(String text) {
if (!text.contains("%")) {
text = "%" + text + "%";
}
return text;
}
}
当我点击/employeese/{searchValue}
时,我希望在department
表和employee
表中进行搜索(可能使用joins
类似)。这可能吗?如果是,我们怎么做?
@Query("SELECT t FROM Todo t WHERE " +
"LOWER(t.title) LIKE LOWER(CONCAT('%',:searchTerm, '%')) OR " +
"LOWER(t.description) LIKE LOWER(CONCAT('%',:searchTerm, '%'))")
List<Todo> findBySearchTerm(@Param("searchTerm") String searchTerm);
有什么指示吗?
如果你看看我的帖子,实际上我有一个加入的解决方案
@Override
public Specification<User> getFilter(UserListRequest request) {
return (root, query, cb) -> {
query.distinct(true); //Important because of the join in the addressAttribute specifications
return where(
where(firstNameContains(request.search))
.or(lastNameContains(request.search))
.or(emailContains(request.search))
)
.and(streetContains(request.street))
.and(cityContains(request.city))
.toPredicate(root, query, cb);
};
}
private Specification<User> firstNameContains(String firstName) {
return userAttributeContains("firstName", firstName);
}
private Specification<User> lastNameContains(String lastName) {
return userAttributeContains("lastName", lastName);
}
private Specification<User> emailContains(String email) {
return userAttributeContains("email", email);
}
private Specification<User> userAttributeContains(String attribute, String value) {
return (root, query, cb) -> {
if(value == null) {
return null;
}
return cb.like(
cb.lower(root.get(attribute)),
containsLowerCase(value)
);
};
}
private Specification<User> cityContains(String city) {
return addressAttributeContains("city", city);
}
private Specification<User> streetContains(String street) {
return addressAttributeContains("street", street);
}
private Specification<User> addressAttributeContains(String attribute, String value) {
return (root, query, cb) -> {
if(value == null) {
return null;
}
ListJoin<User, Address> addresses = root.joinList("addresses", JoinType.INNER);
return cb.like(
cb.lower(addresses.get(attribute)),
containsLowerCase(value)
);
};
}
private String containsLowerCase(String searchField) {
return "%" + searchField.toLowerCase() + "%";
}
在这里,您可以看到我是如何通过用户的地址列(城市和街道)搜索用户的。
Edit:同样,您也不能很好地使用@query
注释(您可以很好地插入参数值,但不能插入参数。这就是Specificaion方便的地方)
我想在Spring-Boot后端创建一个多字段搜索。如何使用实现这一点? 环境 前端的UI是Jquery DataTable。每列允许应用单个字符串搜索项。跨多个列的搜索词由联接。 看来QueryDSL是解决这个问题的更简单、更好的方法。我在用Gradle。我需要改变我的构造吗?
我在Spring Data JPA中有两个实体: 目标是获取与user\u id相关的所有税款: User.java 税务ayment.jva 我不想要一个太多的注释从User.java和列映射在纳税user_id。 规格等级如下: 根据我获取所有与user\u id相关的税款的目标,规范是正确的还是错误的?
我按照本教程获得了Spring Data JPA规范:https://dzone.com/articles/using-spring-data-jpa-specification 它为我实现了这一点,但我不能调用规范方法来搜索它们。我想把它们放在我的SearchController中: 现在我想在我的SearchController(比如Controller)中调用这个方法,但我不知道如何调用。目
我有一个带有枚举列的实体: 其中枚举声明如下所示: 我尝试实施搜索规范: 我得到一个错误: 登上塔斯克斯塔斯。2769df0841;嵌套异常为java。lang.IllegalArgumentException:BoardingTaskStatus上没有枚举常量。2769df0841]具有根本原因java。lang.IllegalArgumentException:BoardingTaskStat
我正在尝试将查询转换为JPA规范,该查询包含带OR条件的连接操作。 以下是查询: 我试图编写一个规范,但在如何将多个列与OR条件连接方面遇到了障碍。 用户实体: 运营实体 我希望有一个规范来取代上面的查询
我正在开发一个库API,我的目标是搜索一本书。目前这本书有两个我想搜索的有趣值:标题和简介(书背面的文本)。 底层数据库是MariaDB。 我构建了一个JPA查询: query和query2的内容相同。对于单词搜索,这种方法效果很好,但当两个或多个单词混合在简介和标题中时,这种方法就停止了。这是可以理解的。 我的第二次尝试是将每个术语拆分为字符串值列表。 这也不起作用。应用程序无法编译。 是否有方