Hibernate@OneToOne @NotNull

它是有效申报@OneToOne,并@NotNull在关系的双方,如:

class ChangeEntry

{

@OneToOne(cascade=CascadeType.ALL)

@NotNull

ChangeEntryDetails changeEntryDetails;

public void addDetails(ChangeEntryDetails details) {

this.changeEntryDetails = details;

details.setChangeEntry(this);

}

}

class ChangeEntryDetails

{

@OneToOne(cascase=CascadeType.ALL)

@NotNull

ChangeEntry changeEntry;

public void setChangeEntry(ChangeEntry changeEntry)

{

this.changeEntry = changeEntry;

}

}

我找不到任何表明这是无效的信息,但似乎在持久性过程中,至少必须违反关系的一侧。(例如,如果首先写入changeEntry,则changeEntryDetails临时为null)。

尝试此操作时,我看到抛出了异常not-null property references a null or transient value

我想避免在可能的情况下放宽约束,因为双方都 存在。

回答:

声明@OneToOne@NotNull在关系的两边是否合法(…)我找不到任何表明无效的内容,但是在持久性过程中,似乎至少必须违反关系的一侧。(例如,如果changeEntry先写,changeEntryDetails则暂时为null)。

这是有效的,并且在正确映射的实体上一切正常。您需要将双向关联的一侧声明为“拥有”侧(此“控制”插入顺序)。一种可行的解决方案:

@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

}

对于其他实体(请注意mappedBy在关联的非所有权方设置的属性):

@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());

}

}

以上是 Hibernate@OneToOne @NotNull 的全部内容, 来源链接: utcz.com/qa/398996.html

回到顶部