在 Spring 中创建动态查询

Create a Dynamic Query in Spring

我使用标准 JPA 实现已有一段时间了,在创建由算法生成的动态查询以在数据库中搜索用户时没有遇到任何问题。但是,我们正在转向 Spring 框架(不幸的是旧版本 - 3.2),我根本不知道如何在 Spring.

中创建动态查询

有了 javax.persistance.EntityManager,我可以调用 createQuery 并给它一个字符串来处理。但是,我发现在 Spring 中,我只能在注释中定义查询的地方使用类似下面的代码。

@Repository
@SuppressWarnings("unused")
public interface PersonRepository extends JpaRepository<Person, Long>, CrudRepository<Person, Long> {

    @Override
    List<Person> findAll(Sort sort);

    @Override
    List<Person> findAll();

    @Query("SELECT p FROM Person p ORDER BY p.lname ASC, p.fname ASC, p.mname ASC")
    List<Person> findAllSort();

    @Query("SELECT p FROM Person p WHERE UPPER(p.userName) = UPPER(?1)")
    Person findPersonByUsername(String username);


}

这是我可以为您复制的最简单的动态查询示例,我想为 Spring:

public List<Person> getPersons(List<Long> perIds) {
    List<Person> persons;
    String whereClause = "";
    for (int i = 0; i < perIds.size(); i++) {
        if (i != 0)
            whereClause += " OR ";
        whereClause += "p.perId = '" + perIds.get(i) + "'";
    }
    persons = em.createQuery("SELECT p FROM Person p WHERE " + whereClause).getResultList();
    return persons;
}

也许更好的问题 这里是询问是否可能,或者我是否应该只使用实体管理器来保留我的实现。话虽这么说,有人会 推荐 我将我的代码从使用 EntityManager 改成使用 Spring 框架吗?

不知道能不能按照您的要求做。 但是我有一个替代方法。

public List<Person> getPersons(List<Long> perIds) {
    return em.createQuery(
        "SELECT p FROM Person p WHERE p.perId = " 
        + org.springframework.util.StringUtils.collectionToDelimitedString(perIds, " OR p.perId = ", "'", "'")
    ).getResultList();
}

Spring 允许您使用@Repository,但不会强制您这样做。 Spring 甚至提供了一个很好的 JPA 接口,将低级问题(数据源定义和事务管理)与高级问题(DAO,具有声明性事务)分开。

chapter Spring Framework Reference Manual 中有一篇关于 JPA 的文章。您还应该阅读前面章节中有关事务管理的部分。

为什么不使用 IN 查询条件呢?

Spring 应该允许你做:

@Query( "SELECT p FROM Person p WHERE p.perId in :ids" )
findPersonsInIdList(@Param("ids") List<Long> perIds);

请考虑以下 example.May 如果您看起来像 this.Though 您的问题不是很直截了当,您 want.Using 的标准或规范是什么,您可以实现很多很酷的事情。

@Service 

Optional<Person> findByEmail(String email);


@NoRepositoryBean
public interface PersonRepositoryCustom {
    Optional<Person> findByEmail(String email);
}

@Repository
public class PersonRepositoryImpl extends QuerydslRepositorySupport implements PersonRepositoryCustom {
    public PersonRepositoryImpl() {
        super(Person.class);
    }

    @Override
    public Optional<Person> findByEmail(String email) {
        JPAQuery<Person> query = getQuerydsl()
                .createQuery()
                .from(QPerson.person)
                .where(QPerson.person.email.equalsIgnoreCase(email))
                .select(QPerson.person);
        return query.fetch().stream().findFirst();
    }
}