java - 运行 Spring 集成测试时为 "org.springframework.dao.InvalidDataAccessApiUsageException: Multiple representations of the same"

标签 java spring jpa spring-data-jpa spring-junit

我遇到了一个奇怪的问题,我不确定解决该问题的最佳方法是什么。我编写了一些 JPA 实体类,这些实体类可以很好地保存到数据库中,但是当我在 Spring JUnit 环境中运行时,出现以下异常:

org.springframework.dao.InvalidDataAccessApiUsageException: Multiple representations of the same entity [com..x.y.z.Address#0] are being merged. Detached: [com..x.y.z.Address@48d9d51f]; Managed: [com..x.y.z.Address@4a5e389b]; nested exception is java.lang.IllegalStateException: Multiple representations of the same entity [com..x.y.z.Address#0] are being merged. Detached: [com..x.y.z.Address@48d9d51f]; Managed: [com..x.y.z.Address@4a5e389b]

我的实体类类似于以下内容:

class User {

   @Id   
   @SequenceGenerator(name = "USER_ID_GENERATOR", sequenceName = "USER_SEQ")
   @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "USER_ID_GENERATOR") 
   private String id;

   @OneToMany(mappedBy = "user", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
   private Set<Address> addresses = new HashSet<>();
}

class Address{
  @Id
  private long addressId;

  private String addressLine;

  @ManyToOne 
  @JoinColumn(name="user_id") 
  private User user;
}

我想补充的一条信息是我正在使用 Spring JPA 的 CrudRepository 进行保存。

我的测试的简单再现如下:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {MyApplication.class})
@WebIntegrationTest({ "server.port=12345", "server.url=http://127.0.0.1:12345" })
@DirtiesContext
public class MyIntegrationTest {

 private UserRepository userRepository

 @Test
 public void testSave(){
   User user = new User(1, "James");
   Address address1 = new Address("1234 xyz street");
   user.addAddress(address1);

   userRepository.save(user);

   User user = userRepository.findById(1);
   Address address2 = new Address("111 abc street");
   user.addAddress(address2);
   userRepository.save(user) // this is where the exception happens while running the test
 }
}

我应该怎样做才能使其在我的测试和实际运行环境中正常运行?谢谢

最佳答案

好吧,我是这样看的..

您的地址实体有一个@Id,没有任何生成策略,因此其中的任何内容都将被视为主键。

您将用户上的所有操作级联到地址:

@OneToMany(mappedBy = "user", fetch = FetchType.EAGER, cascade = CascadeType.ALL)

所以我猜你第二次保存用户时,它实际上会首先尝试合并..

现在,您创建了两个 Address 实例,但未指定 id.. 因此在这两种情况下它都为 0。您首先保存,这很好,您检索用户以及第一个地址(因为急切获取),然后您创建另一个地址,并且 id 将再次是相同的 0

现在您最终会在列表中得到两个具有相同 id 的地址。一个由持久上下文管理,另一个被分离。 在合并期间您会收到该错误。

我无法 100% 证明这一点,但我预感如果您将地址的 id 分别指定为 12(或任何两个不同的),您将不会再看到该错误。

关于java - 运行 Spring 集成测试时为 "org.springframework.dao.InvalidDataAccessApiUsageException: Multiple representations of the same",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41946588/

相关文章:

java - Hibernate:使用别名获取列

java - Spring MVC - 从我的 Controller 读取文件

java - 在 Tomcat 服务器上自动启动 Spring Boot 应用程序

java - 多对多 JPA Hibernate 通过连接表映射复合键错误

java - 如何为无状态 EJB 上的每次调用获取新的 Iterable

java - SNMP 响应为空 [SNMP4j]

java - 如何使用 oAuth2/spring security 限制一个连接/用户

java - CGLIB如何代理String或其他final类?

java - 使用 LocalDateTime 的 Spring 启动项目

java - 在 java 中配置 hibernate 和 mysql 时出错