我遇到了一个奇怪的问题,我不知道解决问题的最佳方法是什么。我编写了一些JPA
实体类,它们可以很好地保存到数据库中,但是当我在Spring JUnit
环境中运行时,我得到以下异常:
org.springframework.dao.InvalidDataAccessApiUsageException:Multiple 正在存在同一实体[com..x.y.z.Address#0]的表示 合并。分离:[com..x.y.z.Address @ 48d9d51f];管理: [com..x.y.z.Address @ 4a5e389b];嵌套异常是 java.lang.IllegalStateException:相同的多个表示 实体[com..x.y.z.Address#0]正在合并。独立: [com..x.y.z.Address @ 48d9d51f];管理:[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&#39; 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
}
}
我应该怎么做才能在我的测试和实际运行环境中都运行良好?感谢
答案 0 :(得分:2)
好的,我看到它的方式..
你的地址实体有一个没有任何生成策略的@Id,所以无论在那里,它都会被视为主键。
您级联用户到地址的所有操作:
@OneToMany(mappedBy = "user", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
所以我猜你第二次保存用户,它实际上是先尝试合并..
现在,您创建两个Address实例而不指定id ..因此在两种情况下它都是0
。你首先保存,没关系,你检索用户和第一个地址(因为EAGER提取),你创建另一个地址,id将再次相同0
。
现在你最终在列表中有两个具有相同id的地址。一个由持久化上下文管理,另一个是分离的。 在合并期间,您会收到该错误。
我无法100%证明这一点,但我预感到,如果您分别将地址的ID指定为1
和2
(或任何两个不同的地址),您将看不到该错误试。