JPA 2 - 如何使用Spring Data JPA构建具有主键的实体,该主键也是外键?

时间:2017-06-27 17:10:27

标签: java hibernate jpa spring-data-jpa jpa-2.0

鉴于以下表格:

@Id

我如何指出CarDetails的{​​{1}}也是Car的外键?

我试过了:

@Entity
public class Car {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @ManyToOne
    @JoinColumn(name = "modelId", nullable = false)
    private Model model;

    //setters & getters
}

@Entity
public class CarDetails {

    @Id
    @OneToOne
    @JoinColumn(name = "carId", nullable = false)
    private Car car;

    private String description;

    //setters & getters
}

然而,我收到错误

org.hibernate.MappingException: Composite-id class must implement Serializable: com.example.CarDetails

实施Serializable后,我得到This class [class com.example.CarDetails] does not define an IdClass。但是在将@IdClass(Car.class)添加到CarDetails课程后,我仍然会收到错误消息。

更新

IdClass错误源自Spring: Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'carDetailsRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: This class [class com.example.CarDetails] does not define an IdClass

这是CarDetailsRepository:

public interface CarDetailsRepository extends JpaRepository<CarDetails, Car> {

}

以下是我的gradle构建文件的相关部分:

plugins {
    id 'java'
    id 'eclipse'
    id 'maven-publish'
    id 'io.spring.dependency-management' version '1.0.3.RELEASE'
}

repositories {
    mavenCentral()
    mavenLocal()
}


dependencies {

    pmd group: 'org.hibernate', name: 'hibernate-tools', version: '5.2.3.Final'
    pmd group: 'org.hibernate', name: 'hibernate-core', version: '5.2.10.Final'
    pmd group: 'org.hibernate.common', name: 'hibernate-commons-annotations', version: '5.0.1.Final'

    compile('org.springframework.boot:spring-boot-starter')
    compile('org.springframework.boot:spring-boot-starter-data-jpa')
    compile('org.hibernate:hibernate-validator:5.2.4.Final')
    compile('org.hibernate:hibernate-envers:5.2.10.Final')
    compile('org.hibernate:hibernate-core:5.2.10.Final')
    compile('org.hibernate.common:hibernate-commons-annotations:5.0.1.Final')
    runtime('net.sourceforge.jtds:jtds:1.3.1')
    runtime('com.microsoft.sqlserver:sqljdbc:4.2')
    runtime('javax.el:javax.el-api:2.2.4')
    testCompile('org.springframework.boot:spring-boot-starter-test')
}

dependencyManagement {
    imports { mavenBom('org.springframework.boot:spring-boot-dependencies:1.5.4.RELEASE') }
}

2 个答案:

答案 0 :(得分:1)

可能最好的方法是在carId实体中引用CarDetails两次 - 一次用于@Id,一次用于外键引用。您必须使用insertable=falseupdatable=false声明其中一个引用,以便JPA不会因为尝试在两个位置管理同一列而感到困惑:

@Entity
public class CarDetails {

    @Id
    @Column(name = "carId", insertable = false, updatable = false)
    private int carId; // don't bother with getter/setter since the `car` reference handles everything

    @OneToOne
    @JoinColumn(name = "carId", nullable = false)
    private Car car;

    private String description;

    //setters & getters
}

它看起来很奇怪,但它会起作用,它实际上是(最)首选的方法。

答案 1 :(得分:-1)

您可以尝试映射CarDetails,如下所示:

@Entity
public class CarDetails {

    @Id
    private int id;

    @MapsId
    @OneToOne
    @JoinColumn(name = "carId", nullable = false)
    private Car car;

    private String description;

    //setters & getters
}

请注意@MapsId注释。