丑陋的Hibernate复合PK映射问题

时间:2012-05-16 13:35:57

标签: java hibernate

假设我有这些表格:

表A在两个字段上有一个复合主键:

  • 员工ID(字符串)
  • 交易ID(长)

表B还有一个复合主键,但在三个字段中:

  • 员工ID(字符串)
  • 交易ID(长)
  • 日期(日期)

在表B中,有一个名为" FK1" (为简单起见)。

由于表A中使用的复合id用于多个映射的hibernate类,因此我创建了一个可以重用的类:

@Embeddable
public class EmployeeTransactionComposite {

    private String employeeId;
    private Long transactionId;

}

因此,映射到表A的类如下所示:

public ClassA implements Serializable {

    private EmployeeTransactionComposite id;
    // rest of fields

    @EmbeddedId
    public EmployeeTransactionComposite getId() {
        return id;
    }
}

映射到表B的类如下所示:

public ClassB implements Serializable {

    private ClassBCompositeId id;
    // fields

    @EmbeddedId
    public getId() {
        return this.id;
    }

    @Embeddable
    public class ClassBCompositeId implements Serializable {

        private EmployeeTransactionComposite composite;
        private Date date;

        @ManyToOne
    @ForeignKey(name="FK1")
        public EmployeeTransactionComposite getComposite() {
            return composite;
        }

        @Column(name="THEDATE")
        public Date getDate() {
            return date;
        }
    }
}

显然,如果它有效,我就不会发布这个帖子。它会像这样的堆栈跟踪爆炸:

Caused By: java.lang.NullPointerException
at org.hibernate.cfg.Configuration.processFkSecondPassInOrder(Configuration.java:1419)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1359)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1728)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1779)
at org.springframework.orm.hibernate4.LocalSessionFactoryBuilder.buildSessionFactory(LocalSessionFactoryBuilder.java:189)
Truncated. see log file for complete stacktrace

这是传统架构的映射,因此无法进行更改。有人可以帮忙吗?

1 个答案:

答案 0 :(得分:2)

ManyToOne从不指向主键类,但始终指向实体。因此,此映射不正确:

@ManyToOne
@ForeignKey(name="FK1")
public EmployeeTransactionComposite getComposite() {
    return composite;
}

我建议不要在主键类中定义任何关联,只定义基本列(或包含基本列的嵌入列)。然后在实体本身中定义关联,并在此关联上使用@MapsId注释告诉Hibernate该关联使用与用于映射ID的列相同的列。

The documentation包含一个映射示例,它完全符合您的要求:

  

嵌入式ID本身可以包含关联的主键   实体。

@Entity
class Customer {
   @EmbeddedId CustomerId id;
   boolean preferredCustomer;

   @MapsId("userId")
   @JoinColumns({
      @JoinColumn(name="userfirstname_fk", referencedColumnName="firstName"),
      @JoinColumn(name="userlastname_fk", referencedColumnName="lastName")
   })
   @OneToOne User user;
}

@Embeddable
class CustomerId implements Serializable {
   UserId userId;
   String customerNumber;

   //implements equals and hashCode
}

@Entity 
class User {
   @EmbeddedId UserId id;
   Integer age;
}

@Embeddable
class UserId implements Serializable {
   String firstName;
   String lastName;

   //implements equals and hashCode
}