具有主键的Hibernate类也是外键

时间:2017-03-07 18:28:28

标签: java hibernate

@Entity
@Table(name = "USER_DATA")
public class UserData {
    Entity entity;

    @OneToOne(fetch = FetchType.EAGER)
    @PrimaryKeyJoinColumn(name="PK_FK_ENTITY")
    @Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE})
    public Entity getEntity() {
        return entity;
    }

    public void setEntity(Entity entity) {
        this.entity = entity;
    }
}

给出的错误是“没有为实体指定标识符”。如何指定实体字段既是主键又是外键?请注意,此处没有“UserData”的类层次结构;它只是一个单一的课程。事实恰恰相反,对于每个'UserData',只有一个'Entity',因此我们希望它既可以是主键也可以是外键。

2 个答案:

答案 0 :(得分:0)

我们在我们的应用程序中有相同的情况,它适用于此(我们注释属性而不是getter,不知道是否有任何区别):

public class UserData {
    @Id
    @Column(name="PK_FK_ENTITY")
    private int id;

    @OneToOne
    @JoinColumn(name="PK_FK_ENTITY")
    private Entity entity;
    ...

    public UserData (Entity entity, ...) {

        this.id = entity.getId();
        ...
    }
    ...
} 

请注意,在构造函数中,您应该设置ididentity都不应该有一个setter,因为它无法改变。

另请注意,在这种情况下我们不使用级联。我们首先保存具有生成ID的Entity,然后保存UserData

答案 1 :(得分:0)

对于一对一的双向映射,只需在子实体上定义@MapsId注释。

@Entity
@Table(name = "USER_DATA")
public class UserData {

    @OneToOne(cascade = CascadeType.ALL, mappedBy = "userData", orphanRemoval = true)
    private Entity entity;

    public void setEntity(Entity entity) {
        this.entity = entity;
        if (null != entity && entity.getUserData() != this) {
            entity.setUserData(this);
        }
    }
}

@Entity
@Table(name = "ENTITY")
public class Entity {

    @Id
    private Long id;

    @MapsId
    @OneToOne
    @JoinColumn(name = "user_data_id")
    private UserData userData;

    public void setUserData(UserData userData) {
        this.userData = userData;
        if (null != userData && userData.getEntity() != this) {
            userData.setEntity(this);
        }
    }

}

对于一对多单向映射,您必须使用@ElementalCollection和@CollectionTable并使用@Embeddable注释注释Entity.class

        @Entity
        @Table(name = "USER_DATA")
        public class UserData {

             @ElementCollection
             @CollectionTable(name = "entity", 
                              joinColumns = @JoinColumn(name = "user_data_id"), 
                              uniqueConstraints = { @UniqueConstraint(columnNames     
= { "user_data_id", "name" }) })
             private final Set<Entity> entities = new LinkedHashSet<>();

             public void setEntities(Set<Entity> entities) {
                 this.entities.clear();
                 if (null != entities) {
                     this.entities.addAll(entities);
                 }
             }
        }

        @Embeddable
        public class Entity {

            @Column
            @Access(AccessType.FIELD)
            private String name;

        }

请参阅以下文章以便更好地理解:
1. @OneToOne使用@PrimaryKeyJoinColumn http://vard-lokkur.blogspot.my/2011/05/onetoone-with-shared-primary-key.html共享主键。

  1. 使用@MapsId http://vard-lokkur.blogspot.my/2014/05/onetoone-with-shared-primary-key.html
  2. 的@OneToOne共享主键