有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何连接非主键列上的表?

我对ORM类层次结构中的对象上的联接表有一个问题,因为LAGANCY数据库结构,联接列不是基类的主键。 以下是表格设计的一个示例:

CREATE TABLE "SCH"."FOO"
(
        "OWNERID"       NUMBER(10,0) NOT NULL ENABLE,
        "FOOID"         NUMBER(10,0) NOT NULL ENABLE,
        CONSTRAINT "FOO_PK" PRIMARY KEY ("OWNERID", "FOOID")
        CONSTRAINT "FOO_FK1" FOREIGN KEY ("OWNERID") REFERENCES "SCH"."OWNERS" ("OWNERID") ENABLE
)

CREATE TABLE "SCH"."BAR"
(
        "BARID"             NUMBER(10,0) NOT NULL ENABLE,
        "FOOID"             NUMBER(10,0)
        CONSTRAINT "BAR_PK" PRIMARY KEY ("BARID")
)

下面是映射(未删除的信息)

@Entity
@IdClass(FooId.class)
@Table(name = "FOO")
public class Foo implements java.io.Serializable
{
    @Id
    @Column(name = "OWNERID")
    private BigInteger ownerId;

    @Id
    @SequenceGenerator(name = "FOO_GENERATOR", sequenceName = "SEQ_FOO")
    @GeneratedValue(generator = "FOO_GENERATOR")
    @Column(name = "FOOID")
    private BigInteger id;

    @OneToMany(fetch = FetchType.LAZY)
    @JoinColumn(name = "FOOID", referencedColumnName = "FOOID")
    @Fetch(value = FetchMode.SUBSELECT)
    @Cascade(value = {CascadeType.ALL})
    private Set<Bar> bar = new LinkedHashSet<Bar>(0);
}


@Entity
@Table(name = "BAR")
public class Bar implements java.io.Serializable
{
    @Id
    @Column(name = "BARID")
    private BigInteger id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "FOOID", referencedColumnName = "FOOID")
    private Foo foo;
}

此操作失败,但有一个例外:

Caused by: org.hibernate.AnnotationException: referencedColumnNames(FOOID) of com.package.Bar.foo referencing com.package.Foo not mapped to a single property
    at org.hibernate.cfg.BinderHelper.createSyntheticPropertyReference(BinderHelper.java:204)
    at org.hibernate.cfg.ToOneFkSecondPass.doSecondPass(ToOneFkSecondPass.java:114)
    at org.hibernate.cfg.Configuration.processEndOfQueue(Configuration.java:1580)
    at org.hibernate.cfg.Configuration.processFkSecondPassInOrder(Configuration.java:1503)
    at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1419)
    at org.hibernate.cfg.Configuration.buildMappings(Configuration.java:1375)

你能帮我找个解决办法吗


共 (3) 个答案

  1. # 1 楼答案

    您在FOO表中使用了复合主键。所以你应该试试@EmbeddedId属性,你应该需要两列“OWNER_ID”和“FOO_ID”在BAR entity中与FOO entity连接

  2. # 2 楼答案

    不能两次映射双向关联。必须使用mappedBy属性将单面标记为多面的倒数:

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "foo")
    @Fetch(value = FetchMode.SUBSELECT)
    @Cascade(value = {CascadeType.ALL})
    private Set<Bar> bar = new LinkedHashSet<Bar>(0);
    
    ...
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "FOOID", referencedColumnName = "FOOID")
    private Foo foo;
    

    没有理由告诉Hibernate两次关联是由联接列FOOID映射的。这样做实际上是一个错误,因为它定义了两个不同的单向关联,而不是一个双向关联

    编辑

    上述方法应该可以工作,但由于以下Hibernate错误而无法工作:这是一个Hibernate错误。见HHH-4284

    为了避免这个问题,由于FOOID足以确保唯一性,解决方案是从所有者ID和@IdClass注释中删除@Id注释

  3. # 3 楼答案

    你可以做如下。。。。它应该有用-

    @Entity
    @IdClass(FooId.class)
    @Table(name = "FOO")
    public class Foo implements java.io.Serializable
    {
        @Id
        @Column(name = "OWNERID")
        private BigInteger ownerId;
    
        @Id
        @SequenceGenerator(name = "FOO_GENERATOR", sequenceName = "SEQ_FOO")
        @GeneratedValue(generator = "FOO_GENERATOR")
        @Column(name = "FOOID")
        private BigInteger id;
    
        @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
        @JoinColumn(name = "FOOID",nullable=false)
        @ForeignKey(name = "fk")     
        private Set<Bar> bar = new LinkedHashSet<Bar>(0);
    }
    
    
    @Entity
    @Table(name = "BAR")
    public class Bar implements java.io.Serializable
    {
        @Id
        @Column(name = "BARID")
        private BigInteger id;
    
        @ManyToOne(fetch=FetchType.LAZY)
        @JoinColumn(name = "FOOID", updatable = false, insertable = false, nullable=false)  
         private Foo foo;
    }