为何Spring Boot集成MicroStream始终加载初始版本数据?
问题:Spring Boot集成MicroStream后数值无法持久化更新
我在Spring Boot中使用MicroStream编写测试示例:首次启动时创建DemoSession对象并存储到嵌入式存储;第二次启动加载该对象后将其numValue属性自增1,但后续每次启动加载的numValue始终为0。transaction*slt文件每次运行都会增大,看起来新值似乎被加载,但根对象每次启动都处于初始状态。
示例代码
package test.microstream; import jakarta.annotation.PostConstruct; import lombok.AllArgsConstructor; import lombok.Data; import lombok.ToString; import lombok.extern.slf4j.Slf4j; import one.microstream.integrations.spring.boot.types.Storage; import one.microstream.storage.types.StorageManager; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import java.util.HashMap; import java.util.Map; @SpringBootApplication @Slf4j public class MicrostreamApplication { public static void main(String[] args) { SpringApplication.run(MicrostreamApplication.class, args); } @AllArgsConstructor @Data @ToString public static class DemoSession { String account; int numValue; } @Data @ToString @Storage public static class DemoStorage { Map<String, DemoSession> sessions; @PostConstruct public void init() { if(sessions == null) { sessions = new HashMap<>(); } } public void setSession(DemoSession session) { sessions.put(session.getAccount(), session); } public DemoSession getSession(String account) { return sessions.get(account); } } @Autowired DemoStorage storage; @Autowired StorageManager storageManager; @Bean public ApplicationRunner runner() { return new ApplicationRunner() { @Override public void run(ApplicationArguments args) throws Exception { log.info("root {}", storageManager.root()); log.info("storage {}", storage); var session = storage.getSession("acc"); if(session == null) { session = new DemoSession("acc", 0); log.info("create session {}", session); storage.setSession(session); storageManager.storeRoot(); } else { log.info("loaded session {}", session); session.setNumValue(session.getNumValue()+1); log.info("update session {}", session); storageManager.storeRoot(); } log.info("after all"); log.info("root {}", storageManager.root()); log.info("storage {}", storage); } }; } }
程序运行输出
2023-02-14T21:35:32.947+01:00 INFO 163817 --- [ main] one.microstream.util.logging.Logging : MicroStream Version 08.00.00-MS-EA2 2023-02-14T21:35:33.089+01:00 INFO 163817 --- [ main] .s.e.t.EmbeddedStorageFoundation$Default : Creating embedded storage manager 2023-02-14T21:35:33.206+01:00 INFO 163817 --- [ main] .t.PersistenceTypeHandlerManager$Default : Initializing type handler manager 2023-02-14T21:35:33.266+01:00 INFO 163817 --- [ main] o.m.s.e.t.EmbeddedStorageManager$Default : Starting embedded storage manager 2023-02-14T21:35:33.268+01:00 INFO 163817 --- [ main] o.m.storage.types.StorageSystem$Default : Starting storage system 2023-02-14T21:35:33.269+01:00 INFO 163817 --- [ main] .m.s.t.StorageStructureValidator$Default : Storage structure validated successfully. 2023-02-14T21:35:33.295+01:00 INFO 163817 --- [ main] .t.PersistenceTypeHandlerManager$Default : Initializing type handler manager 2023-02-14T21:35:33.308+01:00 INFO 163817 --- [ main] o.m.s.e.t.EmbeddedStorageManager$Default : Embedded storage manager initialized 2023-02-14T21:35:33.366+01:00 INFO 163817 --- [ main] t.microstream.MicrostreamApplication : Started MicrostreamApplication in 0.963 seconds (process running for 1.278) 2023-02-14T21:35:33.367+01:00 INFO 163817 --- [ main] t.microstream.MicrostreamApplication : root MicrostreamApplication.DemoStorage(sessions={acc=MicrostreamApplication.DemoSession(account=acc, numValue=0)}) 2023-02-14T21:35:33.367+01:00 INFO 163817 --- [ main] t.microstream.MicrostreamApplication : storage MicrostreamApplication.DemoStorage(sessions={acc=MicrostreamApplication.DemoSession(account=acc, numValue=0)}) 2023-02-14T21:35:33.367+01:00 INFO 163817 --- [ main] t.microstream.MicrostreamApplication : loaded session MicrostreamApplication.DemoSession(account=acc, numValue=0) 2023-02-14T21:35:33.367+01:00 INFO 163817 --- [ main] t.microstream.MicrostreamApplication : update session MicrostreamApplication.DemoSession(account=acc, numValue=1) 2023-02-14T21:35:33.367+01:00 INFO 163817 --- [ main] .t.PersistenceTypeHandlerManager$Default : Initializing type handler manager 2023-02-14T21:35:33.372+01:00 INFO 163817 --- [ main] t.microstream.MicrostreamApplication : after all 2023-02-14T21:35:33.372+01:00 INFO 163817 --- [ main] t.microstream.MicrostreamApplication : root MicrostreamApplication.DemoStorage(sessions={acc=MicrostreamApplication.DemoSession(account=acc, numValue=1)}) 2023-02-14T21:35:33.372+01:00 INFO 163817 --- [ main] t.microstream.MicrostreamApplication : storage MicrostreamApplication.DemoStorage(sessions={acc=MicrostreamApplication.DemoSession(account=acc, numValue=1)}) 2023-02-14T21:45:18.225+01:00 INFO 163817 --- [ionShutdownHook] o.m.storage.types.StorageSystem$Default : Stopping storage system 2023-02-14T21:45:18.227+01:00 INFO 163817 --- [ionShutdownHook] o.m.storage.types.StorageSystem$Default : Storage system stopped
依赖配置
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>one.microstream</groupId> <artifactId>microstream-storage-embedded</artifactId> <version>08.00.00-MS-EA2</version> </dependency> <dependency> <groupId>one.microstream</groupId> <artifactId>microstream-integrations-spring-boot3</artifactId> <version>08.00.00-MS-EA2</version> </dependency> <dependency> <groupId>one.microstream</groupId> <artifactId>microstream-storage-embedded-configuration</artifactId> <version>08.00.00-MS-EA2</version> </dependency> </dependencies>
解决方案
问题根源
MicroStream的持久化规则是:只有新添加到根对象引用链中的对象,或者明确调用store()方法的对象才会被持久化。你修改了DemoSession的numValue后,仅调用storageManager.storeRoot(),但DemoSession是已存在的对象,根对象DemoStorage对它的引用没有变化,因此MicroStream不会自动将修改后的实例写入存储。transaction文件变大只是因为写入了根对象的重复状态,并未实际保存DemoSession的更新值。
修复步骤
在更新DemoSession的numValue后,调用storageManager.store(session)来明确存储修改后的实例:
else { log.info("loaded session {}", session); session.setNumValue(session.getNumValue()+1); log.info("update session {}", session); storageManager.store(session); // 新增该行,持久化修改后的Session对象 storageManager.storeRoot(); }
补充说明
如果有多个Session对象需要更新,也可以使用storageManager.storeAll(storage.getSessions().values())批量存储,但单独存储修改后的对象性能更优。
内容的提问来源于stack exchange,提问作者bit wheeze
相关产品推荐
相关产品推荐

