"org.springframework.dao.InvalidDataAccessApiUsageException: Multiple representations of the same" 当 运行 Spring 集成测试
"org.springframework.dao.InvalidDataAccessApiUsageException: Multiple representations of the same" when running Spring Integration Test
我 运行遇到了一个奇怪的问题,对此我不确定解决问题的最佳方法是什么。我写了一些 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
}
}
我应该怎么做才能使这个 运行 在我的测试和实际 运行 环境中都正常?谢谢
好的,我是这样看的..
您的 Address 实体有一个没有任何生成策略的 @Id,因此无论其中包含什么,都将被视为主键。
您将对用户的所有操作级联到地址:
@OneToMany(mappedBy = "user", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
所以我猜你第二次保存用户时,它实际上首先尝试合并..
现在,您创建了两个 Address 实例而没有指定 id.. 所以在这两种情况下它都是 0
。你先保存,这很好,你检索用户和第一个地址(因为 EAGER 获取),然后你创建另一个地址,id 将再次相同 0
.
现在您在列表中得到两个具有相同 ID 的地址。一个由持久上下文管理,另一个被分离。
在合并期间,您会收到该错误。
我无法 100% 证明这一点,但我有预感,如果您将地址的 ID 分别指定为 1
和 2
(或任何两个不同的 ID),您将看不到又是那个错误。
我 运行遇到了一个奇怪的问题,对此我不确定解决问题的最佳方法是什么。我写了一些 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
}
}
我应该怎么做才能使这个 运行 在我的测试和实际 运行 环境中都正常?谢谢
好的,我是这样看的..
您的 Address 实体有一个没有任何生成策略的 @Id,因此无论其中包含什么,都将被视为主键。
您将对用户的所有操作级联到地址:
@OneToMany(mappedBy = "user", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
所以我猜你第二次保存用户时,它实际上首先尝试合并..
现在,您创建了两个 Address 实例而没有指定 id.. 所以在这两种情况下它都是 0
。你先保存,这很好,你检索用户和第一个地址(因为 EAGER 获取),然后你创建另一个地址,id 将再次相同 0
.
现在您在列表中得到两个具有相同 ID 的地址。一个由持久上下文管理,另一个被分离。 在合并期间,您会收到该错误。
我无法 100% 证明这一点,但我有预感,如果您将地址的 ID 分别指定为 1
和 2
(或任何两个不同的 ID),您将看不到又是那个错误。