在Spring中创建动态查询

时间:2015-06-02 20:37:17

标签: spring spring-mvc jpa spring-data

我一直在使用标准JPA实现,并且在创建动态查询时没有问题,因为算法会搜索数据库中的用户。但是,我们正在转向Spring Framework(不幸的是旧版本 - 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 Framework?

4 个答案:

答案 0 :(得分:2)

我不知道我们能不能按你的要求做。 但我可以替代你的方法。

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();
}

答案 1 :(得分:1)

Spring 允许使用@Repository,但强制你这样做。 Spring甚至提供了一个很好的JPA接口,它将低级别的关注点(数据源定义和事务管理)与高级别的关注点(DAO,声明性事务)区分开来。

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

答案 2 :(得分:1)

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

Spring应该允许你这样做:

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

答案 3 :(得分:-1)

请考虑下面的示例。也许您正在寻找类似的东西。尽管您的问题不是很简单,但是想要使用标准或规范,您可以实现很多很棒的事情。

@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();
    }
}