它是有效申报@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 Layer上有所不同。 如果尝试这样的操作: 一切都会好起来的。但是,保存后,如果您尝试获取订单: 当然,在两种情况下,您的Address类应该看起来有所不同。
问题内容: 我有2个类:User和UserPicture具有1:1的关系。 UserPicture中的“ user”将被加载,而UserPicture中的“ userPicture”则不会加载-我错了吗? 编辑 必须添加,我只是创建一个UserPicture并插入它们(使用现有的userId)-也许我需要在UserPicture中级联“ user”? 问题答案: 您必须映射您的课程。
使用QueryDSLHibernate的功能: 问题: 是否可以为QueryDSL查询设置全局FetchMode。在Hibernate中,您可以用@fetch(FetchMode.join)指定这一点,但不幸的是,QueryDSL忽略了这一点。 因此,我的目标是用QueryDSL加载1000个客户,并且只运行2个查询(count+select)。
我的数据库技能有点生疏,所以对我来说学习Hibernate有点难。 我一直在阅读一对一、一对多和多对多,简而言之,这是我年轻时的理解: 一对一:-表A链接到表B中的另一行,表A中的行数必须等于表B中的行数。 一对多:-每家公司可以有很多员工。 多对多:-许多医生可以拥有/分享不同的病人。(无意双关语)。 假设我有以下表格,对于殡仪员客户模型 [id[pk]、全名(char)、年龄(int)、地址(
在对一个与另一个有一对一关系的实体执行jpql查询时,我遇到了一个意外的行为。关键的一点是,关系是从根实体的主键到目标实体的一个字段,而目标实体不是ID。
在学习JPA/Hibernate时,我偶然发现了一些意想不到的事情。我得到了一个不必要的对db的双击查询(参见buttom)。我有一个简单的OneToOne设置。 这是我的联系人: 我的地址实体: 这就是我运行代码的方式: 这可能是愚蠢的事情,但是什么导致了双重选择? 注意:My EntityManagerFactoryCreator是调用