Hibernate @OneToOne @NotNull [英] 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);
$ b $ class ChangeEntryDetails
{
@OneToOne(cascase = CascadeType.ALL)
@NotNull
ChangeEntry changeEntry ;
public void setChangeEntry(ChangeEntry changeEntry)
{
this.changeEntry = changeEntry;
}
}
我找不到任何说这是无效的但是,在持续存在期间,至少有一方的关系必须受到侵犯。 (例如,如果首先写入changeEntry,则changeEntryDetails将暂时为null)。
尝试此操作时,我看到一个抛出的异常 not-null property引用空值或瞬态值
。
如果可能,我想避免放宽约束,因为双方必须
是否可以声明
@OneToOne
和@NotNull
在关系两边(...)我找不到任何说这是无效的东西,但似乎在坚持期间,至少有一方的关系必须受到侵犯。 (例如,如果首先写入changeEntry
,changeEntryDetails
将暂时为空)。
< blockquote>
这是有效的,一切工作正常与正确映射的实体。您需要将双向关联的一侧声明为拥有方(此控制插入顺序)。一个可能的工作解决方案:
@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
私人长ID;
@OneToOne(可选= 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);
}
//构造函数,获取器和设置器
}
对于其他实体(请注意
mappedBy
在关联非拥有方设置的属性):
<$
@GeneratedValue
私有长ID; pre $@Entity
公共类ChangeEntryDetails实现可序列化{
@Id
@GeneratedValue
私有长ID;
@OneToOne(可选= false,mappedBy =changeEntryDetails)
@NotNull
Private ChangeEntry changeEntry;
//构造函数,getters和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();
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。);
} catch(ConstraintViolationException e){
assertEquals(1,e.getConstraintViolations()。size());
ConstraintViolation<?>违例= 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。);
} catch(ConstraintViolationException e){
assertEquals(1,e.getConstraintViolations()。size());
ConstraintViolation<?>违例= e.getConstraintViolations()
.iterator()。next();
assertEquals(changeEntry,violation.getPropertyPath()
.toString());
assertEquals(NotNull.class,violation.getConstraintDescriptor()
.getAnnotation()。annotationType());
$ b $ @Test
public void validEntryWithDetails(){
ChangeEntry entry = new ChangeEntry();
ChangeEntryDetails details = new ChangeEntryDetails();
entry.addDetails(details);
em.persist(entry);
查询查询= em.createNamedQuery(ChangeEntry.FIND_ALL_CHANGEENTRIES);
assertEquals(1,query.getResultList()。size());
}
}
Is it valid to declare
@OneToOne
and@NotNull
on both sides of a relationship, such as: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; } }
I can't find anything that says this is invalid, but it seems that during persistence at least one side of the relationship must be violated. (Eg., if writing changeEntry first, changeEntryDetails will be null temporarily).
When trying this, I see an exception thrown
not-null property references a null or transient value
.I'd like to avoid relaxing the constraint if possible, because both sides must be present.
解决方案Is it valid to declare
@OneToOne
and@NotNull
on both sides of a relationship (...) I can't find anything that says this is invalid, but it seems that during persistence at least one side of the relationship must be violated. (e.g. if writingchangeEntry
first,changeEntryDetails
will be null temporarily).It is valid and everything works fine with properly mapped entities. You need to declare one side of your bi-directional association as the "owning" side (this "control" the order of inserts). One possible working solution:
@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 }
And for the other entity (note the
mappedBy
attribute set on the non-owning side of the association):@Entity public class ChangeEntryDetails implements Serializable { @Id @GeneratedValue private Long id; @OneToOne(optional = false, mappedBy = "changeEntryDetails") @NotNull private ChangeEntry changeEntry; // constructor, getters and setters }
With these entities, the following test (for demonstration purposes) passes:
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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!