领先一步
VMware 提供培训和认证,助您加速进步。
了解更多发布公告博文很好地强调了 Spring Data 2024.1 中的一些新功能。请记住:Spring Data 是一个总括项目,聚合了支持 Couchbase、Redis、MongoDB、JDBC、R2DBC、Neo4J、Apache Cassandra 等数据存储的模块。它是将数据存储连接到应用程序的最简单方法。事实上,我们可以写一本小书来介绍这里的所有新功能!
以下是一些引起我注意的功能。
.jar 文件,或者其他包中的代码,通过 Spring.factories 服务工厂机制向 Spring Data 仓库机制贡献扩展。@TimeSeries 过期CqlGenerator refined CQL 生成JedisClientConfigBuilderCustomizer 接口来自定义 JedisClientConfig。我想谈谈一个可能改变我游戏规则的功能:值表达式的出现,这是一个花哨的说法,意思是可以使用 Spring Expression Language (SpEL) 或属性占位符解析表达式中的一个或两个来参数化 Spring Data 模块中的查询。
值表达式的功能是基于一个您可以在应用程序中使用的漂亮的底层 API。
package com.example.bootiful_34.data;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.env.Environment;
import org.springframework.data.expression.ValueEvaluationContext;
import org.springframework.data.expression.ValueExpressionParser;
import org.springframework.data.expression.ValueParserConfiguration;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.test.context.DynamicPropertyRegistrar;
import org.springframework.test.context.DynamicPropertyRegistry;
@SpringBootTest
@Import(ValueExpressionDynamicPropertyRegistrar.class)
class ValueExpressionTest {
@Test
void test(@Autowired Environment environment) {
var configuration = (ValueParserConfiguration) SpelExpressionParser::new;
var context = ValueEvaluationContext.of(environment, new StandardEvaluationContext());
var parser = ValueExpressionParser.create(configuration);
var expression = parser.parse("${message}-#{ (6 * 7) + ''}");
var result = expression.evaluate(context);
Assertions.assertEquals("ni hao-42", result);
}
}
@Configuration
class ValueExpressionDynamicPropertyRegistrar implements DynamicPropertyRegistrar {
@Override
public void accept(DynamicPropertyRegistry registry) {
registry.add("message", () -> "ni hao");
}
}
在此示例中,我正在测试中使用底层 ValueEvaluationContext,在该测试中,我动态添加了一个属性:message,其值为问候语 ni hao。该测试会解析一个 String,该 String 包含一个属性占位符 ${message} 和一个 SpEL 表达式 #{ (6 * 7) + ''},在其中我们将两个数字相乘,然后将结果表达式转换为 String。结果正如您所料:ni hao-42。
现在您已经看到了可能性,让我们在 Spring Data JDBC 存储库的查询方法定义中检查其中一些。
package com.example.bootiful_34.data;
import org.springframework.data.jdbc.repository.query.Query;
import org.springframework.data.repository.ListCrudRepository;
import java.util.Collection;
interface CustomerRepository extends ListCrudRepository<Customer, Integer> {
@Query(" select * from #{ #tableName }")
Collection<Customer> all();
@Query(" select * from customer where language = :#{locale.language} ")
Collection<Customer> findCustomersBySystemLanguage();
// this is new! support for property placeholder resolution in queries!
@Query("select * from customer where os = :${os.name} ")
Collection<Customer> findCustomersHavingSameOperatingSystemAsUs();
}
第一个查询依赖于一个 SpEL 上下文,该上下文提供了查询方法中引用的实体的表名(在本例中,Customer 属于 customer SQL 数据库)。
在第二个示例查询中,我们匹配通过 EvaluationContextExtension 贡献的自定义上下文。此扩展程序仅在 SpEL 执行期间使用户的 Locale 可用。
💡 提示
您是否知道 LocaleContextHolder?它自 Spring Framework 1.2 以来就一直存在于 Spring 中!它可以获取当前用户的 Locale 对象。因此,想象一下有一个 HTTP 请求进来;Spring MVC 会确定用户的 Locale,然后将其安装在这里。只要您在与请求相同的线程中,就可以随时读取它。很棒。
package com.example.bootiful_34.data;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.data.spel.spi.EvaluationContextExtension;
import org.springframework.stereotype.Component;
import java.util.Locale;
@Component
class LocaleEvaluationContextExtension implements EvaluationContextExtension {
@Override
public String getExtensionId() {
return "locale";
}
@Override
public Locale getRootObject() {
return LocaleContextHolder.getLocale();
}
}
在第三个示例查询中,我们匹配一个系统属性 os.name,它返回用户当前的操作系统(Mac OS X、类 Unix、Windows)。