ClassA和ClassB之间存在ManyToMany关系。 ClassA拥有ClassB对象的集合,而ClassB对ClassA一无所知。 A类的相关部分看起来像这样:
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name="ClassA_ClassB_JoinTable",
joinColumns=@JoinColumn(name="classAId"),
inverseJoinColumns=@JoinColumn(name="classBId"))
private ArrayList<ClassB> classBReferences = new ArrayList<ClassB>();
我有一个简单的CrudDao,其相关代码是:
@Singleton
public class CrudDao {
@PersistenceContext(unitName = "myDatabaseName")
private EntityManager em;
public <E> E create(E e) {
em.persist(e);
return e;
}
}
我创造了一个人为的/简化的例子来说明我遇到的问题。我写了一个简化的REST端点,如下所示:
@Path("/simplified")
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public class SimplifiedService {
@Inject
private CrudDao crudDao;
@GET
@Path("")
public Response watchItCrash() {
ClassB classB = new ClassB();
classB.setAttribute("Blah!");
crudDao.create(classB);
ClassA classA = new ClassA();
classA.getClassBReferences().add(classB);
crudDao.create(classA);
return Response.ok().build();
}
}
当我站起来使用我的REST服务(使用TomEE)时,我可以进行GET调用,一切都运行良好。但是,我也尝试使用Arquillian和JUnit来测试我的REST端点,这是我遇到麻烦的地方。
我的Arquillian / JUnit测试如下所示:
@RunWith(Arquillian.class)
public class SimplifiedServiceIT {
@ArquillianResource
private URL webappUrl;
@Deployment()
public static WebArchive createDeployment() {
return ShrinkWrap.create(WebArchive.class)
.addClasses(SimplifiedService.class, CrudDao.class)
.addAsWebInfResource("META-INF/persistence.xml")
.addAsWebInfResource("test-resources.xml", "resources.xml")
.addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
}
@Test
public void testGetRoles() throws URISyntaxException {
URI uri = webappUrl.toURI().resolve("simplified");
Client client = ClientBuilder.newClient();
WebTarget target = client.target(uri);
Invocation.Builder builder = target.request();
Response response = builder.get();
}
}
现在显然我实际上并没有在这里测试任何东西,但是我可以看到GET调用成功完成,ClassB成功保持,但它无法持久化ClassA。这是我尝试持久化ClassA时出现的错误:
WARNING: Unexpected exception from beforeCompletion; transaction will roll back
<openjpa-2.4.0-r422266:1674604 nonfatal user error> org.apache.openjpa.persistence.InvalidStateException: Encountered unmanaged object "ClassB@56c6d515" in life cycle state unmanaged while cascading persistence via field "ClassA.classBReferences<element:class ClassB>" during flush. However, this field does not allow cascade persist. You cannot flush unmanaged objects or graphs that have persistent associations to unmanaged objects. Suggested actions:
a) Set the cascade attribute for this field to CascadeType.PERSIST or CascadeType.ALL (JPA annotations) or "persist" or "all" (JPA orm.xml),
b) enable cascade-persist globally,
c) manually persist the related field value prior to flushing.
d) if the reference belongs to another context, allow reference to it by setting StoreContext.setAllowReferenceToSiblingContext().
FailedObject: ClassB@56c6d515
知道为什么它在'生产'中起作用但在Arquillian / UnitTest环境中失败了吗?