JPA规范单向OneToOne外部PK在存储库上引发错误

时间:2019-05-23 08:10:22

标签: hibernate spring-boot jpa

当尝试实现JPA 2.2规范中指定的OneToOne关联的示例时,我在存储库中出现了一个休眠错误,声称它应该是一个复合键,尽管不是。

我知道@MapsId有某种解决方案,但希望尽可能使用jpa spec解决方案。

@Entity
public class Parent implements Serializable {

    private static final long serialVersionUID = 3659483897253805915L;

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

    private String name;

    Parent() {} //jpa

    //getters/setters
}


@Entity
public class Child implements Serializable {

    private static final long serialVersionUID = 6245572225910874612L;

    @Id
    @OneToOne
    @JoinColumn( name = "parent_id" )
    private Parent parent;

    private String name;

    Child() {} //jpa

    //getters/setters
}
public interface ChildRepository extends JpaRepository<Child, Parent> {}

哪个会引发错误:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'childRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: This class [class com.sample.onetoone.Child] does not define an IdClass
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1778) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:593) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$76/1992476840.getObject(Unknown Source) ~[na:na]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:824) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:877) ~[spring-context-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549) ~[spring-context-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775) [spring-boot-2.1.5.RELEASE.jar:2.1.5.RELEASE]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) [spring-boot-2.1.5.RELEASE.jar:2.1.5.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:316) [spring-boot-2.1.5.RELEASE.jar:2.1.5.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260) [spring-boot-2.1.5.RELEASE.jar:2.1.5.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248) [spring-boot-2.1.5.RELEASE.jar:2.1.5.RELEASE]
    at com.sample.onetoone.SpringOnetooneApplication.main(SpringOnetooneApplication.java:10) [classes/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_25]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_25]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_25]
    at java.lang.reflect.Method.invoke(Method.java:483) ~[na:1.8.0_25]
    at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) [spring-boot-devtools-2.1.5.RELEASE.jar:2.1.5.RELEASE]

Caused by: java.lang.IllegalArgumentException: This class [class com.sample.onetoone.Child] does not define an IdClass
    at org.hibernate.metamodel.internal.AbstractIdentifiableType.getIdClassAttributes(AbstractIdentifiableType.java:183) ~[hibernate-core-5.3.10.Final.jar:5.3.10.Final]
    at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation$IdMetadata.<init>(JpaMetamodelEntityInformation.java:259) ~[spring-data-jpa-2.1.8.RELEASE.jar:2.1.8.RELEASE]
    at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation.<init>(JpaMetamodelEntityInformation.java:88) ~[spring-data-jpa-2.1.8.RELEASE.jar:2.1.8.RELEASE]
    at org.springframework.data.jpa.repository.support.JpaEntityInformationSupport.getEntityInformation(JpaEntityInformationSupport.java:66) ~[spring-data-jpa-2.1.8.RELEASE.jar:2.1.8.RELEASE]
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getEntityInformation(JpaRepositoryFactory.java:201) ~[spring-data-jpa-2.1.8.RELEASE.jar:2.1.8.RELEASE]
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:151) ~[spring-data-jpa-2.1.8.RELEASE.jar:2.1.8.RELEASE]
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:134) ~[spring-data-jpa-2.1.8.RELEASE.jar:2.1.8.RELEASE]
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:65) ~[spring-data-jpa-2.1.8.RELEASE.jar:2.1.8.RELEASE]
    at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:305) ~[spring-data-commons-2.1.8.RELEASE.jar:2.1.8.RELEASE]
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.lambda$afterPropertiesSet$5(RepositoryFactoryBeanSupport.java:297) ~[spring-data-commons-2.1.8.RELEASE.jar:2.1.8.RELEASE]
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport$$Lambda$387/121552774.get(Unknown Source) ~[na:na]
    at org.springframework.data.util.Lazy.getNullable(Lazy.java:211) ~[spring-data-commons-2.1.8.RELEASE.jar:2.1.8.RELEASE]
    at org.springframework.data.util.Lazy.get(Lazy.java:94) ~[spring-data-commons-2.1.8.RELEASE.jar:2.1.8.RELEASE]
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:300) ~[spring-data-commons-2.1.8.RELEASE.jar:2.1.8.RELEASE]
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:121) ~[spring-data-jpa-2.1.8.RELEASE.jar:2.1.8.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1837) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1774) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    ... 21 common frames omitted

将存储库ID更改为Long会引发相同的错误。

public interface ChildRepository extends JpaRepository<Child, Long> {}

JPA Spec 2.2,第38页:

https://github.com/javaee/jpa-spec/blob/master/jsr338-MR/JavaPersistence.pdf


pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.sample</groupId>
    <artifactId>spring-onetoone</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-onetoone</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <!-- WORKAROUND FOR POM.XML UNOWN ERROR IN LINE 1
        https://stackoverflow.com/questions/56189383/unknown-error-in-pom-xml-when-i-upgrade-from-spring-1-5-21-to-2-1-5
         -->
        <maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

1 个答案:

答案 0 :(得分:-1)

@Id注释用于标记主键。对于子类,您将父类标记为主键。相反,请尝试以下操作:

@Entity
public class Child implements Serializable {

    private static final long serialVersionUID = 6245572225910874612L;

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

    @OneToOne
    @JoinColumn( name = "parent_id" )
    private Parent parent;

    private String name;

    Child() {} //jpa

    //getters/setters
}