Spring 数据 JPA - return 未来
Spring Data JPA - return Future
我试图保存我的实体异步和 return 结果的未来,但我遇到了以下问题:
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.Repository;
import org.springframework.scheduling.annotation.Async;
//import org.springframework.stereotype.Repository;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
// I must extend Repository because when I extended JpaRepository an argument
// of save is ambigous when I try save(countryEntity) - compiler shows me
// save (CountryEntity) in AsyncCountryRepository and save (S) in CrudRepository
public interface AsyncCountryRepository extends Repository<CountryEntity, Long> {
// I don't know why I cannot return Future<CountryEntity>
@Async
<S extends CountryEntity> Future<S> save(CountryEntity countryEntity);
// I cannot test it - test is below
@Async
CompletableFuture<CountryEntity> findByCode(String code);
}
@RunWith(SpringRunner.class)
@DataJpaTest
public class CountryRepositoryTest {
@Autowired
private TestEntityManager entityManager;
@Autowired
private AsyncCountryRepository countryRepository;
@Test
public void findByCodeTest() throws Exception {
// given
final CountryEntity countryEntity = new CountryEntity("EN");
final CountryEntity persisted = entityManager.persist(countryEntity);
entityManager.flush();
// when
final Future<CountryEntity> byCode = countryRepository.findByCode(persisted.getCode());
// then
assertThat(byCode.get())
.isEqualTo(persisted);
}
测试 returns 失败,我得到 expected:<CountryEntity(id=1, code=EN)> but was:<null>
如何将我的存储库实现为异步存储库以及如何对其进行测试?
哪种方法性能更好:
1. return 来自存储库的期货
2. 运行 存储库方法在 ExecutorService 中可调用
?
如果您使用 @Async
,存储库代码将在它自己的事务中的单独线程中运行。由于您的原始事务未提交,因此它不会看到更改(即插入的实体),因此 null
结果。
所以为了让它工作,你需要提交第一个事务。
关于性能的第二个问题(请下次单独提问):多线程代码的性能取决于很多东西,真正唯一有用的回答方法是:尝试。但是,如果您安排执行的方式对性能的影响比线程池和连接池大小等因素更大,我会感到惊讶。
我试图保存我的实体异步和 return 结果的未来,但我遇到了以下问题:
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.Repository;
import org.springframework.scheduling.annotation.Async;
//import org.springframework.stereotype.Repository;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
// I must extend Repository because when I extended JpaRepository an argument
// of save is ambigous when I try save(countryEntity) - compiler shows me
// save (CountryEntity) in AsyncCountryRepository and save (S) in CrudRepository
public interface AsyncCountryRepository extends Repository<CountryEntity, Long> {
// I don't know why I cannot return Future<CountryEntity>
@Async
<S extends CountryEntity> Future<S> save(CountryEntity countryEntity);
// I cannot test it - test is below
@Async
CompletableFuture<CountryEntity> findByCode(String code);
}
@RunWith(SpringRunner.class)
@DataJpaTest
public class CountryRepositoryTest {
@Autowired
private TestEntityManager entityManager;
@Autowired
private AsyncCountryRepository countryRepository;
@Test
public void findByCodeTest() throws Exception {
// given
final CountryEntity countryEntity = new CountryEntity("EN");
final CountryEntity persisted = entityManager.persist(countryEntity);
entityManager.flush();
// when
final Future<CountryEntity> byCode = countryRepository.findByCode(persisted.getCode());
// then
assertThat(byCode.get())
.isEqualTo(persisted);
}
测试 returns 失败,我得到 expected:<CountryEntity(id=1, code=EN)> but was:<null>
如何将我的存储库实现为异步存储库以及如何对其进行测试?
哪种方法性能更好: 1. return 来自存储库的期货 2. 运行 存储库方法在 ExecutorService 中可调用 ?
如果您使用 @Async
,存储库代码将在它自己的事务中的单独线程中运行。由于您的原始事务未提交,因此它不会看到更改(即插入的实体),因此 null
结果。
所以为了让它工作,你需要提交第一个事务。
关于性能的第二个问题(请下次单独提问):多线程代码的性能取决于很多东西,真正唯一有用的回答方法是:尝试。但是,如果您安排执行的方式对性能的影响比线程池和连接池大小等因素更大,我会感到惊讶。