我正在开发一个Spring应用程序,并在一个存储库上定义各种查找方法:
@Repository
public interface TicketRepository extends JpaRepository<TicketEntity, Long> {
List<TicketEntity> findByTicketId(@Param("ticketId") Long ticketId);
List<TicketEntity> findByTicketIdAndState(@Param("ticketId") Long ticketId, @Param("state") String state);
List<TicketEntity> findByTicketIdAndStateAndFlagged(@Param("ticketId") Long ticketId, @Param("state") String state, @Param("flagged") String Flagged);
}
问题是我有30列,可以选择对其进行筛选。这将导致存储库方法变得笨拙:
List<TicketEntity> findByTicketIdAndStateAndFlaggedAndCol4AndCol5AndCol6AndCol7AndCol8AndCol9AndCol10AndCol11AndCol12AndCol13AndCol14AndCol15AndCol16AndCol17AndCol18AndCol19AndCol120....);
JPA层应该如何设计以适应这种情况?
如果我创建一个具有属性的对象:
public class SearchObject {
private String attribute1;
//Getter and Setters
.
.
.
.
}
我可以将<code>SearchObject</code>传递到一个查找方法中,Spring JPA将根据哪些属性为空来确定要插入哪些属性和用于哪些属性的语句-如果属性不为空,则为该属性生成相应的语句。
使用Spring Data JPA规范
细节解决方案:耐心等待
首先,创建一个SpecificationCriteria类来定义您的准则。这意味着将列过滤为键,将值过滤为值
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class SpecificationCriteria {
private String key;
private Object value;
}
然后创建规范标准构建器以构建您的标准
@Service
public class SpecificationCriteriaBuilder {
public List<SpecificationCriteria> buildCriterias(String name) {
List<SpecificationCriteria> specificationCriterias = new ArrayList<SpecificationCriteria>();
if (!StringUtils.isEmpty(name)) {
specificationCriterias
.add(SpecificationCriteria.builder().key("name")
.value(name).build());
}
// Here you can add other filter one by one
return specificationCriterias;
}
}
然后创建一个SpecificationBuilder类来构建您的规范。您可以从过滤器选项(标准)列表构建到规范列表
import java.util.List;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
@Service
public class SpecificationBuilder<T> {
public Specification<T> buildSpecification(List<SpecificationCriteria> specificationCriterias) {
if (ObjectUtils.isEmpty(specificationCriterias)) {
return null;
}
Specification<T> specification = getSpecification(specificationCriterias.get(0));
for (int index = 1; index < specificationCriterias.size(); index++) {
SpecificationCriteria specificationCriteria = specificationCriterias.get(index);
specification =
Specification.where(specification).and(getSpecification(specificationCriteria));
}
return specification;
}
public Specification<T> getSpecification(SpecificationCriteria specificationCriteria) {
Specification<T> specification = new Specification<T>() {
private static final long serialVersionUID = 2089704018494438143L;
@Override
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
return builder.equal(root.get(specificationCriteria.getKey()),
specificationCriteria.getValue());
}
};
return specification;
}
}
在服务中首先构建标准,然后使用它们构建规范。然后在存储库调用中使用规范
@Service
@Transactional
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class UserService {
private final SpecificationCriteriaBuilder criteriaBuilder;
private final SpecificationBuilder<User> specificationBuilder;
private final UserRepository userRepository;
public List<User> getAll(String name) {
List<SpecificationCriteria> specificationCriterias =
criteriaBuilder.buildCriterias(name); // here you can pass other parameter as function argument
Specification<User> specification =
specificationBuilder.buildSpecification(specificationCriterias);
List<User> users = userRepository.findAll(specification);// pass the specifications
return users;
}
存储库扩展JpaSpecificationExecutor
@Repository
public interface UserRepository extends JpaRepository<User, Integer>, JpaSpecificationExecutor<User> {
}
@AllArgsConstructor公共类TicketFilter{
private final String col1;
private final Integer col2;
public Optional<String> getCol1() {
return Optional.ofNullable(col1);
}
public Optional<Integer> getCol2() {
return Optional.ofNullable(col2);
}
}
创建规范类:
公共类票证规范实现规范 {
private final TicketFilter ticketFilter;
public TicketSpecification(TicketFilter ticketFilter) {
this.ticketFilter = ticketFilter;
}
@Override
public Predicate toPredicate(Root<Ticket> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
List<Predicate> predicates = new ArrayList<>();
ticketFilter.getTitle().ifPresent(col1 -> predicates.add(getCol1Predicate(root, col1)));
ticketFilter.getDescription().ifPresent(col2 -> predicates.add(getCol2Predicate(root, col2)));
return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
}
私有谓词getCol1Predicate(根,根,字符串标题){return Root.get(“col1”).in(col1);}
}
使用您的存储库:ticketRepository.findAll(规范);
问题内容: 我正在使用Hibernate Validator 4.0.2,Spring 3.0和Hibernate 3.3.2(据我所知,是JPA2之前的版本)作为JPA 1提供程序。 我发现将Validator集成到MVC层很容易(这是可行的),但是看不到如何将验证器自动集成到JPA entityManager(JPA 1)中。 基本上,我有一些实体将保留下来,但它们不是来自Web层,因此尚未经
这很有魅力: 但如果我想按多个单词搜索,它将不返回任何内容,例如: 当我使用CURL时,我通过将添加到我的JSON属性来解决这个问题: 卷曲-XGET“http://localhost:9200/_search“-d”{“查询”:{“匹配”:{“字段”:{“查询”:“word\u 1 word\u 2”,““模糊性”:“自动”,““运算符”:“和”}}}}}” 我如何在Java中实现这一点?
问题内容: 我想在Monoose中将两个OR查询与AND结合在一起,例如以下SQL语句: 我在NodeJS模块中尝试了此操作,该模块仅从主应用程序获取模型对象: 但这是行不通的,所有OR条件都将像下面的SQL语句一样连接在一起: 如何在猫鼬中结合AND 和AND 的两个条件? 问题答案: 直接按以下方式创建查询对象可能是最简单的: 但是,您也可以使用最新的3.x Mongoose版本中提供的帮助程
本文向大家介绍我们可以结合使用MySQL IN AND LIKE运算符吗?,包括了我们可以结合使用MySQL IN AND LIKE运算符吗?的使用技巧和注意事项,需要的朋友参考一下 是的,我们可以使用LIKE和OR运算符在MySQL中组合IN和LIKE运算符。让我们首先创建一个表- 使用插入命令在表中插入一些记录- 使用select语句显示表中的所有记录- 输出结果 这将产生以下输出- 以下是在
我们有一个现有的谓词来从表中获取数据,我们还需要将此条件添加到该查询中 我们尝试了不同的方法,但我们所能做到的就是 简单括号应在<代码>或 之后开始,并应在最终条件之后结束。 我们试过这些 步骤-1 步骤-2 我们能得到一些帮助吗?
问题内容: 给定此选择器: 它将匹配一个正文,该正文的类包含 page-node-add- 的子字符串,而类恰好是 page-node-edit 我想说匹配第一个或第二个(但不能同时匹配)。可能吗? 使用逗号的问题: 如果我有一个长选择器,例如: 我原本以为CSS3可以解决这个问题,但是我想到的是: 谢谢 问题答案: 您需要使用逗号将它们分开: 使用逗号的问题: …是除了逗号以外,您无法做其他任何