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)。
尝试这个时,我看到抛出的exceptionnot-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()); } }
由于您的级联类型,它应该保持瞬态值。
如果您实际上在设置其他瞬态元素之前尝试保留第一个元素,那么您会期望出现此错误。
您指定的约束仅指定数据库中的值不能为null,而不是在数据模型中,当您构造对象的新实例时,该引用将为null。 虽然引用为null,但您无法持久保存实体。
如果你在这里遇到与openJPA相同的问题并且Pascals解决方案仍然不适合你,你可能想在persistence.xml中将openJPA属性openjpa.InverseManager
设置为true
- Hibernate Validator方法或构造函数validation
- Java Beanvalidation:具有类级别约束的GroupSequence
- java / beans validation – collection / map不包含空值
- 如何在Spring Boot项目中禁用Hibernatevalidation
- ValidationMessages.properties文件之间的冲突
- 你能在运行时更改注释消息吗?
- javax.validation.ValidationException:无法找到默认提供程序
- Spring MVC – REST服务中bean列表上的@Valid
- 如何在类级别约束之前validation字段级别约束?