否 双方的关系(......) 我看不到什么话说这是无效的,但似乎在持续期间,至少一方的关系必须受到侵犯。 (例如,如果写作changeEntry
first,changeEntryDetails
将暂时取消。)
这种做法是有效的,所有东西都与经过适当规划的实体合作。 你们需要宣布你双向协会的一方为“拥有”一方(这种“控制”插入顺序)。 一种可行的解决办法:
@Entity
@NamedQueries( { @NamedQuery(name = ChangeEntry.FIND_ALL_CHANGEENTRIES, query = "SELECT c FROM ChangeEntry c") })
public class ChangeEntry implements Serializable {
public final static String FIND_ALL_CHANGEENTRIES = "findAllChangeEntries";
@Id
@GeneratedValue
private Long id;
@OneToOne(optional = false, cascade = CascadeType.ALL)
@JoinColumn(name = "DETAILS_ID", unique = true, nullable = false)
@NotNull
private ChangeEntryDetails changeEntryDetails;
public void addDetails(ChangeEntryDetails details) {
this.changeEntryDetails = details;
details.setChangeEntry(this);
}
// constructor, getters and setters
}
http://java.sun.com/javaee/6/docs/api/javax/persistence/One ToOne.html#mappedBy%2829”rel=“noreferer”>。 属于非社团的归属:
@Entity
public class ChangeEntryDetails implements Serializable {
@Id
@GeneratedValue
private Long id;
@OneToOne(optional = false, mappedBy = "changeEntryDetails")
@NotNull
private ChangeEntry changeEntry;
// constructor, getters and setters
}
与这些实体一起进行下列测试(为示范目的):
public class ChangeEntryTest {
private static EntityManagerFactory emf;
private EntityManager em;
@BeforeClass
public static void createEntityManagerFactory() {
emf = Persistence.createEntityManagerFactory("TestPu");
}
@AfterClass
public static void closeEntityManagerFactory() {
emf.close();
}
@Before
public void beginTransaction() {
em = emf.createEntityManager();
em.getTransaction().begin();
}
@After
public void rollbackTransaction() {
if (em.getTransaction().isActive()) {
em.getTransaction().rollback();
}
if (em.isOpen()) {
em.close();
}
}
@Test
public void testCreateEntryWithoutDetails() {
try {
ChangeEntry entry = new ChangeEntry();
em.persist(entry);
fail("Expected ConstraintViolationException wasn t thrown.");
} catch (ConstraintViolationException e) {
assertEquals(1, e.getConstraintViolations().size());
ConstraintViolation<?> violation = e.getConstraintViolations()
.iterator().next();
assertEquals("changeEntryDetails", violation.getPropertyPath()
.toString());
assertEquals(NotNull.class, violation.getConstraintDescriptor()
.getAnnotation().annotationType());
}
}
@Test
public void testCreateDetailsWithoutEntry() {
try {
ChangeEntryDetails details = new ChangeEntryDetails();
em.persist(details);
fail("Expected ConstraintViolationException wasn t thrown.");
} catch (ConstraintViolationException e) {
assertEquals(1, e.getConstraintViolations().size());
ConstraintViolation<?> violation = e.getConstraintViolations()
.iterator().next();
assertEquals("changeEntry", violation.getPropertyPath()
.toString());
assertEquals(NotNull.class, violation.getConstraintDescriptor()
.getAnnotation().annotationType());
}
}
@Test
public void validEntryWithDetails() {
ChangeEntry entry = new ChangeEntry();
ChangeEntryDetails details = new ChangeEntryDetails();
entry.addDetails(details);
em.persist(entry);
Query query = em.createNamedQuery(ChangeEntry.FIND_ALL_CHANGEENTRIES);
assertEquals(1, query.getResultList().size());
}
}