保持领先
VMware 提供培训和认证,以加速您的进步。
了解更多发布公告博客很好地突出了 Spring Data 2024.1 中的许多功能。请记住:Spring Data 是一个伞形项目,聚合了支持 Couchbase、Redis、MongoDB、JDBC、R2DBC、Neo4J、Apache Cassandra 和无数其他数据存储的模块。 它是将数据存储连接到应用程序的最简单方法。 实际上,我们可以用这里的所有新功能写一本小书!
以下是一些引起我注意的功能。
.jar
,或者实际上是另一个包中的代码,通过 Spring.factories
服务工厂机制为 Spring Data 存储库机制贡献扩展@TimeSeries
的过期时间CqlGenerator
改进的 CQL 生成JedisClientConfigBuilderCustomizer
接口自定义 JedisClientConfig
。我想谈谈一个可能会改变我的事情的功能:值表达式的最终实现,这是一种花哨的说法,即可以使用 Spring 表达式语言 (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
,该字符串依次具有属性占位符 ${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)。