首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Hibernate @OneToOne @NotNull

Hibernate @OneToOne @NotNull
EN

Stack Overflow用户
提问于 2010-04-27 21:01:02
回答 3查看 17.2K关注 0票数 15

在关系的两边声明@OneToOne@NotNull是否有效,例如:

代码语言:javascript
复制
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暂时为空)。

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

如果可能的话,我想避免放松约束,因为双方都必须在场。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-04-28 01:11:06

在关系的两边声明@OneToOne@NotNull是否有效(.)我找不到任何东西说这是无效的,但似乎在坚持期间,至少有一方的关系必须被违反。(例如,如果首先写入changeEntry,则changeEntryDetails暂时为空)。

它是有效的,每件事都能很好地处理映射好的实体。您需要将双向关联的一方声明为“拥有”方(此“控件”为插入顺序)。一个可能的工作解决办法是:

代码语言:javascript
复制
@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属性):

代码语言:javascript
复制
@Entity
public class ChangeEntryDetails implements Serializable {
    @Id
    @GeneratedValue
    private Long id;

    @OneToOne(optional = false, mappedBy = "changeEntryDetails")
    @NotNull
    private ChangeEntry changeEntry;

    // constructor, getters and setters
}

对于这些实体,下列测试(为演示目的)通过:

代码语言:javascript
复制
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());
    }
}
票数 19
EN

Stack Overflow用户

发布于 2010-04-27 21:05:55

因为您的级联类型,所以它应该持久化瞬态值。

如果在设置另一个瞬态元素之前,您实际上正在尝试持久化第一个元素,那么您将预期会出现此错误。

您指定的约束仅指定数据库中的值不能为空,而不是在数据模型中,显然,当您构造对象的新实例时,引用将为空。当引用为null时,不能持久化该实体。

票数 0
EN

Stack Overflow用户

发布于 2011-06-15 12:38:57

如果您在这里遇到了与 openJPA 和Pascals解决方案相同的问题,那么您可能需要在persistence.xml中将openJPA属性openjpa.InverseManager设置为true

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2725111

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档