基本类型的一对一映射,在Hibernate中成为单个类

时间:2011-10-05 18:22:13

标签: java hibernate jpa annotations

所以情况如下:有一个实体需要与字典连接。想象一下以下结构

create table Address (
    addressId bigint not null,
    addressLine1 varchar(255),
    city varchar(255),
    country varchar(255),
    state varchar(255),
    zipCode varchar(255),
    primary key (addressId)
)

create table STATES_DICT (
    state_code varchar(255),
    state_fullname varchar(255), 
    primary key (state_code)
)

我想将ADDRESS和STATE_DICTIONARY映射到单个实体。

@Entity
@Table(name = "ADDRESS")
public class Address implements Serializable {

    @Id
    @Column(name = "ADDRESSID")
    private int addressId;

    @Column(name = "ADDRESSLINE1")
    private String addressLine1;

    @Column(name = "STATE")
    private String state;

    //??? annotations
    private String fullStateName;

    @Column(name = "ZIPCODE")
    private String zipCode;

    @Column(name = "CITY")
    private String city;

    @Column(name = "COUNTRY")
    private String country;
    //... getters and setters
}

对于纯SQL,我将运行

select a.ADDRESSID, a.ADDRESSLINE1, a.CITY, a.ZIPCODE, a.STATE, 
    d.STATE_FULLNAME, a.COUNTRY 
from ADDRESS a, STATES_DICT d where a.STATE = d.STATE_CODE

但我在使用JPA映射时遇到了严重问题。

  1. 我不能使用@SecondaryTable,因为表没有按主键映射
  2. 我能得到的最好的是:
  3.     @ElementCollection
        @JoinTable(name="STATES_DICT", 
                joinColumns=@JoinColumn(name="STATE_CODE", referencedColumnName="STATE"))
        @Column(name = "STATE_FULLNAME")
        private Collection<String> fullStateName;
    

    下行是 - 映射始终是一对一的,并且收集带来混乱,并且关系更多地是一对一(多对一)而不是一对多。

    有什么想法吗?对于一对一映射,是否存在等效的@ElementCollection? 删除@ElementCollection没有帮助。 fullStateName字段应该在ADDRESS列中 - 事实并非如此。

    一些说明: *我需要将这两者整合在一个实体中。 *我正在扩展现有的解决方案,需要添加这个字典列 *稍后由一些仅通过基本类型运行的其他服务处理该实体。我宁愿不改变服务,这就是为什么添加@OneToOne关系不是更好的原因

    非常感谢


    我正在用@SecondaryTable示例扩展这个问题 - 这对我不起作用。

    @Entity
    @Table(name = "ADDRESS")
    @SecondaryTable(name="STATES_DICT", 
            pkJoinColumns=@PrimaryKeyJoinColumn(columnDefinition="STATE_CODE", referencedColumnName="STATE"))
    public class Address implements Serializable {
    
        @Id
        @Column(name = "ADDRESSID")
        private int addressId;
    
        @Column(name = "ADDRESSLINE1")
        private String addressLine1;
    
        @Column(name = "STATE")
        private String state;
    
        @Column(table="STATES_DICT", name = "STATE_FULLNAME")
        private String fullStateName;
    
        @Column(name = "ZIPCODE")
        private String zipCode;
    
        @Column(name = "CITY")
        private String city;
    
        @Column(name = "COUNTRY")
        private String country;
    
        //... getters and setters
    }
    

    这引起了一个令人讨厌的例外: 引起:org.hibernate.AnnotationException:SecondaryTable JoinColumn无法引用非主键


    为了记录 - 我找不到办法做到这一点(并假设它根本不是应该这样做的方式)。我已经使用关系注释(@ManyToOne,@ OneToOne)和@JoinColumn - 所以正确的方法。我已经调整了进一步的处理逻辑来处理@JoinColumn注释,就像它使用@Column一样。它奏效了。

    进一步处理是一种安全功能,它根据用户角色和原始数据库列名来抑制值。这就是为什么我坚持使用@Column注释

    非常重要

3 个答案:

答案 0 :(得分:1)

使用

来自user2601805的回答是正确的
@PrimaryKeyJoinColumn(name="STATE_CODE", referencedColumnName="STATE")

在你的情况下,这应该足够了,因为你想要的只是STATES_DICT的属性。

我还询问了一个与JPA有关的问题,该问题显示了使用@SecondaryTable和@Embeddable来实现与@ElementCollection相似但是对于@OneToOne的一个例子

另请参阅此博客,例如http://www.bagdemir.com/2013/03/03/mapping-embeddable-objects-whichve-no-identities-using-multiple-tables-with-jpahibernate/

答案 1 :(得分:0)

您应该能够创建映射关系的@Embeddable State类,但提供委托方法以将状态名称公开为属性。这会完成你想要做的事吗?

答案 2 :(得分:0)

@pkJoinColumns中你应该使用:

@PrimaryKeyJoinColumn(name="STATE_CODE", referencedColumnName="STATE")

我有同样的问题,你使用@SecondaryTable的提示解决了我的问题。有关详细信息,请参阅Mapping one entity to several tables