Spring Boot整合Apache Ignite:通用<String, ProtobufObject>键值存储的创建、SQL查询与存储删除实现咨询
Hey there! Let's break down how to tackle your Ignite key-value store with SQL querying needs step by step. First, we'll fix a critical dependency issue, then move to configuration, cache setup, and operations that fit your requirements.
First off, your dependency versions are out of sync: you're using ignite-spring-data_2.2:2.9.1 but your core Ignite version is set to 2.13.0. This will cause compatibility issues. Update your Spring Data dependency to match the core Ignite version:
<dependency> <groupId>org.apache.ignite</groupId> <artifactId>ignite-spring-data_2.2</artifactId> <version>${ignite.version}</version> <!-- Uses your 2.13.0 version --> </dependency>
Keep the other autoconfigure dependencies as-is, but ensure all Ignite-related versions align.
To fix the @Autowired Ignite ignite issue, you need a valid Ignite bean in your Spring context. If you're using a client node (most common for Spring Boot apps), create a configuration class to define the Ignite instance:
@Configuration public class IgniteConfig { @Bean public Ignite igniteInstance() { IgniteConfiguration cfg = new IgniteConfiguration(); cfg.setClientMode(true); // Run as client, not a server node // Configure discovery to connect to your Ignite cluster TcpDiscoverySpi discoverySpi = new TcpDiscoverySpi(); TcpDiscoveryVmIpFinder ipFinder = new TcpDiscoveryVmIpFinder(); ipFinder.setAddresses(Collections.singletonList("127.0.0.1:47500..47509")); // Update with your cluster addresses discoverySpi.setIpFinder(ipFinder); cfg.setDiscoverySpi(discoverySpi); return Ignition.start(cfg); } }
Now @Autowired Ignite ignite will inject this instance successfully.
ProtobufObject Since you need SQL querying (sorting, pagination), we'll create a cache with explicit query metadata. This maps your Protobuf object's fields to SQL columns (critical for Ignite to understand how to query the data).
Assuming your ProtobufObject has fields like name (String), timestamp (Long), and value (Double), here's how to set up the cache:
@Service public class ProtobufCacheService { private final Ignite ignite; private Cache<String, ProtobufObject> protobufCache; @Autowired public ProtobufCacheService(Ignite ignite) { this.ignite = ignite; createProtobufCache(); // Initialize cache on service startup } public void createProtobufCache() { // Define how Ignite maps your Protobuf object to SQL columns QueryEntity queryEntity = new QueryEntity(String.class, ProtobufObject.class) .setTableName("PROTOBUF_STORE") // SQL table name for queries .addQueryField("cacheKey", String.class.getName(), "KEY") // Map cache key to SQL column .addQueryField("name", String.class.getName(), "NAME") // Map Protobuf's name field .addQueryField("timestamp", Long.class.getName(), "TIMESTAMP") // Map timestamp field .addQueryField("value", Double.class.getName(), "VALUE") // Map value field .setKeyFieldName("cacheKey"); // Link cache key to the SQL column CacheConfiguration<String, ProtobufObject> cacheCfg = new CacheConfiguration<>("ProtobufCache") .setQueryEntities(Collections.singleton(queryEntity)) .setIndexedTypes(String.class, ProtobufObject.class); // Enable indexing for fast SQL queries // Create cache if it doesn't exist protobufCache = ignite.getOrCreateCache(cacheCfg); }
Note: For generated Protobuf classes, Ignite will automatically use getter methods (like getName(), getTimestamp()) to access fields, so no extra work is needed here.
Add Data
// Add single entry public void addEntry(String key, ProtobufObject obj) { protobufCache.put(key, obj); } // Bulk add entries public void addBulkEntries(Map<String, ProtobufObject> entries) { protobufCache.putAll(entries); }
SQL Query with Sorting & Pagination
Use Ignite's SqlFieldsQuery for flexible, native SQL support:
public List<ProtobufObject> queryWithSortAndPagination(String nameFilter, int pageSize, int pageNumber) { int offset = pageSize * (pageNumber - 1); // SQL query with filter, sorting, and pagination String sql = """ SELECT * FROM PROTOBUF_STORE WHERE NAME LIKE ? ORDER BY TIMESTAMP DESC LIMIT ? OFFSET ? """; SqlFieldsQuery query = new SqlFieldsQuery(sql) .setArgs("%" + nameFilter + "%", pageSize, offset); // Execute query and map results to ProtobufObject return protobufCache.query(query) .getAll() .stream() .map(row -> row.get(1)) // Index 1 is the ProtobufObject (index 0 is the key) .map(obj -> (ProtobufObject) obj) .collect(Collectors.toList()); }
When you're done with the store, you can safely destroy it:
public void destroyCache() { if (ignite.cacheExists("ProtobufCache")) { ignite.destroyCache("ProtobufCache"); protobufCache = null; } }
- If you're using a thin client instead of a thick client, adjust the configuration to use
IgniteThinClientConfiguration—the SQL query API remains almost identical. - For complex Protobuf structures, you can use Ignite's
BinaryObjectAPI to serialize objects, but for basic SQL queries, theQueryEntityapproach works perfectly. - Always ensure your Ignite cluster is running before starting your Spring Boot app, or enable auto-start for embedded nodes if you're testing locally.
内容的提问来源于stack exchange,提问作者Capitano Giovarco

