Bootiful Spring Boot 3.4:Spring Data

工程 | Josh Long | 2024 年 11 月 24 日 | ...

发布公告博文很好地强调了 Spring Data 2024.1 中的一些新功能。请记住:Spring Data 是一个总括项目,聚合了支持 Couchbase、Redis、MongoDB、JDBC、R2DBC、Neo4J、Apache Cassandra 等数据存储的模块。它是将数据存储连接到应用程序的最简单方法。事实上,我们可以写一本小书来介绍这里的所有新功能!

以下是一些引起我注意的功能。

  • 一个新的 Repository fragments SPI 允许 classpath 上的任何任意 .jar 文件,或者其他包中的代码,通过 Spring.factories 服务工厂机制向 Spring Data 仓库机制贡献扩展。
  • Spring Data JPA 中查询解析开销大大降低
  • Spring Data MongoDB 中的 @TimeSeries 过期
  • Spring Data for Apache Cassandra 中表和用户定义类型的 keyspace 限定
  • Spring Data Cassandra 中使用 CqlGenerator refined CQL 生成
  • Spring Data Redis 在事务和管道操作中支持 Jedis Lua 脚本
  • 使用 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、类 UnixWindows)。

获取 Spring 新闻通讯

通过 Spring 新闻通讯保持联系

订阅

领先一步

VMware 提供培训和认证,助您加速进步。

了解更多

获得支持

Tanzu Spring 提供 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件,只需一份简单的订阅。

了解更多

即将举行的活动

查看 Spring 社区所有即将举行的活动。

查看所有