字符串集在 Spring JPA 投影接口中不正常
Set of String is not acting normal in Spring JPA Projection Interface
我正在使用投影接口 return 实体的局部视图,局部视图包含一组字符串。我希望 Set 正常工作,但它不是:当我向它添加一个新的字符串时,它会忽略该字符串,请参见下面的示例代码:
@Entity public class MyEntity {
@Id private Long id;
@ElementCollection private Set<String> strings;
// more fields
// getters and setters
}
public interface MyEntityRepo extends CrudRepository<MyEntity, Long> {
MyEntityPartial getMyEntityPartialById(Long id);
}
public interface MyEntityPartial {
Set<String> getStrings();
}
@DataJpaTest public class MyTest {
@Autowired private MyEntityRepo repo;
@BeforeEach private void setup() {
MyEntity myEntity = new MyEntity();
myEntity.setId(1L);
Set<String> strings = new HashSet<>();
strings.add("A");
myEntity.setStrings(strings);
repo.save(myEntity);
}
@Test public void exampleTest() {
MyEntityPartial myEntityPartial = repo.getMyEntityPartialById(1L);
assertThat(myEntityPartial, is(notNullValue()));
assertThat(myEntityPartial.getStrings(), containsInAnyOrder("A"));
myEntityPartial.getStrings().add("B");
assertThat(myEntityPartial.getStrings(), containsInAnyOrder("A", "B"));
}
}
此处测试在最后一个断言处失败,因为 myEntityPartial.getStrings()
仍然仅包含“A”,但不包含“A”和“B”。我检查了投影实例的 Set
myEntityPartial
不是正常的 HashSet
而是 org.hibernate.collection.internal.PersistentSet
。想知道这是否是问题所在?以及如何告诉 Hibernate 或 Spring 在投影界面中使用 HashSet
?
注意:我之前没有在 Spring Data JPA 中使用过投影。所以谢谢你分享这个! :直到
我认为 myEntityPartial.getStrings().add("B");
有问题。
它不会更新 MyRepo
管理的实际 MyEntity
。每次执行 myEntityPartial.getStrings()
我猜 returns 数据库中实体的最新投影。
但如果我们将 myEntityPartial.getStrings()
存储在本地集合中,它就可以工作!
@Test public void exampleTest() {
MyEntityPartial myEntityPartial = repo.getMyEntityPartialById(1L);
Set<String> partialSet = myEntityPartial.getStrings();
assertNotNull(myEntityPartial);
assertTrue(partialSet.contains("A"));
partialSet.add("B");
assertTrue(partialSet.contains("A"));
assertTrue(partialSet.contains("B"));
}
我假设这不是测试的真正目的?
因此,如果由存储库管理的实体已更新,则它会起作用
@Test public void exampleTest2() {
MyEntityPartial myEntityPartial = repo.getMyEntityPartialById(1L);
assertNotNull(myEntityPartial);
assertTrue(myEntityPartial.getStrings().contains("A"));
//update the entity in db
updateEntity("B");
assertTrue(myEntityPartial.getStrings().contains("A"));
assertTrue(myEntityPartial.getStrings().contains("B"));
}
/*
* Updating actual entity, returns B with partial projection
*/
private void updateEntity(String newStrings){
MyEntity entity = repo.findById(1L).get();
Set<String> existing = entity.getStrings();
existing.add(newStrings);
entity.setStrings(existing);
repo.save(entity);
}
此外,myEntityPartial.getStrings()
显示了 LinkedHashSet 类型。
希望这有助于解决问题。
我正在使用投影接口 return 实体的局部视图,局部视图包含一组字符串。我希望 Set 正常工作,但它不是:当我向它添加一个新的字符串时,它会忽略该字符串,请参见下面的示例代码:
@Entity public class MyEntity {
@Id private Long id;
@ElementCollection private Set<String> strings;
// more fields
// getters and setters
}
public interface MyEntityRepo extends CrudRepository<MyEntity, Long> {
MyEntityPartial getMyEntityPartialById(Long id);
}
public interface MyEntityPartial {
Set<String> getStrings();
}
@DataJpaTest public class MyTest {
@Autowired private MyEntityRepo repo;
@BeforeEach private void setup() {
MyEntity myEntity = new MyEntity();
myEntity.setId(1L);
Set<String> strings = new HashSet<>();
strings.add("A");
myEntity.setStrings(strings);
repo.save(myEntity);
}
@Test public void exampleTest() {
MyEntityPartial myEntityPartial = repo.getMyEntityPartialById(1L);
assertThat(myEntityPartial, is(notNullValue()));
assertThat(myEntityPartial.getStrings(), containsInAnyOrder("A"));
myEntityPartial.getStrings().add("B");
assertThat(myEntityPartial.getStrings(), containsInAnyOrder("A", "B"));
}
}
此处测试在最后一个断言处失败,因为 myEntityPartial.getStrings()
仍然仅包含“A”,但不包含“A”和“B”。我检查了投影实例的 Set
myEntityPartial
不是正常的 HashSet
而是 org.hibernate.collection.internal.PersistentSet
。想知道这是否是问题所在?以及如何告诉 Hibernate 或 Spring 在投影界面中使用 HashSet
?
注意:我之前没有在 Spring Data JPA 中使用过投影。所以谢谢你分享这个! :直到
我认为 myEntityPartial.getStrings().add("B");
有问题。
它不会更新 MyRepo
管理的实际 MyEntity
。每次执行 myEntityPartial.getStrings()
我猜 returns 数据库中实体的最新投影。
但如果我们将 myEntityPartial.getStrings()
存储在本地集合中,它就可以工作!
@Test public void exampleTest() {
MyEntityPartial myEntityPartial = repo.getMyEntityPartialById(1L);
Set<String> partialSet = myEntityPartial.getStrings();
assertNotNull(myEntityPartial);
assertTrue(partialSet.contains("A"));
partialSet.add("B");
assertTrue(partialSet.contains("A"));
assertTrue(partialSet.contains("B"));
}
我假设这不是测试的真正目的?
因此,如果由存储库管理的实体已更新,则它会起作用
@Test public void exampleTest2() {
MyEntityPartial myEntityPartial = repo.getMyEntityPartialById(1L);
assertNotNull(myEntityPartial);
assertTrue(myEntityPartial.getStrings().contains("A"));
//update the entity in db
updateEntity("B");
assertTrue(myEntityPartial.getStrings().contains("A"));
assertTrue(myEntityPartial.getStrings().contains("B"));
}
/*
* Updating actual entity, returns B with partial projection
*/
private void updateEntity(String newStrings){
MyEntity entity = repo.findById(1L).get();
Set<String> existing = entity.getStrings();
existing.add(newStrings);
entity.setStrings(existing);
repo.save(entity);
}
此外,myEntityPartial.getStrings()
显示了 LinkedHashSet 类型。
希望这有助于解决问题。