Hibernate @OneToOne @NotNull [英] Hibernate @OneToOne @NotNull

查看:105
本文介绍了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 writing changeEntry 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆