【问题标题】:How to Execute a Query stored as String with Spring Data JPA?如何使用 Spring Data JPA 执行存储为字符串的查询?
【发布时间】:2017-04-20 16:02:45
【问题描述】:

我以编程方式将我的 SQL 查询构造为字符串,并希望将其作为 SQL 语句执行,但我使用的是 Spring Data JPA,无法将 JDBC 与 Prepared Statements 一起使用。这在 JPA 中可行吗?

public class Polygon {

public static void main(String[] args) {

    // Build Lat/Longs

    Set<String[]> coordinates = new HashSet<>();

    coordinates.add(new String[]{"42", "-72.95333862304689"});
    coordinates.add(new String[]{"42.05337156043361", "-71.06643676757814"});
    coordinates.add(new String[]{"41.32732632036624", "-71.06643676757814"});
    coordinates.add(new String[]{"41.32732632036624", "-72.95333862304689"});
    coordinates.add(new String[]{"42.05337156043361", "-72"});

    // Trim & Build Query

    String query = "SELECT * FROM SITE WHERE (LATITUDE LIKE ";

    for(String[] c : coordinates){

        c[0] += ".0";
        c[1] += ".0";

        String[] latArray = c[0].split("\\.");
        String[] lngArray = c[1].split("\\.");

        String lat = latArray[0] + "." + latArray[1].substring(0, 1) + "%";
        String lng = lngArray[0] + "." + lngArray[1].substring(0, 1) + "%";

        query += lat + " AND LONGITUDE LIKE " + lng + ") OR (LATITUDE LIKE ";
    }

    query = query.substring(0, query.length() - 20) + ");";
    System.err.println(query);

    /* 
     * This is the Query I am printing, which is correct
     * 
     * SELECT * FROM SITE 
     * WHERE (LATITUDE LIKE 41.3% AND LONGITUDE LIKE -71.0%) 
     *    OR (LATITUDE LIKE 42.0% AND LONGITUDE LIKE -72.0%) 
     *    OR (LATITUDE LIKE 42.0% AND LONGITUDE LIKE -72.9%) 
     *    OR (LATITUDE LIKE 42.0% AND LONGITUDE LIKE -71.0%) 
     *    OR (LATITUDE LIKE 41.3% AND LONGITUDE LIKE -72.9%);
     *    
     * How to execute this with Spring Data JPA?
     */

    // @Query("SELECT * FROM SITE :where", nativeQuery = true)
    // public List<SiteDTO> executeSiteQuery(@Param("where") String where); 
    // Doesn't Work, because (Syntax error on token ""SELECT * FROM SITE :where"", invalid MemberValuePairs)
}
}

【问题讨论】:

    标签: java sql spring spring-data-jpa


    【解决方案1】:

    您的查询看起来过于动态,Spring Data JPA 注释无法理解。事实上,当您尝试将 SQL 注入参数字段时,您尝试的解决方法将无效,因此框架将阻止您这样做以防止 SQL 注入。

    您可以将自定义行为添加到您的存储库并实现准备好的语句(请参阅如何从 EntityManager here 获取会话)。基本上:

    public class MyRepositoryImpl<SiteDTO, ID extends Serializable>
      extends SimpleJpaRepository<SiteDTO, ID> implements MyRepository<SiteDTO, ID> {
    
      private EntityManager entityManager;
    
      // There are two constructors to choose from, either can be used.
      public MyRepositoryImpl(Class<T> domainClass, EntityManager entityManager) {
        super(domainClass, entityManager);
    
        // This is the recommended method for accessing inherited class dependencies.
        this.entityManager = entityManager;
      }
    
      public List<SiteDTO> executeSiteQuery(List<String> longitudesToMatch, List<String> latitudesToMatch) {
        // Here you can grab the session from the entity manager and create your own query
      }
    } 
    

    否则,如果您认为这太过分了,您可能会考虑在 Spring Service 中执行查询的 or 部分。我的意思是,使用像 public List&lt;SiteDTO&gt; executeSiteQuery(@Param("latitude") String latitude, @Param("longitude") String longitude); 这样的查询并多次调用它。性能较差,但有时简单是值得的。

    【讨论】:

    • 在使用 Spring Boot 时我是否能够获取 EntityManager,因为我们根本没有配置它。这一切都由 Spring 抽象和处理。
    • @jDub9 这是 Spring Boot 最好的部分,您可以获取由框架创建和自动配置的元素,然后根据需要在自定义类中使用它们。
    猜你喜欢
    • 2021-04-01
    • 2015-06-19
    • 2018-09-24
    • 2015-11-25
    • 1970-01-01
    • 2016-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多