【问题标题】:JPA cross unidirectional OneToOneJPA 跨单向 OneToOne
【发布时间】:2015-04-17 05:12:09
【问题描述】:

我有两个实体类 A 和 B。对于 A,只有一个类 B 的实例。通过应用程序的生命周期,我需要为 A 创建新的 B 实例。但是对于历史日志,我需要存储以前的实例B 的链接到 this A 实例。所以我创建了下一个映射:

@Entity
class A {
    @OneToOne
    @JoinColumn(name="B_ID")
    B b;
}

@Entity
class B {
    @OneToOne
    @JoinColumn(name="A_ID")
    A a;
}
///////
CREATE TABLE A_TABLE (ID uuid, B_ID uuid, FOREIGN KEY (B_ID) REFERENCES B_TABLE(ID));
CREATE TABLE B_TABLE (ID uuid, A_ID uuid, FOREIGN KEY (A_ID) REFERENCES A_TABLE(ID));

我的表中已经有一些正确的数据,但是每次当我尝试获取 A 类的任何实例时,b 字段都是空的。那么,我做错了什么?

UPD_0 好的,这就是我真正要处理的:

@MappedSuperclass
public abstract class BaseUuidEntity {
     @Id
     @Column(name = "ID")
     @Persistent
     protected UUID id;
}

@MappedSuperclass
public class StandartEntity extends BaseUuidEntity { ... }
@MappedSuperclass
public abstract class AbstractEntity extends BaseUuidEntity { ... }
@Entity(name = "CardEntity")
@Table(name = "TBL_CARD")
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "CARD_TYPE", discriminatorType = DiscriminatorType.INTEGER)
@DiscriminatorValue("0")
public class CardEntity extends AbstractEntity { ... }

@Entity("aEntity")
@DiscriminatorValue("1")
@Table(name = "A_TABLE")
class A extends CardEntity { 
    @OneToOne
    @JoinColumn(name="B_ID")
    B b;
    public String getBName() {
        return b.getName(); // NullPointerException
    }
}
@Entity("bEntity")
@Table(name = "B_TABLE")
class B extends StandartEntity {
    @Column(name="name")
    String name;
    public String getName() {
        return this.name;
    }
}

-- A_TABLE (ID, B_ID)
'41a2647d-2ef6-f507-92ee-bff0f784b6f3', '5d3c66da-b377-11e4-bc9c-1008b124eacf'
-- B_TABLE (ID, A_TABLE, NAME)
'5d3c66da-b377-11e4-bc9c-1008b124eacf', '41a2647d-2ef6-f507-92ee-bff0f784b6f3', 'Some text'

我得到所有 A 实体(在我的情况下 - 它是一个)

select e from aEntity e

并试图在每个实体中获取 b 实体的名称,但获取空指针,导致 b 为空;

【问题讨论】:

  • 如何获取A类的实例?你能展示你的代码吗?
  • 只是简单的Id查询:Query q = em.createQuery("select e from my.package.A e where e.id=:id"); q.setParameter("id", required_uuid); q.getSingleResult();
  • 该代码看起来不错,因此问题一定出在您未显示的内容上。您的实体中是否有任何 @Id 注释?你可以给他们看吗?

标签: java jpa openjpa


【解决方案1】:

我不确定这是否会有所不同,但请尝试更改getBName() 中的代码以使用getter,而不是直接引用实例变量b

public String getBName() {
    return getB().getName();
}

代替:

public String getBName() {
    return b.getName(); // NullPointerException
}

我怀疑这可能是问题所在,因为 JPA 实现会为实体创建代理,这些实体通常是实体的子类,并且这些代理会覆盖您的 getter 和 setter。因此,如果您不使用 getter,则可能是实例变量未正确初始化。

【讨论】:

  • 不,抱歉,仍然是空值。但是,实际上,您给了我一个想法,所以我尝试为 Ab 字段设置 @Access(AccessType.FIELD) 并在构建时遇到此异常: Field "my.package.Ab" with "explicit field access" is not compatible其声明类使用“隐式字段访问”。我不知道,也许它会给你一些其他的想法。
  • 我解决了!实际上,是的,您对实施的事情是非常正确的。在我的情况下,它是框架“功能” - 我需要在视图中添加这个字段,在我的屏幕中使用。谢谢你,伙计!
【解决方案2】:

你需要 mappedBy 注释:http://en.wikibooks.org/wiki/Java_Persistence/OneToOne 通知 java 谁负责此关系以及何时存储“外国”ID。您还需要仅在其中一个实体中的外键,而不是两者!

【讨论】:

  • 但我两者都需要!我需要为 A 类的某个实例存储 B 的先前实例。我需要为 A 实例确定 B 的工作实例。并且 mappedBy 设置双向关系,但正如我所写,我需要两个单向关系。
  • @Zielu 他不想做双向关系,他想要两个独立的单向关系。
猜你喜欢
  • 2014-05-17
  • 1970-01-01
  • 2014-11-09
  • 2012-01-11
  • 1970-01-01
  • 2021-07-14
  • 1970-01-01
  • 1970-01-01
  • 2012-09-28
相关资源
最近更新 更多