具有动态 where 子句的 Spring 数据 JPA

Posted

技术标签:

【中文标题】具有动态 where 子句的 Spring 数据 JPA【英文标题】:Spring data JPA with dynamic where clause 【发布时间】:2017-05-25 19:17:25 【问题描述】:

我有一个基础存储库,比如IBaseRepository,它是

public interface IBaseRepository<T extends BaseEntity<PK>, PK extends Serializable>
      extends JpaRepository<T, PK>, JpaSpecificationExecutor<T>  

现在每个存储库类,例如UserRepository 都从这个基础存储库扩展。如何添加通用方法,例如

T findOne(String filter, Map<String, Object> params);

对于所有继承的类,以便调用

Map<String,Object> params = new HashMap<String,Object>();
params.put("username","Lord");
params.put("locked",Status.LOCKED);
userRepo.findeOne("username = :username AND status = :locked",params);

用动态 where 子句返回一条记录。

【问题讨论】:

我不认为你可以这样做,你应该使用 JPA 查询。 您不能这样做,出于性能原因,JPA 查询已预编译。如果你想要动态的东西,你必须自己构建一个查询。 好吧,谢谢你们。我是这么想的。 你可以create a custom repository implementation。 【参考方案1】:

您可以执行以下操作

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.NoRepositoryBean;

import java.io.Serializable;
import java.util.Map;

/**
 * Created by shazi on 1/11/2017.
 */
@NoRepositoryBean
public interface IBaseRepository<T, ID extends Serializable> extends JpaRepository<T, ID>, JpaSpecificationExecutor<T> 

    T findOne(String filter, Map<String, Object> params);


并实现如下。

import org.springframework.data.jpa.repository.support.JpaEntityInformation;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.io.Serializable;
import java.util.Map;

/**
 * Created by shazi on 1/11/2017.
 */
public class BaseRepositoryImpl<T, ID extends Serializable>
        extends SimpleJpaRepository<T, ID> implements IBaseRepository<T, ID> 

    private final EntityManager entityManager;

    private final JpaEntityInformation entityInformation;

    public BaseRepositoryImpl(JpaEntityInformation entityInformation,
                            EntityManager entityManager) 
        super(entityInformation, entityManager);

        // Keep the EntityManager around to used from the newly introduced methods.
        this.entityManager = entityManager;
        this.entityInformation = entityInformation;
    

    @Override
    public T findOne(String filter, Map<String, Object> params) 
        final String jpql = "FROM " + entityInformation.getEntityName() + " WHERE " + filter;
        Query query = entityManager.createQuery(jpql);
        for (Map.Entry<String, Object> value:params.entrySet()) 
            query.setParameter(value.getKey(), value.getValue());
        
        return (T) query.getSingleResult();
    

并配置如下

@Configuration
@EnableJpaRepositories(repositoryBaseClass = BaseRepositoryImpl.class)
@EnableTransactionManagement
public class RepoConfig 

或在 XML 中

<repositories base-class="….BaseRepositoryImpl" />

终于可以如下使用了;

User found = userRepository.findOne("name = :name", Collections.singletonMap("name", "name"));

但您必须确保您的查询 WHERE 始终只返回 1 个结果。看到这个post

【讨论】:

以上是关于具有动态 where 子句的 Spring 数据 JPA的主要内容,如果未能解决你的问题,请参考以下文章

如何在sql中创建动态where子句?

如何在 SQL 的 WHERE 子句中动态调用列

如何使用动态数组使用where子句查询mysql数据库

在实体框架中使用动态 where 子句

使用多个where子句在spring数据jpa中删除

如何从 Firestore 7.24.0 实例中查询具有多个 where 子句的数据?