简体   繁体   中英

JPA 2 - How to build entity that has Primary key that is also a foreign key using Spring Data JPA?

Given the following tables:

Car
int id PK
int modelId FK

CarDetails
int carId PK, FK to Car.id
varchar(50) description

How would I indicate that the @Id of CarDetails is also a foreign key to Car ?

I've tried:

@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
}

However, I get the error

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

After implementing Serializable I get This class [class com.example.CarDetails] does not define an IdClass . But I still get the error after adding @IdClass(Car.class) to the CarDetails class.

UPDATE

The IdClass error originates from 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 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

Here's the CarDetailsRepository:

public interface CarDetailsRepository extends JpaRepository<CarDetails, Car> {

}

Here are the relevant parts of my gradle build file:

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') }
}

Probably the best way is to reference carId twice in your CarDetails entity--once for the @Id and once for the foreign key reference. You must declare one of these references with insertable=false and updatable=false so that JPA doesn't get confused trying to manage the same column in two spots:

@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
}

It looks odd, but it'll work and it's actually the (most) preferred method.

You might try mapping CarDetails like this:

@Entity
public class CarDetails {

    @Id
    private int id;

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

    private String description;

    //setters & getters
}

Note the @MapsId annotation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM