我正在使用Spring Data JPA,以违反直觉的行为运行以下测试结果
@Test
public void testAsync() throws ExecutionException, InterruptedException {
Job job = jobRepository.save(new Job());
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
long origJobID = job.getId();
executor.initialize();
Future<?> wait = executor.submit(() -> {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
Job outcome = jobRepository.save(job.setStopTime(Instant.now()));
// this assertion fails, Hibernate requested a new ID and persisted a new entity ... even though I am reusing the same instance with an ID already populated
assertEquals(origJobID, outcome.getId().longValue());
});
wait.get();
}
进一步研究Hibernate的代码库,它出现在一个新线程上,persistentContext被清除干净。因此,就DefaultMergeEventListener
而言,我的实体变成了分离状态...创建了一系列决策,这些决策莫名其妙地导致生成一个新ID
我引用的特定代码位于:https://github.com/hibernate/hibernate-orm/blob/master/hibernate-core/src/main/java/org/hibernate/event/internal/defaultmergeeventlistener.java#l109
如果从一个新线程运行,Hibernate的持久性上下文是空的...这很好....但我不明白为什么我的实体现在被认为是超然的...
更多摘自Hibernate源代码的内容:Default https://github.com/hibernate/hibernate-orm/blob/master/hibernate-core/src/main/java/org/hibernate/event/internal/defaultmergeeventlistener.java#L293
if ( result == null ) {
//TODO: we should throw an exception if we really *know* for sure
// that this is a detached instance, rather than just assuming
//throw new StaleObjectStateException(entityName, id);
// we got here because we assumed that an instance
// with an assigned id was detached, when it was
// really persistent
entityIsTransient( event, copyCache );
}
如果这与事务尚未提交有关,并且新线程没有使用相同的事务,请编辑...是否有方法在代码中强制执行事务?
注意调用jparepository.saveandflush()
不能解决此问题
编辑2我将使用embedded h2进行此测试,无论哪种情况,我都希望saveandflush()
已经将事务提交到数据库(嵌入的或在世界的另一端),以便多个线程可以使用JPararePository查看其他线程保存的状态,对吗?
编辑3查看其他类似的问题,它似乎将测试方法本身标记为@transaction(propagation=NOT_SUPPORTED)强制底层事务管理器提交jparepository.save()
...这仍然令人困惑...测试方法一开始是如何事务性的?即为什么交易没有从一开始就提交?
关于它的工作原理的一个非常粗略的想法:
EntityManager
通常是事务绑定的(每个事务都有自己的EntityManager
,它根据该事务查看事情)你正在做的是
通过确保线程1在步骤3时已经提交,您应该能够实现这一工作。被执行。无论如何,我不建议在线程之间传递托管实体引用,因为它非常棘手,非常快。
关于Spring数据事务分界,您可以阅读https://docs.Spring.io/spring-data/jpa/docs/current/reference/html/#transactions了解更多信息,但它基本上涉及将每个事务变成一个方法,然后对该方法进行注释。
我正在运行RxJava并创建一个主题以使用方法生成数据。我正在使用Spring。 这是我的设置: 在RxJava流上生成新数据的方式是通过Autowire private SubjectObserver SubjectObserver,然后调用SubjectObserver。发布(newDataObjGenerated) 无论我为subscribeOn()指定了什么 Schedulers.io()
线程n:usern:task1->task2->Task3,usern:task1->task2->Task3,usern:task1->task2->Task3,... 然而,我还不知道如何做到这一点。每次我运行测试时,所有线程似乎都在迭代CSV文件并混合用户时选择用户,直到同时在两个不同的线程上找到一个用户。 像这样: 线程n:usern:task1->task2->Task3,...,use
问题内容: 在我拥有的一个小程序(尤其是cgo调用)上,go build和go run非常慢。我想缓存二进制文件,以便仅在源文件较新时才重建。我会使用带有%规则的简单Makefile,但是语言设计人员声称go的构建支持不需要Makefile。 我还有其他选择吗?go社区是否愿意使用另一个构建系统(可能是基于哈希的构建系统)来缓存和重用构建产品? 问题答案: 我写了一个工具来解决这个问题。单独不会检
我正在使用Python和tkinter创建一个游戏,当我试图添加一些音乐时,制作音乐的函数停止了脚本的其余部分(还有窗口)。所以我需要创建一个新的线程来播放音频并保持窗口工作... 我尝试了一些错误、不运行或停止窗口的事情,目前我有: 重要的细节:playSound函数什么也不返回,所以什么都不需要等待它。我也不太懂用Python编程,我更喜欢用Luau。
问题内容: 是否可以在运行时创建hibernate的Entity类(带有注释)?它应与也在运行时中添加的表相关。重要的是,该实体应该对Hibernate可见。一般情况下是否可能,请您给我有关该问题的任何建议吗?我了解,反射是关键字,但需要更多的单词。问候。 问题答案: 在这种情况下,您可能希望在运行时以编程方式创建Hibernate Session Factory,并传入创建的新映射,请访问htt