JPA交叉单向OneToOne

时间:2015-02-16 16:13:47

标签: java jpa openjpa

我有两个实体类A和B.对于A只有一个B类实例。通过应用程序的生命周期我需要为A创建B的新实例。但是对于历史日志我需要存储以前的实例B的链接到这个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实体的名称,但是获取nullpointer,因为b为null;

2 个答案:

答案 0 :(得分:0)

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

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

而不是:

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

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

答案 1 :(得分:-1)

你需要mappedBy注释:http://en.wikibooks.org/wiki/Java_Persistence/OneToOne 告知负责这种关系的java以及何时“外援”。您还需要只有一个实体中的外键而不是两个实体!