-
Notifications
You must be signed in to change notification settings - Fork 340
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support dynamic SQL provider [DATAJDBC-319] #542
Comments
Jens Schauder commented If I understand correctly you want an API for generating SQL dynamically. The reason is that there are already many options for this available:
And you can integrate with those technologies using custom methods. So if this is what you want I'll close the issue. |
Sanghyuk Jung commented Here's the API I imagined. public interface ProductRepository extends CrudRepository<Product, String> {
@SelectProvider(type=ProductSql.class, method="select")
@Query(rowMapper=ProducMapper.class)
List<Product> findByName(@Param("name") String name);
} public class ProductSql {
public String select(String name) {
String sql = "SELECT id name FROM product";
if (name !=null ) {
return sql + " WHERE name = :name";
}
return sql;
}
} In this code, the attribute of new annotation( I understand that there is a way as shown in the example of JooqRepositoryImpl . It would be more convenient if I do it without adding a custom interface and an implementation class |
Jens Schauder commented Interesting. How would Spring Data JDBC determine the parameters that actually need binding? I'm currently not at all convinced that this feature is worth its weight since it basically seems to save just a single interface and costs an additional annotation, compared to a custom method. |
Sanghyuk Jung commented As I mentioned, MyBatis supports a similar feature, it can be a reference. Following examples are from http:https://www.mybatis.org/mybatis-3/java-api.html . @SelectProvider(type = UserSqlBuilder.class, method = "buildGetUsersByName")
List<User> getUsersByName(
@Param("name") String name, @Param("orderByColumn") String orderByColumn);
class UserSqlBuilder {
// If not use @Param, you should be define same arguments with mapper method
public static String buildGetUsersByName(
final String name, final String orderByColumn) {
return new SQL(){{
SELECT("*");
FROM("users");
WHERE("name like #{name} || '%'");
ORDER_BY(orderByColumn);
}}.toString();
}
// If use @Param, you can define only arguments to be used
public static String buildGetUsersByName(@Param("orderByColumn") final String orderByColumn) {
return new SQL(){{
SELECT("*");
FROM("users");
WHERE("name like #{name} || '%'");
ORDER_BY(orderByColumn);
}}.toString();
}
} The implementation of MyBatis is at https://github.com/mybatis/mybatis-3/blob/master/src/main/java/org/apache/ibatis/builder/annotation/ProviderSqlSource.java#L106 The ways of MyBatis has the disadvantage of weak inspection at the time of compilation. An alternative is to define a stricter interface , as shown below. // This interface is assumed to be provided by Spring Data JDBC.
public interface QueryProvider {
String getQuery(SqlParameterSource source);
default boolean isNotNull(SqlParameterSource source, String paramName){
return source.hasValue(paramName) && (source.getValue(paramName) != null);
}
// Another helper methods can be added as default methods, for example 'isNotEmpty()'
}
// An implementation class of QueryProvider by the framework user
public class ProductQueryProvider implements QueryProvider {
@Override
public String getQuery(SqlParameterSource source) {
String sql = "SELECT id name FROM product";
if (isNotNull(source, "name")) {
return sql + " WHERE name = :name";
}
return sql;
}
}
// The QueryProvider's implementation class is specified in the Repository interface, similar to the RowMapper's implementation class.
public interface ProductRepository extends CrudRepository<Product, String> {
@Query(rowMapper=ProducMapper.class, queryProvider = productSelectProvider.class)
List<Product> findByName(@Param("name") String name);
} When infrastructure for semantic SQL generation ( https://jira.spring.io/browse/DATAJDBC-309) is merged in the future, this feature will create a larger synergy. If the specifications are confirmed here, I am willing to send pull request |
+1 |
1 similar comment
+1 |
+1 |
2 similar comments
+1 |
+1 |
Recently, I provide a criteria extension, which can implement the feature of dynamic sql. It is similar to the Spring Data JPA Specification. default Page<User> searchByQuery(UserQuery query, Pageable pageable) {
return findAll(Criteria.from(eq(User_.province, query.province))
.and(eq(User_.city, query.city))
.and(like(User_.area, query.area))
.and(like(User_.name, query.nick))
.and(between(User_.created, query.createFrom, query.createTo))
, pageable);
} |
+1 |
Sanghyuk Jung opened DATAJDBC-319 and commented
In MyBatis, Dynamic sql is supported by
@SelectProvider
http:https://kamalmeet.com/java/mybatis-using-selectprovider-and-resultmap/ ( updated link)
It would be more convenient if a similar feature is in Spring Data JDBC
No further details from DATAJDBC-319
The text was updated successfully, but these errors were encountered: